diff --git a/src/java/io/bazel/rulesscala/scalac/scala_2/ScalacInvoker.java b/src/java/io/bazel/rulesscala/scalac/scala_2/ScalacInvoker.java index 4f1e17501..3b6fd319e 100644 --- a/src/java/io/bazel/rulesscala/scalac/scala_2/ScalacInvoker.java +++ b/src/java/io/bazel/rulesscala/scalac/scala_2/ScalacInvoker.java @@ -11,14 +11,14 @@ //Invokes Scala 2 compiler class ScalacInvoker{ - + public static ScalacInvokerResults invokeCompiler(CompileOptions ops, String[] compilerArgs) throws IOException, Exception{ ReportableMainClass comp = new ReportableMainClass(ops); ScalacInvokerResults results = new ScalacInvokerResults(); - + results.startTime = System.currentTimeMillis(); try { comp.process(compilerArgs); @@ -28,7 +28,15 @@ public static ScalacInvokerResults invokeCompiler(CompileOptions ops, String[] c } else if (ex.toString().contains("java.lang.StackOverflowError")) { throw new ScalacWorker.CompilationFailed("with StackOverflowError", ex); } else if (isMacroException(ex)) { - throw new ScalacWorker.CompilationFailed("during macro expansion", ex); + String reason; + + if (ex instanceof ClassFormatError) { + reason = "during macro expansion. You may have declared a target containing a macro as a `scala_library` target instead of a `scala_macro_library` target"; + } else { + reason = "during macro expansion"; + } + + throw new ScalacWorker.CompilationFailed(reason, ex); } else { throw ex; } @@ -37,7 +45,7 @@ public static ScalacInvokerResults invokeCompiler(CompileOptions ops, String[] c } results.stopTime = System.currentTimeMillis(); - + ConsoleReporter reporter = (ConsoleReporter) comp.getReporter(); if (reporter == null) { // Can happen only when `ReportableMainClass::newCompiler` was not invoked, diff --git a/test/macros/BUILD b/test/macros/BUILD new file mode 100644 index 000000000..b293ff61d --- /dev/null +++ b/test/macros/BUILD @@ -0,0 +1,24 @@ +load("//scala:scala.bzl", "scala_library", "scala_macro_library") + +scala_library( + name = "incorrect-macro", + srcs = ["IdentityMacro.scala"], +) + +scala_macro_library( + name = "correct-macro", + srcs = ["IdentityMacro.scala"], +) + +scala_library( + name = "incorrect-macro-user", + srcs = ["MacroUser.scala"], + tags = ["manual"], + deps = [":incorrect-macro"], +) + +scala_library( + name = "correct-macro-user", + srcs = ["MacroUser.scala"], + deps = [":correct-macro"], +) diff --git a/test/macros/IdentityMacro.scala b/test/macros/IdentityMacro.scala new file mode 100644 index 000000000..f2504485f --- /dev/null +++ b/test/macros/IdentityMacro.scala @@ -0,0 +1,9 @@ +package macros + +import scala.language.experimental.macros +import scala.reflect.macros.blackbox + +object IdentityMacro { + def identityMacro[A](value: A): A = macro identityMacroImpl[A] + def identityMacroImpl[A](context: blackbox.Context)(value: context.Expr[A]): context.Expr[A] = value +} diff --git a/test/macros/MacroUser.scala b/test/macros/MacroUser.scala new file mode 100644 index 000000000..f05d36eb2 --- /dev/null +++ b/test/macros/MacroUser.scala @@ -0,0 +1,5 @@ +package macros + +object Main { + def main(arguments: Array[String]): Unit = println(IdentityMacro.identityMacro("Hello, world!")) +} diff --git a/test/shell/test_macros.sh b/test/shell/test_macros.sh new file mode 100755 index 000000000..468c87bca --- /dev/null +++ b/test/shell/test_macros.sh @@ -0,0 +1,17 @@ +# shellcheck source=./test_runner.sh +dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +. "${dir}"/test_runner.sh +. "${dir}"/test_helper.sh +runner=$(get_test_runner "${1:-local}") + +incorrect_macro_user_does_not_build() { + (! bazel build //test/macros:incorrect-macro-user) |& + grep --fixed-strings 'Build failure during macro expansion. You may have declared a target containing a macro as a `scala_library` target instead of a `scala_macro_library` target' +} + +correct_macro_user_builds() { + bazel build //test/macros:correct-macro-user +} + +$runner incorrect_macro_user_does_not_build +$runner correct_macro_user_builds