diff --git a/sbt-bridge/src/xsbt/DelegatingReporter.java b/sbt-bridge/src/xsbt/DelegatingReporter.java index 536a08d31b96..4fe7cd40d95b 100644 --- a/sbt-bridge/src/xsbt/DelegatingReporter.java +++ b/sbt-bridge/src/xsbt/DelegatingReporter.java @@ -78,45 +78,59 @@ public void doReport(dotty.tools.dotc.reporting.Diagnostic dia, Context ctx) { SourcePosition pos = dia.pos(); SourceFile src = pos.source(); position = new Position() { - public Optional sourceFile() { - if (!src.exists()) return Optional.empty(); - else return Optional.ofNullable(src.file().file()); - } public Optional sourcePath() { - if (!src.exists()) return Optional.empty(); - else return Optional.ofNullable(src.file().path()); + if (!src.exists()) + return Optional.empty(); + + return Optional.ofNullable(src.file().path()); + } + public Optional sourceFile() { + if (!src.exists()) + return Optional.empty(); + + return Optional.ofNullable(src.file().file()); } public Optional line() { + if (!src.file().exists()) + return Optional.empty(); + int line = pos.line() + 1; - if (line == -1) return Optional.empty(); - else return Optional.of(line); + if (line == -1) + return Optional.empty(); + + return Optional.of(line); } public String lineContent() { + if (!src.file().exists()) + return ""; + String line = pos.lineContent(); if (line.endsWith("\r\n")) return line.substring(0, line.length() - 2); - else if (line.endsWith("\n") || line.endsWith("\u000c")) + if (line.endsWith("\n") || line.endsWith("\u000c")) return line.substring(0, line.length() - 1); - else - return line; + + return line; } public Optional offset() { return Optional.of(pos.point()); } public Optional pointer() { - if (!src.exists()) return Optional.empty(); - else return Optional.of(pos.point() - src.startOfLine(pos.point())); + if (!src.file().exists()) + return Optional.empty(); + + return Optional.of(pos.point() - src.startOfLine(pos.point())); } public Optional pointerSpace() { - if (!src.exists()) return Optional.empty(); - else { - String lineContent = this.lineContent(); - int pointer = this.pointer().get(); - StringBuilder result = new StringBuilder(); - for (int i = 0; i < pointer; i++) - result.append(lineContent.charAt(i) == '\t' ? '\t' : ' '); - return Optional.of(result.toString()); - } + if (!src.file().exists()) + return Optional.empty(); + + String lineContent = this.lineContent(); + int pointer = this.pointer().get(); + StringBuilder result = new StringBuilder(); + for (int i = 0; i < pointer; i++) + result.append(lineContent.charAt(i) == '\t' ? '\t' : ' '); + return Optional.of(result.toString()); } }; } else { diff --git a/sbt-dotty/sbt-test/compilerReporter/i7442/a/A.scala b/sbt-dotty/sbt-test/compilerReporter/i7442/a/A.scala new file mode 100644 index 000000000000..90dd22877b5d --- /dev/null +++ b/sbt-dotty/sbt-test/compilerReporter/i7442/a/A.scala @@ -0,0 +1,5 @@ +object A { + inline def a[T](x: T): T = inline x match { + case 1 => x + } +} diff --git a/sbt-dotty/sbt-test/compilerReporter/i7442/b/B.scala b/sbt-dotty/sbt-test/compilerReporter/i7442/b/B.scala new file mode 100644 index 000000000000..9ae301eb3260 --- /dev/null +++ b/sbt-dotty/sbt-test/compilerReporter/i7442/b/B.scala @@ -0,0 +1,4 @@ +object B { + def b = A.a(2) +} + diff --git a/sbt-dotty/sbt-test/compilerReporter/i7442/build.sbt b/sbt-dotty/sbt-test/compilerReporter/i7442/build.sbt new file mode 100644 index 000000000000..4e2a4a284394 --- /dev/null +++ b/sbt-dotty/sbt-test/compilerReporter/i7442/build.sbt @@ -0,0 +1,18 @@ +lazy val a = project.in(file("a")) + .settings( + scalaVersion := sys.props("plugin.scalaVersion") + ) +lazy val b = project.in(file("b")) + .settings(Reporter.checkSettings) + .settings( + scalaVersion := sys.props("plugin.scalaVersion"), + // Manually depend on `a` so that we can: + // 1. Compile `a` + // 2. Remove a source file in `a` + // 3. Compile `b` without forcing a recompilation of `a` + Compile / unmanagedJars := { + val s = Seq(Attributed.blank((a / Compile / packageBin / artifactPath).value)) + println("s: " + s) + s + } + ) diff --git a/sbt-dotty/sbt-test/compilerReporter/i7442/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/compilerReporter/i7442/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..1c6c00400f04 --- /dev/null +++ b/sbt-dotty/sbt-test/compilerReporter/i7442/project/DottyInjectedPlugin.scala @@ -0,0 +1,11 @@ +import sbt._ +import Keys._ + +object DottyInjectedPlugin extends AutoPlugin { + override def requires = plugins.JvmPlugin + override def trigger = allRequirements + + override val projectSettings = Seq( + scalaVersion := sys.props("plugin.scalaVersion"), + ) +} diff --git a/sbt-dotty/sbt-test/compilerReporter/i7442/project/Reporter.scala b/sbt-dotty/sbt-test/compilerReporter/i7442/project/Reporter.scala new file mode 100644 index 000000000000..10bb3a9f5a46 --- /dev/null +++ b/sbt-dotty/sbt-test/compilerReporter/i7442/project/Reporter.scala @@ -0,0 +1,42 @@ +import sbt._ +import Keys._ +import KeyRanks.DTask + +object Reporter { + import xsbti.{Reporter, Problem, Position, Severity} + + lazy val check = TaskKey[Unit]("check", "make sure compilation info are forwared to sbt") + + // compilerReporter is marked private in sbt + lazy val compilerReporter = TaskKey[xsbti.Reporter]("compilerReporter", "Experimental hook to listen (or send) compilation failure messages.", DTask) + + lazy val reporter = + new xsbti.Reporter { + private val buffer = collection.mutable.ArrayBuffer.empty[Problem] + def reset(): Unit = buffer.clear() + def hasErrors: Boolean = buffer.exists(_.severity == Severity.Error) + def hasWarnings: Boolean = buffer.exists(_.severity == Severity.Warn) + def printSummary(): Unit = println(problems.mkString(System.lineSeparator)) + def problems: Array[Problem] = buffer.toArray + def log(problem: Problem): Unit = buffer.append(problem) + def comment(pos: xsbti.Position, msg: String): Unit = () + } + + lazy val checkSettings = Seq( + compilerReporter in (Compile, compile) := reporter, + check := (compile in Compile).failure.map(_ => { + println(reporter.problems.toList) + assert(reporter.problems.length == 1) + val problem = reporter.problems.head + // Check that all methods on position can ba called without crashing + val pos = problem.position + println(pos.sourceFile) + println(pos.sourcePath) + println(pos.line) + println(pos.lineContent) + println(pos.offset) + println(pos.pointer) + println(pos.pointerSpace) + }).value + ) +} diff --git a/sbt-dotty/sbt-test/compilerReporter/i7442/project/plugins.sbt b/sbt-dotty/sbt-test/compilerReporter/i7442/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/compilerReporter/i7442/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/compilerReporter/i7442/test b/sbt-dotty/sbt-test/compilerReporter/i7442/test new file mode 100644 index 000000000000..7ccc4821ae91 --- /dev/null +++ b/sbt-dotty/sbt-test/compilerReporter/i7442/test @@ -0,0 +1,4 @@ +> a/packageBin +# Remove the source file to check if we later try to read it because it's in the @SourceFile annotation of the tasty file being inlined +$ delete a/A.scala +> b/check diff --git a/sbt-dotty/sbt-test/compilerReporter/simple/build.sbt b/sbt-dotty/sbt-test/compilerReporter/simple/build.sbt index 017846f5ed23..2ce5b3be9063 100644 --- a/sbt-dotty/sbt-test/compilerReporter/simple/build.sbt +++ b/sbt-dotty/sbt-test/compilerReporter/simple/build.sbt @@ -1 +1,3 @@ -Reporter.checkSettings \ No newline at end of file +scalaVersion := sys.props("plugin.scalaVersion") + +Reporter.checkSettings