JasonMond
JasonMond

Reputation: 1450

Force compile error for missing resources

Is it possible to make Scala (or Java called from Scala) check whether a resource is missing at compile time and throw a compile error if it's missing?

I'm working on a large Java/Scala hybrid project with many developers and I'm providing a Scala component that kicks in near the end of the system run. So if my component throws a missing resource runtime error, it's only discovered very late. I try to make sure that my resource is there so this doesn't happen. But several times already, the head engineer decided to shift things around, my resources changed paths, I wasn't aware so didn't change my code, then the code died at my component because of the missing resource. We're working on more centralized resource control, but in the meantime, would it be possible to make Scala throw a compile error over a missing resource? Mostly curiosity, but might implement if it turns out simple enough.

ETA: There's questions about build tools. It's not straightforward because everyone is using their own environment. Some are using eclipse, some netbeans, I'm using emacs+sbt. So even if I insert a check for sbt, it won't matter to other people who are using eclipse.

Upvotes: 1

Views: 859

Answers (3)

kiritsuku
kiritsuku

Reputation: 53348

In 2.10, it is definitely possible with help of a macro and string interpolation:

object CheckResource {

  import scala.reflect.macros.Context
  import scala.language.experimental.macros

  implicit class StringResource(sc: StringContext) {
    def res(): String = macro __res
  }

  def __res(c: Context)(): c.Expr[String] = {
    import c.universe._
    val str = c.prefix.tree match {
      case Apply(_, List(Apply(_, List(Literal(Constant(const: String)))))) =>
        if (!new java.io.File(const).exists())
          c.abort(c.enclosingPosition, s"file '$const' does not exist")
        else Literal(Constant(const))
    }
    c.Expr(str)
  }
}

scala> import CheckResource._
import CheckResource._

scala> val file = new java.io.File("test")
file: java.io.File = test

scala> file.createNewFile
res7: Boolean = true

scala> res"test"
res8: String = test

scala> file.delete
res9: Boolean = true

scala> res"test"
<console>:12: error: file 'test' does not exist
              res"test"
              ^

Upvotes: 3

Paul Butcher
Paul Butcher

Reputation: 10852

Actually, you probably could do this in Scala 2.10 with a macro - a macro being a piece of code that runs at compile time.

Whether it's a sensible thing to do is another question altogether (just because it's available at compile time doesn't necessarily mean that it will be at runtime, or vice-versa?). I would suggest that Richard's suggestion of doing something in your build tool is probably more sensible.

Upvotes: 2

Richard Sitze
Richard Sitze

Reputation: 8463

No, you can't induce the compiler to make this check for you.

Yes, ant/maven/buildr/sbt can do this check for you.

If you'd like more details, provide information on your build tools.

Upvotes: 0

Related Questions