diff --git a/compile/interface/src/main/scala/xsbt/API.scala b/compile/interface/src/main/scala/xsbt/API.scala index 8af37f6b0..e556590a5 100644 --- a/compile/interface/src/main/scala/xsbt/API.scala +++ b/compile/interface/src/main/scala/xsbt/API.scala @@ -22,16 +22,19 @@ final class API(val global: CallbackGlobal) extends Compat { @inline def debug(msg: => String) = if (settings.verbose.value) inform(msg) def newPhase(prev: Phase) = new ApiPhase(prev) - class ApiPhase(prev: Phase) extends Phase(prev) { + class ApiPhase(prev: Phase) extends GlobalPhase(prev) { override def description = "Extracts the public API from source files." def name = API.name - def run: Unit = + override def run(): Unit = { val start = System.currentTimeMillis - currentRun.units.foreach(processUnit) + super.run val stop = System.currentTimeMillis debug("API phase took : " + ((stop - start) / 1000.0) + " s") } + + def apply(unit: global.CompilationUnit): Unit = processUnit(unit) + def processUnit(unit: CompilationUnit) = if (!unit.isJava) processScalaUnit(unit) def processScalaUnit(unit: CompilationUnit): Unit = { val sourceFile = unit.source.file.file diff --git a/compile/interface/src/main/scala/xsbt/Analyzer.scala b/compile/interface/src/main/scala/xsbt/Analyzer.scala index 2bf01f630..adc26ff5e 100644 --- a/compile/interface/src/main/scala/xsbt/Analyzer.scala +++ b/compile/interface/src/main/scala/xsbt/Analyzer.scala @@ -19,11 +19,11 @@ final class Analyzer(val global: CallbackGlobal) extends LocateClassFile { import global._ def newPhase(prev: Phase): Phase = new AnalyzerPhase(prev) - private class AnalyzerPhase(prev: Phase) extends Phase(prev) { + private class AnalyzerPhase(prev: Phase) extends GlobalPhase(prev) { override def description = "Finds concrete instances of provided superclasses, and application entry points." def name = Analyzer.name - def run { - for (unit <- currentRun.units if !unit.isJava) { + def apply(unit: CompilationUnit) { + if (!unit.isJava) { val sourceFile = unit.source.file.file // build list of generated classes for (iclass <- unit.icode) { diff --git a/compile/interface/src/main/scala/xsbt/Dependency.scala b/compile/interface/src/main/scala/xsbt/Dependency.scala index 80d68c5ba..edcc3bd0c 100644 --- a/compile/interface/src/main/scala/xsbt/Dependency.scala +++ b/compile/interface/src/main/scala/xsbt/Dependency.scala @@ -33,11 +33,11 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile { import global._ def newPhase(prev: Phase): Phase = new DependencyPhase(prev) - private class DependencyPhase(prev: Phase) extends Phase(prev) { + private class DependencyPhase(prev: Phase) extends GlobalPhase(prev) { override def description = "Extracts dependency information" def name = Dependency.name - def run: Unit = { - for (unit <- currentRun.units if !unit.isJava) { + def apply(unit: CompilationUnit): Unit = { + if (!unit.isJava) { // build dependencies structure val sourceFile = unit.source.file.file if (global.callback.nameHashing) { diff --git a/sbt/src/sbt-test/api/source-path/build.sbt b/sbt/src/sbt-test/api/source-path/build.sbt new file mode 100644 index 000000000..58e2a083c --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/build.sbt @@ -0,0 +1,5 @@ +scalaVersion := "2.11.7" + +scalacOptions in Compile ++= "-sourcepath" :: (baseDirectory.value / "srcpath").toString :: Nil + + diff --git a/sbt/src/sbt-test/api/source-path/src/main/scala/test.scala b/sbt/src/sbt-test/api/source-path/src/main/scala/test.scala new file mode 100644 index 000000000..18ca50b84 --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/src/main/scala/test.scala @@ -0,0 +1,18 @@ + +object Test { + // When the refchecks compiler phase checks if Tuple2 has the + // @deprecated annotation, it forces the info for the + // `@deprecatedInheritance` annotation (the only annotation on + // class Tuple2. + // + // Because we are compiling with `-sourcpath` that contains a + // source file for `deprecatedInheritance`, this triggers a + // `compileLate` of that file (which basically runs all previous + // compiler phases on that file.) + // + // `compileLate` assumes that all of the phases are subclasses + // of `GlobalPhase`, rather than just `Phase`. This triggers a + // `ClassCastException` when it encounters SBT's custom + // API phase. + new Tuple2("", "") +} diff --git a/sbt/src/sbt-test/api/source-path/srcpath/scala/deprecatedInheritance.scala b/sbt/src/sbt-test/api/source-path/srcpath/scala/deprecatedInheritance.scala new file mode 100644 index 000000000..8f49314ca --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/srcpath/scala/deprecatedInheritance.scala @@ -0,0 +1,4 @@ +package scala + +private[scala] // for now, this needs to be generalized to communicate other modifier deltas +class deprecatedInheritance(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation diff --git a/sbt/src/sbt-test/api/source-path/test b/sbt/src/sbt-test/api/source-path/test new file mode 100644 index 000000000..5df2af1f3 --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/test @@ -0,0 +1 @@ +> compile