From 6aafb6912c2d9f68ed63e8c0557c0236b37edce0 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 6 Jun 2017 11:33:00 +0200 Subject: [PATCH 001/101] sbt 1.0.0-M6 --- build.sbt | 1 - project/Build.scala | 24 ++---------------------- project/build.properties | 2 +- project/scripted.sbt | 2 +- 4 files changed, 4 insertions(+), 25 deletions(-) diff --git a/build.sbt b/build.sbt index 93e194a97d37..9fbaee50a7f4 100644 --- a/build.sbt +++ b/build.sbt @@ -15,7 +15,6 @@ val `dotty-library-optimised` = Build.`dotty-library-optimised` val `dotty-sbt-bridge` = Build.`dotty-sbt-bridge` val `dotty-sbt-bridge-bootstrapped` = Build.`dotty-sbt-bridge-bootstrapped` val `dotty-language-server` = Build.`dotty-language-server` -val sjsSandbox = Build.sjsSandbox val `dotty-bench` = Build.`dotty-bench` val `dotty-bench-bootstrapped` = Build.`dotty-bench-bootstrapped` val `dotty-bench-optimised` = Build.`dotty-bench-optimised` diff --git a/project/Build.scala b/project/Build.scala index 0e28abc47f51..2abe1fe2e992 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -7,18 +7,12 @@ import java.nio.file.{ Files, FileSystemException } import java.util.Calendar import scala.reflect.io.Path -import sbtassembly.AssemblyKeys.assembly -import xerial.sbt.Pack._ import sbt.Package.ManifestAttributes -import com.typesafe.sbteclipse.plugin.EclipsePlugin._ - import dotty.tools.sbtplugin.DottyPlugin.autoImport._ import dotty.tools.sbtplugin.DottyIDEPlugin.{ prepareCommand, runProcess } import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._ -import org.scalajs.sbtplugin.ScalaJSPlugin -import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._ import pl.project13.scala.sbt.JmhPlugin import JmhPlugin.JmhKeys.Jmh @@ -151,7 +145,6 @@ object Build { // Settings used when compiling dotty with a non-bootstrapped dotty lazy val commonBootstrappedSettings = commonSettings ++ Seq( - EclipseKeys.skipProject := true, version := dottyVersion, scalaVersion := dottyNonBootstrappedVersion, @@ -285,8 +278,6 @@ object Build { crossPaths := false, // Do not depend on the Scala library autoScalaLibrary := false, - // Let the sbt eclipse plugin know that this is a Java-only project - EclipseKeys.projectFlavor := EclipseProjectFlavor.Java, //Remove javac invalid options in Compile doc javacOptions in (Compile, doc) --= Seq("-Xlint:unchecked", "-Xlint:deprecation") ) @@ -370,10 +361,6 @@ object Build { settings( resourceDirectory in Test := baseDirectory.value / "test" / "resources", - // specify main and ignore tests when assembling - mainClass in assembly := Some("dotty.tools.bot.Main"), - test in assembly := {}, - libraryDependencies ++= { val circeVersion = "0.7.0" val http4sVersion = "0.15.3" @@ -462,19 +449,12 @@ object Build { Seq(file) }.taskValue, - // include sources in eclipse (downloads source code for all dependencies) - //http://stackoverflow.com/questions/10472840/how-to-attach-sources-to-sbt-managed-dependencies-in-scala-ide#answer-11683728 - com.typesafe.sbteclipse.plugin.EclipsePlugin.EclipseKeys.withSource := true, - // get libraries onboard - libraryDependencies ++= Seq("com.typesafe.sbt" % "sbt-interface" % sbtVersion.value, + libraryDependencies ++= Seq("org.scala-sbt" % "compiler-interface" % sbtVersion.value, ("org.scala-lang.modules" %% "scala-xml" % "1.0.6").withDottyCompat(), "com.novocode" % "junit-interface" % "0.11" % "test", "org.scala-lang" % "scala-library" % scalacVersion % "test"), - // enable improved incremental compilation algorithm - incOptions := incOptions.value.withNameHashing(true), - // For convenience, change the baseDirectory when running the compiler baseDirectory in (Compile, run) := baseDirectory.value / "..", // .. but not when running test @@ -721,7 +701,7 @@ object Build { description := "sbt compiler bridge for Dotty", resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api libraryDependencies ++= Seq( - "com.typesafe.sbt" % "sbt-interface" % sbtVersion.value, + "org.scala-sbt" % "compiler-interface" % "1.0.0-X16", "org.scala-sbt" % "api" % sbtVersion.value % "test", ("org.specs2" %% "specs2-core" % "3.9.1" % "test").withDottyCompat(), ("org.specs2" %% "specs2-junit" % "3.9.1" % "test").withDottyCompat() diff --git a/project/build.properties b/project/build.properties index 64317fdae59f..cd66fd542cf2 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.15 +sbt.version=1.0.0-M6 diff --git a/project/scripted.sbt b/project/scripted.sbt index 76fdf267ff0d..a7d7ecccf2a9 100644 --- a/project/scripted.sbt +++ b/project/scripted.sbt @@ -1,2 +1,2 @@ // Used by the subproject dotty-bridge -libraryDependencies += "org.scala-sbt" % "scripted-plugin" % sbtVersion.value +libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value From 4ce83b8d41cc898e6f6d100e7f89645e1d7a0e5b Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 6 Jun 2017 14:28:30 +0200 Subject: [PATCH 002/101] Upgrade to sbt 1.0.0-M6 --- build.sbt | 6 +- project/Build.scala | 65 +++++---- project/inject-sbt-dotty.sbt | 5 +- project/scripted.sbt | 4 +- .../dotty/tools/sbtplugin/DottyPlugin.scala | 127 +++++++++++------- 5 files changed, 126 insertions(+), 81 deletions(-) diff --git a/build.sbt b/build.sbt index 9fbaee50a7f4..b547156c2d76 100644 --- a/build.sbt +++ b/build.sbt @@ -22,9 +22,9 @@ val `scala-library` = Build.`scala-library` val `scala-compiler` = Build.`scala-compiler` val `scala-reflect` = Build.`scala-reflect` val scalap = Build.scalap -val dist = Build.dist -val `dist-bootstrapped` = Build.`dist-bootstrapped` -val `dist-optimised` = Build.`dist-optimised` +// val dist = Build.dist +// val `dist-bootstrapped` = Build.`dist-bootstrapped` +// val `dist-optimised` = Build.`dist-optimised` val `sbt-dotty` = Build.`sbt-dotty` val `vscode-dotty` = Build.`vscode-dotty` diff --git a/project/Build.scala b/project/Build.scala index 2abe1fe2e992..2210837300ee 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -10,6 +10,7 @@ import scala.reflect.io.Path import sbt.Package.ManifestAttributes +// import sbt.ScriptedPlugin.autoImport._ import dotty.tools.sbtplugin.DottyPlugin.autoImport._ import dotty.tools.sbtplugin.DottyIDEPlugin.{ prepareCommand, runProcess } import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._ @@ -128,7 +129,7 @@ object Build { resourceDirectory in Test := baseDirectory.value / "test-resources", // Prevent sbt from rewriting our dependencies - ivyScala ~= (_ map (_ copy (overrideScalaVersion = false))) + ivyScala ~= (_.map(_.withOverrideScalaVersion(false))) ) // Settings used for projects compiled only with Scala 2 @@ -150,8 +151,8 @@ object Build { // Avoid having to run `dotty-sbt-bridge/publishLocal` before compiling a bootstrapped project scalaCompilerBridgeSource := - (dottyOrganization %% "dotty-sbt-bridge" % dottyVersion % Configurations.Component.name) - .artifacts(Artifact.sources("dotty-sbt-bridge").copy(url = + (dottyOrganization %% "dotty-sbt-bridge" % "NOT_PUBLISHED" % Configurations.Component.name) + .artifacts(Artifact.sources("dotty-sbt-bridge").withUrl( // We cannot use the `packageSrc` task because a setting cannot depend // on a task. Instead, we make `compile` below depend on the bridge `packageSrc` Some((artifactPath in (`dotty-sbt-bridge`, Compile, packageSrc)).value.toURI.toURL))), @@ -165,7 +166,7 @@ object Build { // contain `scalaInstance.value.libraryJar` which in our case is the // non-bootstrapped dotty-library that will then take priority over // the bootstrapped dotty-library on the classpath or sourcepath. - classpathOptions ~= (_.copy(autoBoot = false)), + classpathOptions ~= (_.withAutoBoot(false)), // We still need a Scala bootclasspath equal to the JVM bootclasspath, // otherwise sbt 0.13 incremental compilation breaks (https://github.com/sbt/sbt/issues/3142) scalacOptions ++= Seq("-bootclasspath", sys.props("sun.boot.class.path")), @@ -187,9 +188,9 @@ object Build { libraryDependencies ++= { if (bootstrapFromPublishedJars.value) Seq( - dottyOrganization %% "dotty-library" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name, - dottyOrganization %% "dotty-compiler" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name - ).map(_.withDottyCompat()) + dottyOrganization % "dotty-library_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name, + dottyOrganization % "dotty-compiler_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name + )//.map(_.withDottyCompat()) else Seq() }, @@ -197,25 +198,29 @@ object Build { // Compile using the non-bootstrapped and non-published dotty managedScalaInstance := false, scalaInstance := { + val updateResult = update.value val (libraryJar, compilerJar) = if (bootstrapFromPublishedJars.value) { - val jars = update.value.select( + val jars = updateResult.select( configuration = configurationFilter(Configurations.ScalaTool.name), + module = moduleFilter(), artifact = artifactFilter(extension = "jar") ) (jars.find(_.getName.startsWith("dotty-library_2.12")).get, jars.find(_.getName.startsWith("dotty-compiler_2.12")).get) } else - ((packageBin in (`dotty-library`, Compile)).value, - (packageBin in (`dotty-compiler`, Compile)).value) + ((packageBin in (`dotty-library`, Compile)).value: @sbtUnchecked, + (packageBin in (`dotty-compiler`, Compile)).value: @sbtUnchecked) // All compiler dependencies except the library val otherDependencies = (dependencyClasspath in (`dotty-compiler`, Compile)).value .filterNot(_.get(artifact.key).exists(_.name == "dotty-library")) .map(_.data) - val loader = state.value.classLoaderCache(libraryJar :: compilerJar :: otherDependencies.toList) - new ScalaInstance(scalaVersion.value, loader, libraryJar, compilerJar, otherDependencies, None) + val allJars = libraryJar :: compilerJar :: otherDependencies.toList + val classLoader = state.value.classLoaderCache(allJars) + new sbt.internal.inc.ScalaInstance(scalaVersion.value, + classLoader, libraryJar, compilerJar, allJars.toArray, None) } ) @@ -450,8 +455,8 @@ object Build { }.taskValue, // get libraries onboard - libraryDependencies ++= Seq("org.scala-sbt" % "compiler-interface" % sbtVersion.value, - ("org.scala-lang.modules" %% "scala-xml" % "1.0.6").withDottyCompat(), + libraryDependencies ++= Seq("org.scala-sbt" % "compiler-interface" % "1.0.0-X16", + ("org.scala-lang.modules" % "scala-xml_2.12" % "1.0.6"), "com.novocode" % "junit-interface" % "0.11" % "test", "org.scala-lang" % "scala-library" % scalacVersion % "test"), @@ -482,7 +487,6 @@ object Build { // Override run to be able to run compiled classfiles dotr := { val args: Seq[String] = spaceDelimited("").parsed - val java: String = Process("which" :: "java" :: Nil).!! val attList = (dependencyClasspath in Runtime).value val _ = packageAll.value val scalaLib = attList @@ -490,13 +494,18 @@ object Build { .find(_.contains("scala-library")) .toList.mkString(":") - if (java == "") - println("Couldn't find java executable on path, please install java to a default location") - else if (scalaLib == "") { + if (scalaLib == "") { println("Couldn't find scala-library on classpath, please run using script in bin dir instead") } else { val dottyLib = packageAll.value("dotty-library") - s"""$java -classpath .:$dottyLib:$scalaLib ${args.mkString(" ")}""".! + val exitCode = new java.lang.ProcessBuilder("java", "-classpath", s""".:$dottyLib:$scalaLib ${args.mkString(" ")}""") + .inheritIO() + .start() + .waitFor() + if (exitCode != 0) + throw new FeedbackProvidedException { + override def toString = "dotr failed" + } } }, run := Def.inputTaskDyn { @@ -702,9 +711,9 @@ object Build { resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api libraryDependencies ++= Seq( "org.scala-sbt" % "compiler-interface" % "1.0.0-X16", - "org.scala-sbt" % "api" % sbtVersion.value % "test", - ("org.specs2" %% "specs2-core" % "3.9.1" % "test").withDottyCompat(), - ("org.specs2" %% "specs2-junit" % "3.9.1" % "test").withDottyCompat() + "org.scala-sbt" % "zinc-apiinfo_2.12" % "1.0.0-X16" % "test", + ("org.specs2" %% "specs2-core" % "3.9.1" % "test"),//.withDottyCompat() + ("org.specs2" %% "specs2-junit" % "3.9.1" % "test")//.withDottyCompat() ), // The sources should be published with crossPaths := false since they // need to be compiled by the project using the bridge. @@ -833,8 +842,13 @@ object Build { lazy val `sbt-dotty` = project.in(file("sbt-dotty")). settings(commonSettings). settings( + scalaVersion := "2.12.2", // Keep in sync with inject-sbt-dotty.sbt - libraryDependencies += Dependencies.`jackson-databind`, + libraryDependencies ++= Seq( + Dependencies.`jackson-databind`, + "org.scala-sbt" % "compiler-interface" % "1.0.0-X16", + // "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value + ), unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", @@ -873,7 +887,7 @@ object Build { val coursier = baseDirectory.value / "out/coursier" val packageJson = baseDirectory.value / "package.json" if (!coursier.exists || packageJson.lastModified > coursier.lastModified) - runProcess(Seq("npm", "run", "update-all"), wait = true, directory = baseDirectory.value) + runProcess(Seq("npm", "run", "update-all"), wait = true, directory = baseDirectory.value: @sbtUnchecked) val tsc = baseDirectory.value / "node_modules" / ".bin" / "tsc" runProcess(Seq(tsc.getAbsolutePath, "--pretty", "--project", baseDirectory.value.getAbsolutePath), wait = true) @@ -882,7 +896,7 @@ object Build { // (--extensionDevelopmentPath=...) runProcess(codeCommand.value ++ Seq("--install-extension", "daltonjorge.scala"), wait = true) - sbt.inc.Analysis.Empty + sbt.internal.inc.Analysis.Empty }, sbt.Keys.`package`:= { runProcess(Seq("vsce", "package"), wait = true, directory = baseDirectory.value) @@ -1161,5 +1175,4 @@ object Build { case BootstrappedOptimised => commonOptimisedSettings }) } - } diff --git a/project/inject-sbt-dotty.sbt b/project/inject-sbt-dotty.sbt index 5ccc77fc2783..d63d6da5d1d4 100644 --- a/project/inject-sbt-dotty.sbt +++ b/project/inject-sbt-dotty.sbt @@ -5,6 +5,9 @@ unmanagedSourceDirectories in Compile += baseDirectory.value / "../sbt-dotty/src" // Keep in sync with `sbt-dotty` config in Build.scala -libraryDependencies += Dependencies.`jackson-databind` +libraryDependencies ++= Seq( + Dependencies.`jackson-databind`, + "org.scala-sbt" % "compiler-interface" % "1.0.0-X16" +) unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config" diff --git a/project/scripted.sbt b/project/scripted.sbt index a7d7ecccf2a9..c3b5976d568e 100644 --- a/project/scripted.sbt +++ b/project/scripted.sbt @@ -1,2 +1,4 @@ // Used by the subproject dotty-bridge -libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value +// libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value +// val sbtV = sbtVersion.value +//addSbtPlugin("org.scala-sbt" %% "scripted-plugin" % "1.0.0-M6") diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index 04b87f8004a4..f413efb5520d 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -2,7 +2,9 @@ package dotty.tools.sbtplugin import sbt._ import sbt.Keys._ -import sbt.inc.{ ClassfileManager, IncOptions } +// import sbt.inc.{ ClassfileManager, IncOptions } +import xsbti.compile._ +import java.util.Optional object DottyPlugin extends AutoPlugin { object autoImport { @@ -49,44 +51,38 @@ object DottyPlugin extends AutoPlugin { nightly } - implicit class DottyCompatModuleID(moduleID: ModuleID) { - /** If this ModuleID cross-version is a Dotty version, replace it - * by the Scala 2.x version that the Dotty version is retro-compatible with, - * otherwise do nothing. - * - * This setting is useful when your build contains dependencies that have only - * been published with Scala 2.x, if you have: - * {{{ - * libraryDependencies += "a" %% "b" % "c" - * }}} - * you can replace it by: - * {{{ - * libraryDependencies += ("a" %% "b" % "c").withDottyCompat() - * }}} - * This will have no effect when compiling with Scala 2.x, but when compiling - * with Dotty this will change the cross-version to a Scala 2.x one. This - * works because Dotty is currently retro-compatible with Scala 2.x. - * - * NOTE: Dotty's retro-compatibility with Scala 2.x will be dropped before - * Dotty is released, you should not rely on it. - */ - def withDottyCompat(): ModuleID = - moduleID.crossVersion match { - case _: CrossVersion.Binary => - moduleID.cross(CrossVersion.binaryMapped { version => - CrossVersion.partialVersion(version) match { - case Some((0, minor)) => - // Dotty v0.4 or greater is compatible with 2.12.x - if (minor >= 4) "2.12" - else "2.11" - case _ => - version - } - }) - case _ => - moduleID - } - } + // implicit class DottyCompatModuleID(moduleID: ModuleID) { + // /** If this ModuleID cross-version is a Dotty version, replace it + // * by the Scala 2.x version that the Dotty version is retro-compatible with, + // * otherwise do nothing. + // * + // * This setting is useful when your build contains dependencies that have only + // * been published with Scala 2.x, if you have: + // * {{{ + // * libraryDependencies += "a" %% "b" % "c" + // * }}} + // * you can replace it by: + // * {{{ + // * libraryDependencies += ("a" %% "b" % "c").withDottyCompat() + // * }}} + // * This will have no effect when compiling with Scala 2.x, but when compiling + // * with Dotty this will change the cross-version to a Scala 2.x one. This + // * works because Dotty is currently retro-compatible with Scala 2.x. + // * + // * NOTE: Dotty's retro-compatibility with Scala 2.x will be dropped before + // * Dotty is released, you should not rely on it. + // */ + // def withDottyCompat(): ModuleID = + // moduleID.crossVersion match { + // case _: librarymanagement.Binary => + // moduleID.cross(CrossVersion.binaryMapped { + // case version if version.startsWith("0.") => "2.11" + // case version => version + // }) + // case _ => + // moduleID + // } + // } } import autoImport._ @@ -108,6 +104,27 @@ object DottyPlugin extends AutoPlugin { } } + // Copy-pasted from sbt where it's private + private case class WrappedClassFileManager(internal: ClassFileManager, + external: Option[ClassFileManager]) + extends ClassFileManager { + + override def delete(classes: Array[File]): Unit = { + external.foreach(_.delete(classes)) + internal.delete(classes) + } + + override def complete(success: Boolean): Unit = { + external.foreach(_.complete(success)) + internal.complete(success) + } + + override def generated(classes: Array[File]): Unit = { + external.foreach(_.generated(classes)) + internal.generated(classes) + } + } + /** Patches the IncOptions so that .tasty and .hasTasty files are pruned as needed. * * This code is adapted from `scalaJSPatchIncOptions` in Scala.js, which needs @@ -119,25 +136,34 @@ object DottyPlugin extends AutoPlugin { * corresponding .tasty or .hasTasty file is also deleted. */ def dottyPatchIncOptions(incOptions: IncOptions): IncOptions = { - val inheritedNewClassfileManager = incOptions.newClassfileManager - val newClassfileManager = () => new ClassfileManager { - private[this] val inherited = inheritedNewClassfileManager() + val inheritedNewClassFileManager = ClassFileManagerUtil.getDefaultClassFileManager(incOptions) + val tastyFileManager = new ClassFileManager { + private[this] val inherited = inheritedNewClassFileManager - def delete(classes: Iterable[File]): Unit = { + def delete(classes: Array[File]): Unit = { val tastySuffixes = List(".tasty", ".hasTasty") inherited.delete(classes flatMap { classFile => - val dottyFiles = if (classFile.getPath endsWith ".class") { + if (classFile.getPath endsWith ".class") { val prefix = classFile.getAbsolutePath.stripSuffix(".class") tastySuffixes.map(suffix => new File(prefix + suffix)).filter(_.exists) } else Nil - classFile :: dottyFiles }) } - def generated(classes: Iterable[File]): Unit = inherited.generated(classes) - def complete(success: Boolean): Unit = inherited.complete(success) + def generated(classes: Array[File]): Unit = {} + def complete(success: Boolean): Unit = {} + } + val inheritedHooks = incOptions.externalHooks + val hooks = new ExternalHooks { + override def externalClassFileManager() = Option(inheritedHooks.externalClassFileManager.orElse(null)) match { + case Some(prevManager) => + Optional.of(WrappedClassFileManager(prevManager, Some(tastyFileManager))) + case None => + Optional.of(tastyFileManager) + } + override def externalLookup() = inheritedHooks.externalLookup() } - incOptions.withNewClassfileManager(newClassfileManager) + incOptions.withExternalHooks(hooks) } override def projectSettings: Seq[Setting[_]] = { @@ -161,10 +187,11 @@ object DottyPlugin extends AutoPlugin { }, incOptions in Compile := { + val inc = (incOptions in Compile).value if (isDotty.value) - dottyPatchIncOptions((incOptions in Compile).value) + dottyPatchIncOptions(inc) else - (incOptions in Compile).value + inc }, scalaBinaryVersion := { From c91171da3abf2d95b5aee318ed6de5f46a4a64ac Mon Sep 17 00:00:00 2001 From: Thierry Treyer Date: Wed, 10 May 2017 17:51:12 +0200 Subject: [PATCH 003/101] Fix sbt bridge First draft at fixing the sbt bridge to match the Zinc 1.0 API. --- .../dotty/tools/backend/jvm/GenBCode.scala | 4 +- .../tools/dotc/core/SymDenotations.scala | 9 ++ .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 121 ++++++++++-------- .../tools/dotc/sbt/ExtractDependencies.scala | 38 ++++-- .../src/dotty/tools/dotc/sbt/ShowAPI.scala | 26 ++-- sbt-bridge/src/xsbt/CompilerInterface.scala | 3 +- sbt-bridge/src/xsbt/DelegatingReporter.scala | 33 ++--- sbt-bridge/src/xsbt/ScaladocInterface.scala | 13 +- 8 files changed, 144 insertions(+), 103 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index ad84bde680d1..93a273af1e9b 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -407,7 +407,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter if (ctx.compilerCallback != null) ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(outFile), className) if (ctx.sbtCallback != null) - ctx.sbtCallback.generatedClass(sourceFile.jfile.orElse(null), outFile.file, className) + // ctx.sbtCallback.generatedClass(sourceFile.jfile.orElse(null), outFile.file, className) + // TODO: Check + ctx.sbtCallback.generatedNonLocalClass(sourceFile.jfile.orElse(null), outFile.file, jclassName, className) } catch { case e: FileConflictException => diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 145913261053..8f53fa063740 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -11,6 +11,7 @@ import collection.BitSet import dotty.tools.io.AbstractFile import Decorators.SymbolIteratorDecorator import ast._ +import ast.Trees._ import annotation.tailrec import CheckRealizable._ import util.SimpleIdentityMap @@ -334,6 +335,14 @@ object SymDenotations { case Nil => Nil } + final def children(implicit ctx: Context): List[Symbol] = + this.annotations.filter(_.symbol == ctx.definitions.ChildAnnot).map { annot => + // refer to definition of Annotation.makeChild + annot.tree match { + case Apply(TypeApply(_, List(tpTree)), _) => tpTree.symbol + } + } + /** The denotation is completed: info is not a lazy type and attributes have defined values */ final def isCompleted: Boolean = !myInfo.isInstanceOf[LazyType] diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 532aef36b723..30401ab2a5c2 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -47,19 +47,19 @@ class ExtractAPI extends Phase { if ((ctx.sbtCallback != null || forceRun) && !unit.isJava) { val sourceFile = unit.source.file val apiTraverser = new ExtractAPICollector - val source = apiTraverser.apiSource(unit.tpdTree) + val sources = apiTraverser.apiSource(unit.tpdTree) if (dumpInc) { // Append to existing file that should have been created by ExtractDependencies val pw = new PrintWriter(Path(sourceFile.jpath).changeExtension("inc").toFile .bufferedWriter(append = true), true) try { - pw.println(DefaultShowAPI(source)) + sources.foreach(source => pw.println(DefaultShowAPI(source))) } finally pw.close() } if (ctx.sbtCallback != null) - ctx.sbtCallback.api(sourceFile.file, source) + sources.foreach(ctx.sbtCallback.api(sourceFile.file, _)) } } } @@ -113,7 +113,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder /** This cache is necessary for correctness, see the comment about inherited * members in `apiClassStructure` */ - private[this] val classLikeCache = new mutable.HashMap[ClassSymbol, api.ClassLike] + private[this] val classLikeCache = new mutable.HashMap[ClassSymbol, api.ClassLikeDef] /** This cache is optional, it avoids recomputing representations */ private[this] val typeCache = new mutable.HashMap[Type, api.Type] /** This cache is necessary to avoid unstable name hashing when `typeCache` is present, @@ -122,6 +122,8 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder */ private[this] val refinedTypeCache = new mutable.HashMap[(api.Type, api.Definition), api.Structure] + private[this] val allNonLocalClassesInSrc = new mutable.HashSet[xsbti.api.ClassLike] + private[this] object Constants { val emptyStringArray = Array[String]() val local = new api.ThisQualifier @@ -153,25 +155,25 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder /** Extract the API representation of a source file */ - def apiSource(tree: Tree): api.SourceAPI = { - val classes = new mutable.ListBuffer[api.ClassLike] + def apiSource(tree: Tree): Seq[api.ClassLike] = { def apiClasses(tree: Tree): Unit = tree match { case PackageDef(_, stats) => stats.foreach(apiClasses) case tree: TypeDef => - classes += apiClass(tree.symbol.asClass) + apiClass(tree.symbol.asClass) case _ => } apiClasses(tree) forceThunks() - new api.SourceAPI(Array(), classes.toArray) + + allNonLocalClassesInSrc.toSeq } - def apiClass(sym: ClassSymbol): api.ClassLike = + def apiClass(sym: ClassSymbol): api.ClassLikeDef = classLikeCache.getOrElseUpdate(sym, computeClass(sym)) - private def computeClass(sym: ClassSymbol): api.ClassLike = { + private def computeClass(sym: ClassSymbol): api.ClassLikeDef = { import xsbti.api.{DefinitionType => dt} val defType = if (sym.is(Trait)) dt.Trait @@ -184,14 +186,23 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val name = if (sym.is(ModuleClass)) sym.fullName.sourceModuleName else sym.fullName - val tparams = sym.typeParams.map(apiTypeParameter) + val tparams = sym.typeParams.map(apiTypeParameter).toArray val structure = apiClassStructure(sym) + val acc = apiAccess(sym) + val modifiers = apiModifiers(sym) + val anns = apiAnnotations(sym).toArray + // from SymDenotations.topLevelClass + val topLevel = (sym.isEffectiveRoot || (sym is PackageClass) || (sym.owner is PackageClass)) + val childrenOfSealedClass = sym.children.sorted(classFirstSort).map(c => apiType(c.info)).toArray + + val cl = new api.ClassLike( + name.toString, acc, modifiers, anns, defType, strict2lzy(selfType), strict2lzy(structure), Constants.emptyStringArray, + childrenOfSealedClass, topLevel, tparams) + + allNonLocalClassesInSrc += cl - new api.ClassLike( - defType, strict2lzy(selfType), strict2lzy(structure), Constants.emptyStringArray, - tparams.toArray, name.toString, apiAccess(sym), apiModifiers(sym), - apiAnnotations(sym).toArray) + new api.ClassLikeDef(name.toString, acc, modifiers, anns, tparams, defType); } private[this] val LegacyAppClass = ctx.requiredClass("dotty.runtime.LegacyApp") @@ -240,48 +251,48 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder info.baseClasses.tail.map(ref.baseType) } - def apiDefinitions(defs: List[Symbol]): List[api.Definition] = { - // The hash generated by sbt for definitions is supposed to be symmetric so - // we shouldn't have to sort them, but it actually isn't symmetric for - // definitions which are classes, therefore we need to sort classes to - // ensure a stable hash. - // Modules and classes come first and are sorted by name, all other - // definitions come later and are not sorted. - object classFirstSort extends Ordering[Symbol] { - override def compare(a: Symbol, b: Symbol) = { - val aIsClass = a.isClass - val bIsClass = b.isClass - if (aIsClass == bIsClass) { - if (aIsClass) { - if (a.is(Module) == b.is(Module)) - a.fullName.toString.compareTo(b.fullName.toString) - else if (a.is(Module)) - -1 - else - 1 - } else - 0 - } else if (aIsClass) - -1 - else - 1 - } + // The hash generated by sbt for definitions is supposed to be symmetric so + // we shouldn't have to sort them, but it actually isn't symmetric for + // definitions which are classes, therefore we need to sort classes to + // ensure a stable hash. + // Modules and classes come first and are sorted by name, all other + // definitions come later and are not sorted. + private object classFirstSort extends Ordering[Symbol] { + override def compare(a: Symbol, b: Symbol) = { + val aIsClass = a.isClass + val bIsClass = b.isClass + if (aIsClass == bIsClass) { + if (aIsClass) { + if (a.is(Module) == b.is(Module)) + a.fullName.toString.compareTo(b.fullName.toString) + else if (a.is(Module)) + -1 + else + 1 + } else + 0 + } else if (aIsClass) + -1 + else + 1 } + } + def apiDefinitions(defs: List[Symbol]): List[api.ClassDefinition] = { defs.sorted(classFirstSort).map(apiDefinition) } - def apiDefinition(sym: Symbol): api.Definition = { + def apiDefinition(sym: Symbol): api.ClassDefinition = { if (sym.isClass) { apiClass(sym.asClass) } else if (sym.isType) { apiTypeMember(sym.asType) } else if (sym.is(Mutable, butNot = Accessor)) { - new api.Var(apiType(sym.info), sym.name.toString, - apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray) + new api.Var(sym.name.toString, apiAccess(sym), apiModifiers(sym), + apiAnnotations(sym).toArray, apiType(sym.info)) } else if (sym.isStable) { - new api.Val(apiType(sym.info), sym.name.toString, - apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray) + new api.Val(sym.name.toString, apiAccess(sym), apiModifiers(sym), + apiAnnotations(sym).toArray, apiType(sym.info)) } else { apiDef(sym.asTerm) } @@ -324,8 +335,8 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val vparamss = paramLists(sym.info) val retTp = sym.info.finalResultType.widenExpr - new api.Def(vparamss.toArray, apiType(retTp), tparams.toArray, - sym.name.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray) + new api.Def(sym.name.toString, apiAccess(sym), apiModifiers(sym), + apiAnnotations(sym).toArray, tparams.toArray, vparamss.toArray, apiType(retTp)) } def apiTypeMember(sym: TypeSymbol): api.TypeMember = { @@ -337,10 +348,10 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val tpe = sym.info if (sym.isAliasType) - new api.TypeAlias(apiType(tpe.bounds.hi), typeParams, name, access, modifiers, as.toArray) + new api.TypeAlias(name, access, modifiers, as.toArray, typeParams, apiType(tpe.bounds.hi)) else { assert(sym.isAbstractType) - new api.TypeDeclaration(apiType(tpe.bounds.lo), apiType(tpe.bounds.hi), typeParams, name, access, modifiers, as.to) + new api.TypeDeclaration(name, access, modifiers, as.toArray, typeParams, apiType(tpe.bounds.lo), apiType(tpe.bounds.hi)) } } @@ -405,11 +416,11 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder def typeRefinement(name: String, tp: TypeBounds): api.TypeMember = tp match { case TypeAlias(alias) => - new api.TypeAlias(apiType(alias), - Array(), name, Constants.public, Constants.emptyModifiers, Array()) + new api.TypeAlias(name, + Constants.public, Constants.emptyModifiers, Array(), Array(), apiType(alias)) case TypeBounds(lo, hi) => - new api.TypeDeclaration(apiType(lo), apiType(hi), - Array(), name, Constants.public, Constants.emptyModifiers, Array()) + new api.TypeDeclaration(name, + Constants.public, Constants.emptyModifiers, Array(), Array(), apiType(lo), apiType(hi)) } val decl = rt.refinedInfo match { case rinfo: TypeBounds => @@ -441,7 +452,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // `apiFoo == apiBar` always imply `apiFoo eq apiBar`. This is what // `refinedTypeCache` is for. refinedTypeCache.getOrElseUpdate((parent, decl), { - val adecl: Array[api.Definition] = if (decl == null) Array() else Array(decl) + val adecl: Array[api.ClassDefinition] = if (decl == null) Array() else Array(decl) new api.Structure(strict2lzy(Array(parent)), strict2lzy(adecl), strict2lzy(Array())) }) case tp: RecType => diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 32b9827e8535..cdec3e4b3366 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -13,7 +13,7 @@ import java.io.File import java.util.{Arrays, Comparator} -import xsbti.DependencyContext +import xsbti.api.DependencyContext /** This phase sends information on classes' dependencies to sbt via callbacks. * @@ -68,8 +68,8 @@ class ExtractDependencies extends Phase { } if (ctx.sbtCallback != null) { - extractDeps.usedNames.foreach(name => - ctx.sbtCallback.usedName(sourceFile.file, name.toString)) + extractDeps.usedNames.foreach{ case (enclosingName, names) => + names.foreach(name => ctx.sbtCallback.usedName(enclosingName.toString, name.toString)) } extractDeps.topLevelDependencies.foreach(dep => recordDependency(sourceFile.file, dep, DependencyContext.DependencyByMemberRef)) extractDeps.topLevelInheritanceDependencies.foreach(dep => @@ -93,7 +93,7 @@ class ExtractDependencies extends Phase { def className(classSegments: List[String]) = classSegments.mkString(".").stripSuffix(".class") def binaryDependency(file: File, className: String) = - ctx.sbtCallback.binaryDependency(file, className, currentSourceFile, context) + ctx.sbtCallback.binaryDependency(file, className, currentClass.fullName.toString, currentSourceFile, context) depFile match { case ze: ZipArchive#Entry => @@ -112,7 +112,7 @@ class ExtractDependencies extends Phase { ctx.warning(s"sbt-deps: Ignoring dependency $depFile of class ${depFile.getClass}") } } else if (depFile.file != currentSourceFile) { - ctx.sbtCallback.sourceDependency(depFile.file, currentSourceFile, context) + ctx.sbtCallback.classDependency(dep.enclosingClass.fullName.toString, currentClass.fullName.toString, context) } } } @@ -129,14 +129,14 @@ class ExtractDependencies extends Phase { private class ExtractDependenciesCollector(implicit val ctx: Context) extends tpd.TreeTraverser { import tpd._ - private[this] val _usedNames = new mutable.HashSet[Name] + private[this] val _usedNames = new mutable.HashMap[Name, mutable.Set[Name]].withDefault(_ => new mutable.HashSet[Name]) private[this] val _topLevelDependencies = new mutable.HashSet[Symbol] private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[Symbol] /** The names used in this class, this does not include names which are only * defined and not referenced. */ - def usedNames: Set[Name] = _usedNames + def usedNames: collection.Map[Name, Set[Name]] = _usedNames /** The set of top-level classes that the compilation unit depends on * because it refers to these classes or something defined in them. @@ -149,15 +149,29 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp */ def topLevelInheritanceDependencies: Set[Symbol] = _topLevelInheritanceDependencies - private def addUsedName(name: Name) = - _usedNames += name + private def addUsedName(enclosingName: Name, name: Name) = + _usedNames(enclosingName) += name - private def addDependency(sym: Symbol): Unit = + private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { val tlClass = sym.topLevelClass if (tlClass.ne(NoSymbol)) // Some synthetic type aliases like AnyRef do not belong to any class _topLevelDependencies += sym.topLevelClass - addUsedName(sym.name) + addUsedName(nonLocalEnclosingClass(sym).fullName, sym.name) + } + + private def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = { + val owner = sym.maybeOwner + owner.isTerm || + owner.is(Trait) && isLocal(owner) || + sym.isConstructor && isLocal(owner) + } + + private def nonLocalEnclosingClass(sym: Symbol)(implicit ctx: Context): Symbol = + sym.enclosingClass match { + case NoSymbol => NoSymbol + case sym: Symbol if (isLocal(sym)) => sym + case sym: Symbol => nonLocalEnclosingClass(sym.owner) } private def ignoreDependency(sym: Symbol) = @@ -188,7 +202,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp case Thicket(Ident(name) :: Ident(rename) :: Nil) => addImported(name) if (rename ne nme.WILDCARD) - addUsedName(rename) + addUsedName(nonLocalEnclosingClass(ctx.owner).fullName, rename) case _ => } case Inlined(call, _, _) => diff --git a/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala index 0e6b19867950..35bdc8594066 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala @@ -18,17 +18,17 @@ object DefaultShowAPI { def apply(d: Definition) = ShowAPI.showDefinition(d)(defaultNesting) def apply(d: Type) = ShowAPI.showType(d)(defaultNesting) - def apply(a: SourceAPI) = ShowAPI.showApi(a)(defaultNesting) + def apply(a: ClassLike) = ShowAPI.showApi(a)(defaultNesting) } object ShowAPI { private lazy val numDecls = Try { java.lang.Integer.parseInt(sys.props.get("sbt.inc.apidiff.decls").get) } getOrElse 0 - private def truncateDecls(decls: Array[Definition]): Array[Definition] = if (numDecls <= 0) decls else decls.take(numDecls) + private def truncateDecls(decls: Array[ClassDefinition]): Array[ClassDefinition] = if (numDecls <= 0) decls else decls.take(numDecls) private def lines(ls: Seq[String]): String = ls.mkString("\n", "\n", "\n") - def showApi(a: SourceAPI)(implicit nesting: Int) = - a.packages.map(pkg => "package " + pkg.name).mkString("\n") + lines(truncateDecls(a.definitions).map(showDefinition)) + def showApi(c: ClassLike)(implicit nesting: Int) = + showDefinition(c) def showDefinition(d: Definition)(implicit nesting: Int): String = d match { case v: Val => showMonoDef(v, "val") + ": " + showType(v.tpe) @@ -36,7 +36,9 @@ object ShowAPI { case d: Def => showPolyDef(d, "def") + showValueParams(d.valueParameters) + ": " + showType(d.returnType) case ta: TypeAlias => showPolyDef(ta, "type") + " = " + showType(ta.tpe) case td: TypeDeclaration => showPolyDef(td, "type") + showBounds(td.lowerBound, td.upperBound) - case cl: ClassLike => showPolyDef(cl, showDefinitionType(cl.definitionType)) + " extends " + showTemplate(cl) + case cl: ClassLike => showMonoDef(d, showDefinitionType(cl.definitionType)) + + showTypeParameters(cl.typeParameters) + " extends " + showTemplate(cl) + case cl: ClassLikeDef => showPolyDef(cl, showDefinitionType(cl.definitionType)) } private def showTemplate(cl: ClassLike)(implicit nesting: Int) = @@ -61,14 +63,17 @@ object ShowAPI { case s: Structure => s.parents.map(showType).mkString(" with ") + ( if (nesting <= 0) "{ }" - else truncateDecls(s.declared).map(showNestedDefinition).mkString(" {", "\n", "}")) + else truncateDecls(s.declared).map(showNestedDefinition).mkString(" {", "\n", "}") + ) case e: Existential => showType(e.baseType) + ( if (nesting <= 0) " forSome { }" - else e.clause.map(t => "type " + showNestedTypeParameter(t)).mkString(" forSome { ", "; ", " }")) + else e.clause.map(t => "type " + showNestedTypeParameter(t)).mkString(" forSome { ", "; ", " }") + ) case p: Polymorphic => showType(p.baseType) + ( if (nesting <= 0) " [ ]" - else showNestedTypeParameters(p.parameters)) + else showNestedTypeParameters(p.parameters) + ) } private def showPath(p: Path): String = p.components.map(showPathComponent).mkString(".") @@ -104,9 +109,7 @@ object ShowAPI { private def showValueParams(ps: Seq[ParameterList])(implicit nesting: Int): String = ps.map(pl => pl.parameters.map(mp => - mp.name + ": " + showParameterModifier(showType(mp.tpe), mp.modifier) + (if (mp.hasDefault) "= ..." else "") - ).mkString(if (pl.isImplicit) "(implicit " else "(", ", ", ")") - ).mkString("") + mp.name + ": " + showParameterModifier(showType(mp.tpe), mp.modifier) + (if (mp.hasDefault) "= ..." else "")).mkString(if (pl.isImplicit) "(implicit " else "(", ", ", ")")).mkString("") private def showParameterModifier(base: String, pm: ParameterModifier): String = pm match { case ParameterModifier.Plain => base @@ -154,3 +157,4 @@ object ShowAPI { private def showNestedTypeParameters(tps: Seq[TypeParameter])(implicit nesting: Int) = showTypeParameters(tps)(nesting - 1) private def showNestedDefinition(d: Definition)(implicit nesting: Int) = showDefinition(d)(nesting - 1) } + diff --git a/sbt-bridge/src/xsbt/CompilerInterface.scala b/sbt-bridge/src/xsbt/CompilerInterface.scala index bf1488dad93b..b2418d70cd9d 100644 --- a/sbt-bridge/src/xsbt/CompilerInterface.scala +++ b/sbt-bridge/src/xsbt/CompilerInterface.scala @@ -3,8 +3,7 @@ */ package xsbt -import xsbti.{ AnalysisCallback, Logger, Problem, Reporter, Severity, DependencyContext } -import xsbti.api.SourceAPI +import xsbti.{ AnalysisCallback, Logger, Problem, Reporter, Severity } import xsbti.compile._ import Log.debug import java.io.File diff --git a/sbt-bridge/src/xsbt/DelegatingReporter.scala b/sbt-bridge/src/xsbt/DelegatingReporter.scala index ffc4792ecef0..0b096a2336e3 100644 --- a/sbt-bridge/src/xsbt/DelegatingReporter.scala +++ b/sbt-bridge/src/xsbt/DelegatingReporter.scala @@ -9,7 +9,8 @@ import reporting._ import reporting.diagnostic.MessageContainer import reporting.diagnostic.messages import core.Contexts._ -import xsbti.{Maybe, Position} +import xsbti.Position +import java.util.Optional final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter with UniqueMessagePositions @@ -32,13 +33,13 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter val pos = cont.pos val src = pos.source new Position { - val sourceFile: Maybe[java.io.File] = maybe(Option(src.file.file)) - val sourcePath: Maybe[String] = maybe(Option(src.file.path)) - val line: Maybe[Integer] = Maybe.just(pos.line) + val sourceFile: Optional[java.io.File] = maybe(Option(src.file.file)) + val sourcePath: Optional[String] = maybe(Option(src.file.path)) + val line: Optional[Integer] = Optional.of(pos.line) val lineContent: String = pos.lineContent.stripLineEnd - val offset: Maybe[Integer] = Maybe.just(pos.point) - val pointer: Maybe[Integer] = Maybe.just(pos.point - src.startOfLine(pos.point)) - val pointerSpace: Maybe[String] = Maybe.just( + val offset: Optional[Integer] = Optional.of(pos.point) + val pointer: Optional[Integer] = Optional.of(pos.point - src.startOfLine(pos.point)) + val pointerSpace: Optional[String] = Optional.of( ((lineContent: Seq[Char]).take(pointer.get).map { case '\t' => '\t'; case x => ' ' }).mkString ) } @@ -54,18 +55,18 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter delegate.log(position, sb.toString(), severity) } - private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match { - case None => Maybe.nothing[T] - case Some(s) => Maybe.just[T](s) + private[this] def maybe[T](opt: Option[T]): Optional[T] = opt match { + case None => Optional.empty[T] + case Some(s) => Optional.of[T](s) } private[this] val noPosition = new Position { - val line: Maybe[Integer] = Maybe.nothing[Integer] + val line: Optional[Integer] = Optional.empty[Integer] val lineContent: String = "" - val offset: Maybe[Integer] = Maybe.nothing[Integer] - val pointer: Maybe[Integer] = Maybe.nothing[Integer] - val pointerSpace: Maybe[String] = Maybe.nothing[String] - val sourceFile: Maybe[java.io.File] = Maybe.nothing[java.io.File] - val sourcePath: Maybe[String] = Maybe.nothing[String] + val offset: Optional[Integer] = Optional.empty[Integer] + val pointer: Optional[Integer] = Optional.empty[Integer] + val pointerSpace: Optional[String] = Optional.empty[String] + val sourceFile: Optional[java.io.File] = Optional.empty[java.io.File] + val sourcePath: Optional[String] = Optional.empty[String] } } diff --git a/sbt-bridge/src/xsbt/ScaladocInterface.scala b/sbt-bridge/src/xsbt/ScaladocInterface.scala index 1eae8374d28b..387b54e13673 100644 --- a/sbt-bridge/src/xsbt/ScaladocInterface.scala +++ b/sbt-bridge/src/xsbt/ScaladocInterface.scala @@ -5,6 +5,7 @@ package xsbt import xsbti.{ Logger, Severity } import java.net.URL +import java.util.Optional class ScaladocInterface { def run(args: Array[String], log: Logger, delegate: xsbti.Reporter) = @@ -20,13 +21,13 @@ class DottydocRunner(args: Array[String], log: Logger, delegate: xsbti.Reporter) ) private[this] val NoPosition = new xsbti.Position { - val line = xsbti.Maybe.nothing[Integer] + val line = Optional.empty[Integer] val lineContent = "" - val offset = xsbti.Maybe.nothing[Integer] - val sourcePath = xsbti.Maybe.nothing[String] - val sourceFile = xsbti.Maybe.nothing[java.io.File] - val pointer = xsbti.Maybe.nothing[Integer] - val pointerSpace = xsbti.Maybe.nothing[String] + val offset = Optional.empty[Integer] + val sourcePath = Optional.empty[String] + val sourceFile = Optional.empty[java.io.File] + val pointer = Optional.empty[Integer] + val pointerSpace = Optional.empty[String] } private def getStringSetting(name: String): Option[String] = From 024f5fbc1346de015b7a9030cbf50848d791c7ae Mon Sep 17 00:00:00 2001 From: Thierry Treyer Date: Wed, 10 May 2017 18:14:09 +0200 Subject: [PATCH 004/101] Add method SymDenotation.isTopLevelClass --- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 5 ++++- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 8f53fa063740..386968e59943 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -928,13 +928,16 @@ object SymDenotations { */ final def topLevelClass(implicit ctx: Context): Symbol = { def topLevel(d: SymDenotation): Symbol = { - if (d.isEffectiveRoot || (d is PackageClass) || (d.owner is PackageClass)) d.symbol + if (d.isTopLevelClass) d.symbol else topLevel(d.owner) } val sym = topLevel(this) if (sym.isClass) sym else sym.moduleClass } + final def isTopLevelClass(implicit ctx: Context): Boolean = + this.isEffectiveRoot || (this is PackageClass) || (this.owner is PackageClass) + /** The package class containing this denotation */ final def enclosingPackageClass(implicit ctx: Context): Symbol = if (this is PackageClass) symbol else owner.enclosingPackageClass diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 30401ab2a5c2..2390931a93cf 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -192,8 +192,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val acc = apiAccess(sym) val modifiers = apiModifiers(sym) val anns = apiAnnotations(sym).toArray - // from SymDenotations.topLevelClass - val topLevel = (sym.isEffectiveRoot || (sym is PackageClass) || (sym.owner is PackageClass)) + val topLevel = sym.isTopLevelClass val childrenOfSealedClass = sym.children.sorted(classFirstSort).map(c => apiType(c.info)).toArray val cl = new api.ClassLike( From e1018d1ffac893ec54c5ac97844f0d286df01178 Mon Sep 17 00:00:00 2001 From: Thierry Treyer Date: Mon, 15 May 2017 11:50:28 +0200 Subject: [PATCH 005/101] Remove SimpleType After sbt/zinc#101, SimpleType simply doesn't exist anymore. --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 2390931a93cf..608e05e9ec9d 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -386,7 +386,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder sym.owner.thisType else tp.prefix - new api.Projection(simpleType(prefix), sym.name.toString) + new api.Projection(apiType(prefix), sym.name.toString) case AppliedType(tycon, args) => def processArg(arg: Type): api.Type = arg match { case arg @ TypeBounds(lo, hi) => // Handle wildcard parameters @@ -402,7 +402,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder apiType(arg) } - val apiTycon = simpleType(tycon) + val apiTycon = apiType(tycon) val apiArgs = args.map(processArg) new api.Parameterized(apiTycon, apiArgs.toArray) case tl: TypeLambda => @@ -498,15 +498,6 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } } - // TODO: Get rid of this method. See https://github.com/sbt/zinc/issues/101 - def simpleType(tp: Type): api.SimpleType = apiType(tp) match { - case tp: api.SimpleType => - tp - case _ => - ctx.debuglog("sbt-api: Not a simple type: " + tp.show) - Constants.emptyType - } - def apiLazy(tp: => Type): api.Type = { // TODO: The sbt api needs a convenient way to make a lazy type. // For now, we repurpose Structure for this. From 7865186c4b8413f6b603ff23eb729153bd02fb21 Mon Sep 17 00:00:00 2001 From: Thierry Treyer Date: Sun, 21 May 2017 21:40:05 +0200 Subject: [PATCH 006/101] Update bridge for compatibility with Zinc 1.0.0-X15 --- .../tools/dotc/sbt/ExtractDependencies.scala | 83 +++++++++++++++++-- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index cdec3e4b3366..f30871b7faa0 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -11,9 +11,11 @@ import scala.collection.{Set, mutable} import dotty.tools.io.{AbstractFile, Path, ZipArchive, PlainFile} import java.io.File -import java.util.{Arrays, Comparator} +import java.util.{Arrays, Comparator, EnumSet} import xsbti.api.DependencyContext +import xsbti.UseScope + /** This phase sends information on classes' dependencies to sbt via callbacks. * @@ -68,8 +70,22 @@ class ExtractDependencies extends Phase { } if (ctx.sbtCallback != null) { - extractDeps.usedNames.foreach{ case (enclosingName, names) => - names.foreach(name => ctx.sbtCallback.usedName(enclosingName.toString, name.toString)) } + extractDeps.usedNames.foreach{ + case (rawClassName, usedNames) => + val className = rawClassName.toString.trim + usedNames.defaultNames.foreach { rawUsedName => + val useName = rawUsedName.decode.toString.trim + val useScopes = + usedNames.scopedNames.get(rawUsedName) match { + case None => EnumSet.of(UseScope.Default) + case Some(existingScopes) => + existingScopes.add(UseScope.Default) + existingScopes + } + + ctx.sbtCallback.usedName(className, useName, useScopes) + } + } extractDeps.topLevelDependencies.foreach(dep => recordDependency(sourceFile.file, dep, DependencyContext.DependencyByMemberRef)) extractDeps.topLevelInheritanceDependencies.foreach(dep => @@ -118,6 +134,33 @@ class ExtractDependencies extends Phase { } } +private final class NameUsedInClass { + // Default names and other scopes are separated for performance reasons + val defaultNames: mutable.Set[Name] = new mutable.HashSet[Name] + val scopedNames: mutable.Map[Name, EnumSet[UseScope]] = new mutable.HashMap[Name, EnumSet[UseScope]].withDefault(_ => EnumSet.noneOf(classOf[UseScope])) + + // We have to leave with commas on ends + override def toString(): String = { + val builder = new StringBuilder(": ") + defaultNames.foreach { name => + builder.append(name.toString.trim) + val otherScopes = scopedNames.get(name) + scopedNames.get(name) match { + case None => + case Some(otherScopes) => + builder.append(" in [") + otherScopes.forEach(new java.util.function.Consumer[UseScope]() { + def accept(scope: UseScope): Unit = + builder.append(scope.name()).append(", ") + }) + builder.append("]") + } + builder.append(", ") + } + builder.toString() + } +} + /** Extract the dependency information of a compilation unit. * * To understand why we track the used names see the section "Name hashing @@ -126,17 +169,17 @@ class ExtractDependencies extends Phase { * specially, see the subsection "Dependencies introduced by member reference and * inheritance" in the "Name hashing algorithm" section. */ -private class ExtractDependenciesCollector(implicit val ctx: Context) extends tpd.TreeTraverser { +private class ExtractDependenciesCollector(implicit val ctx: Context) extends tpd.TreeTraverser { thisTreeTraverser => import tpd._ - private[this] val _usedNames = new mutable.HashMap[Name, mutable.Set[Name]].withDefault(_ => new mutable.HashSet[Name]) + private[this] val _usedNames = new mutable.HashMap[Name, NameUsedInClass].withDefault(_ => new NameUsedInClass) private[this] val _topLevelDependencies = new mutable.HashSet[Symbol] private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[Symbol] /** The names used in this class, this does not include names which are only * defined and not referenced. */ - def usedNames: collection.Map[Name, Set[Name]] = _usedNames + def usedNames: collection.Map[Name, NameUsedInClass] = _usedNames /** The set of top-level classes that the compilation unit depends on * because it refers to these classes or something defined in them. @@ -149,8 +192,12 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp */ def topLevelInheritanceDependencies: Set[Symbol] = _topLevelInheritanceDependencies - private def addUsedName(enclosingName: Name, name: Name) = - _usedNames(enclosingName) += name + private def addUsedName(enclosingName: Name, name: Name) = { + val nameUsed = _usedNames(enclosingName) + nameUsed.defaultNames += name + // TODO: Set correct scope + nameUsed.scopedNames(name).add(UseScope.Default) + } private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { @@ -183,12 +230,25 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp private def addInheritanceDependency(sym: Symbol): Unit = _topLevelInheritanceDependencies += sym.topLevelClass + private object PatMatDependencyTraverser extends ExtractTypesCollector { + override protected def addDependency(symbol: Symbol): Unit = { + if (!ignoreDependency(symbol) && symbol.is(Sealed)) { + val nameUsed = _usedNames(nonLocalEnclosingClass(symbol).fullName) + + nameUsed.defaultNames += symbol.name + nameUsed.scopedNames(symbol.name).add(UseScope.PatMatTarget) + } + } + } + /** Traverse the tree of a source file and record the dependencies which * can be retrieved using `topLevelDependencies`, `topLevelInheritanceDependencies`, * and `usedNames` */ override def traverse(tree: Tree)(implicit ctx: Context): Unit = { tree match { + case v @ ValDef(_, tpt, _) if v.symbol.is(Case) && v.symbol.is(Synthetic) => + PatMatDependencyTraverser.traverse(tpt.tpe) case Import(expr, selectors) => def lookupImported(name: Name) = expr.tpe.member(name).symbol def addImported(name: Name) = { @@ -254,7 +314,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp * The tests in sbt `types-in-used-names-a`, `types-in-used-names-b`, * `as-seen-from-a` and `as-seen-from-b` rely on this. */ - private object usedTypeTraverser extends TypeTraverser { + private class ExtractTypesCollector extends TypeTraverser { val seen = new mutable.HashSet[Type] def traverse(tp: Type): Unit = if (!seen.contains(tp)) { seen += tp @@ -277,5 +337,10 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverseChildren(tp) } } + + protected def addDependency(symbol: Symbol): Unit = + thisTreeTraverser.addDependency(symbol) } + + private object usedTypeTraverser extends ExtractTypesCollector } From 3f8a49c6557d979450677d40bf153c31a761b212 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 6 Jun 2017 14:44:55 +0200 Subject: [PATCH 007/101] Fix for zinc 1.0.0-X16 --- sbt-bridge/src/xsbt/CompilerInterface.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbt-bridge/src/xsbt/CompilerInterface.scala b/sbt-bridge/src/xsbt/CompilerInterface.scala index b2418d70cd9d..144dcbc6e17e 100644 --- a/sbt-bridge/src/xsbt/CompilerInterface.scala +++ b/sbt-bridge/src/xsbt/CompilerInterface.scala @@ -42,7 +42,7 @@ class CachedCompilerImpl(args: Array[String], output: Output, resident: Boolean) case multi: MultipleOutput => ??? case single: SingleOutput => - List("-d", single.outputDirectory.getAbsolutePath.toString) + List("-d", single.getOutputDirectory.getAbsolutePath.toString) } def commandArguments(sources: Array[File]): Array[String] = From 848e41bed8c1b5243f571da83f2ff4aeac06c307 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 6 Jun 2017 15:03:55 +0200 Subject: [PATCH 008/101] ExtractAPI: fix children of sealed classes --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 608e05e9ec9d..b93d16bc73b7 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -193,7 +193,12 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val modifiers = apiModifiers(sym) val anns = apiAnnotations(sym).toArray val topLevel = sym.isTopLevelClass - val childrenOfSealedClass = sym.children.sorted(classFirstSort).map(c => apiType(c.info)).toArray + val childrenOfSealedClass = sym.children.sorted(classFirstSort).map(c => + if (c.isClass) + apiType(c.typeRef) + else + apiType(c.valRef) + ).toArray val cl = new api.ClassLike( name.toString, acc, modifiers, anns, defType, strict2lzy(selfType), strict2lzy(structure), Constants.emptyStringArray, From bfd2b0f59fac913e37e66844d912e49d5112af6e Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 6 Jun 2017 15:37:54 +0200 Subject: [PATCH 009/101] ExtractAPI: add missing startSource callback --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index b93d16bc73b7..8ebd41e3d9c7 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -46,6 +46,9 @@ class ExtractAPI extends Phase { val forceRun = dumpInc || ctx.settings.YforceSbtPhases.value if ((ctx.sbtCallback != null || forceRun) && !unit.isJava) { val sourceFile = unit.source.file + if (ctx.sbtCallback != null) + ctx.sbtCallback.startSource(sourceFile) + val apiTraverser = new ExtractAPICollector val sources = apiTraverser.apiSource(unit.tpdTree) From d3f50a4e6af5f30368a799760fc6d450babb6441 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 6 Jun 2017 21:21:52 +0200 Subject: [PATCH 010/101] Fix various issues --- .../dotty/tools/backend/jvm/GenBCode.scala | 28 +++++++-- .../src/dotty/tools/dotc/core/Names.scala | 3 +- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 17 +++++- .../tools/dotc/sbt/ExtractDependencies.scala | 57 ++++++++++++------- 4 files changed, 76 insertions(+), 29 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index 93a273af1e9b..ca8c5f0807fc 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -17,6 +17,7 @@ import java.util.Optional import scala.reflect.ClassTag import dotty.tools.dotc.core._ +import dotty.tools.dotc.sbt.ExtractDependencies import Periods._ import SymDenotations._ import Contexts._ @@ -134,6 +135,8 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter private val poison3 = Item3(Int.MaxValue, null, null, null, null) private val q3 = new java.util.PriorityQueue[Item3](1000, i3comparator) + private val srcClassNames = new mutable.HashMap[String, String] + /* * Pipeline that takes ClassDefs from queue-1, lowers them into an intermediate form, placing them on queue-2 */ @@ -230,6 +233,15 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter // ----------- hand over to pipeline-2 + val srcClassName = ctx.atPhase(ctx.typerPhase) { implicit ctx => + ExtractDependencies.extractedName(claszSymbol) + } + for (cls <- List(mirrorC, plainC, beanC)) { + if (cls != null) { + srcClassNames += (cls.name -> srcClassName) + } + } + val item2 = Item2(arrivalPos, mirrorC, plainC, beanC, @@ -403,13 +415,21 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter else getFileForClassfile(outFolder, jclassName, ".class") bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, outFile) - val className = jclassName.replace('/', '.') + val srcClassName = srcClassNames(jclassName) + if (ctx.compilerCallback != null) - ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(outFile), className) - if (ctx.sbtCallback != null) + ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(outFile), srcClassName) + if (ctx.sbtCallback != null) { // ctx.sbtCallback.generatedClass(sourceFile.jfile.orElse(null), outFile.file, className) // TODO: Check - ctx.sbtCallback.generatedNonLocalClass(sourceFile.jfile.orElse(null), outFile.file, jclassName, className) + val isLocal = srcClassName.contains("_$") + if (isLocal) + ctx.sbtCallback.generatedLocalClass(sourceFile.jfile.orElse(null), outFile.file) + else { + ctx.sbtCallback.generatedNonLocalClass(sourceFile.jfile.orElse(null), outFile.file, + jclassName, srcClassName) + } + } } catch { case e: FileConflictException => diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index af92bbb4ecdb..62f0e38860eb 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -424,7 +424,8 @@ object Names { "dotty$tools$dotc$core$NameOps$NameDecorator$$functionArityFor$extension", "dotty$tools$dotc$typer$Checking$CheckNonCyclicMap$$apply", "$plus$plus", - "readConstant") + "readConstant", + "extractedName") .contains(elem.getMethodName)) } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 8ebd41e3d9c7..32325b43425c 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -112,6 +112,7 @@ class ExtractAPI extends Phase { private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder { import tpd._ import xsbti.api + import ExtractDependencies.extractedName /** This cache is necessary for correctness, see the comment about inherited * members in `apiClassStructure` @@ -187,7 +188,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val selfType = apiType(sym.givenSelfType) - val name = if (sym.is(ModuleClass)) sym.fullName.sourceModuleName else sym.fullName + val name = extractedName(sym) val tparams = sym.typeParams.map(apiTypeParameter).toArray @@ -204,12 +205,22 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder ).toArray val cl = new api.ClassLike( - name.toString, acc, modifiers, anns, defType, strict2lzy(selfType), strict2lzy(structure), Constants.emptyStringArray, + name, acc, modifiers, anns, defType, strict2lzy(selfType), strict2lzy(structure), Constants.emptyStringArray, childrenOfSealedClass, topLevel, tparams) + // if (name.toString.contains("DottyPredef")) { + // println("sym: " + sym) + // println("name: " + name) + // ctx.atPhase(ctx.flattenPhase.next) { implicit ctx => + // println("flatten: " + sym.fullName.toString) + // println("flattenm: " + sym.fullName.mangledString) + // } + // println("flattenx: " + toDenot(sym.binaryName.toString) + // } + allNonLocalClassesInSrc += cl - new api.ClassLikeDef(name.toString, acc, modifiers, anns, tparams, defType); + new api.ClassLikeDef(name, acc, modifiers, anns, tparams, defType) } private[this] val LegacyAppClass = ctx.requiredClass("dotty.runtime.LegacyApp") diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index f30871b7faa0..10954569302d 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -37,6 +37,8 @@ import xsbti.UseScope * @see ExtractAPI */ class ExtractDependencies extends Phase { + import ExtractDependencies._ + override def phaseName: String = "sbt-deps" // This phase should be run directly after `Frontend`, if it is run after @@ -69,12 +71,13 @@ class ExtractDependencies extends Phase { } finally pw.close() } + // println("extractDeps.usedNames: " + extractDeps.usedNames) if (ctx.sbtCallback != null) { extractDeps.usedNames.foreach{ case (rawClassName, usedNames) => - val className = rawClassName.toString.trim + val className = rawClassName.toString usedNames.defaultNames.foreach { rawUsedName => - val useName = rawUsedName.decode.toString.trim + val useName = rawUsedName.toString val useScopes = usedNames.scopedNames.get(rawUsedName) match { case None => EnumSet.of(UseScope.Default) @@ -109,7 +112,7 @@ class ExtractDependencies extends Phase { def className(classSegments: List[String]) = classSegments.mkString(".").stripSuffix(".class") def binaryDependency(file: File, className: String) = - ctx.sbtCallback.binaryDependency(file, className, currentClass.fullName.toString, currentSourceFile, context) + ctx.sbtCallback.binaryDependency(file, className, extractedName(currentClass), currentSourceFile, context) depFile match { case ze: ZipArchive#Entry => @@ -128,12 +131,22 @@ class ExtractDependencies extends Phase { ctx.warning(s"sbt-deps: Ignoring dependency $depFile of class ${depFile.getClass}") } } else if (depFile.file != currentSourceFile) { - ctx.sbtCallback.classDependency(dep.enclosingClass.fullName.toString, currentClass.fullName.toString, context) + ctx.sbtCallback.classDependency(extractedName(dep.enclosingClass), extractedName(currentClass), context) } } } } +object ExtractDependencies { + def extractedName(sym: Symbol)(implicit ctx: Context): String = + // ctx.atPhase(ctx.flattenPhase.next) { implicit ctx => + if (sym.is(ModuleClass)) + sym.fullName.stripModuleClassSuffix.toString + else + sym.fullName.toString + // } +} + private final class NameUsedInClass { // Default names and other scopes are separated for performance reasons val defaultNames: mutable.Set[Name] = new mutable.HashSet[Name] @@ -171,15 +184,16 @@ private final class NameUsedInClass { */ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tpd.TreeTraverser { thisTreeTraverser => import tpd._ + import ExtractDependencies._ - private[this] val _usedNames = new mutable.HashMap[Name, NameUsedInClass].withDefault(_ => new NameUsedInClass) + private[this] val _usedNames = new mutable.HashMap[String, NameUsedInClass] private[this] val _topLevelDependencies = new mutable.HashSet[Symbol] private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[Symbol] /** The names used in this class, this does not include names which are only * defined and not referenced. */ - def usedNames: collection.Map[Name, NameUsedInClass] = _usedNames + def usedNames: collection.Map[String, NameUsedInClass] = _usedNames /** The set of top-level classes that the compilation unit depends on * because it refers to these classes or something defined in them. @@ -192,8 +206,9 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp */ def topLevelInheritanceDependencies: Set[Symbol] = _topLevelInheritanceDependencies - private def addUsedName(enclosingName: Name, name: Name) = { - val nameUsed = _usedNames(enclosingName) + private def addUsedName(enclosingSym: Symbol, name: Name) = { + val enclosingName = extractedName(enclosingSym) + val nameUsed = _usedNames.getOrElseUpdate(enclosingName, new NameUsedInClass) nameUsed.defaultNames += name // TODO: Set correct scope nameUsed.scopedNames(name).add(UseScope.Default) @@ -204,21 +219,20 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp val tlClass = sym.topLevelClass if (tlClass.ne(NoSymbol)) // Some synthetic type aliases like AnyRef do not belong to any class _topLevelDependencies += sym.topLevelClass - addUsedName(nonLocalEnclosingClass(sym).fullName, sym.name) + addUsedName(nonLocalEnclosingClass(ctx.owner), sym.name) } - private def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = { - val owner = sym.maybeOwner - owner.isTerm || - owner.is(Trait) && isLocal(owner) || - sym.isConstructor && isLocal(owner) - } + private def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = + sym.ownersIterator.exists(_.isTerm) private def nonLocalEnclosingClass(sym: Symbol)(implicit ctx: Context): Symbol = sym.enclosingClass match { case NoSymbol => NoSymbol - case sym: Symbol if (isLocal(sym)) => sym - case sym: Symbol => nonLocalEnclosingClass(sym.owner) + case csym => + if (isLocal(csym)) + nonLocalEnclosingClass(csym.owner) + else + csym } private def ignoreDependency(sym: Symbol) = @@ -231,9 +245,10 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp _topLevelInheritanceDependencies += sym.topLevelClass private object PatMatDependencyTraverser extends ExtractTypesCollector { - override protected def addDependency(symbol: Symbol): Unit = { + override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val nameUsed = _usedNames(nonLocalEnclosingClass(symbol).fullName) + val encName = nonLocalEnclosingClass(ctx.owner).fullName.stripModuleClassSuffix.mangledString + val nameUsed = _usedNames.getOrElseUpdate(encName, new NameUsedInClass) nameUsed.defaultNames += symbol.name nameUsed.scopedNames(symbol.name).add(UseScope.PatMatTarget) @@ -262,7 +277,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp case Thicket(Ident(name) :: Ident(rename) :: Nil) => addImported(name) if (rename ne nme.WILDCARD) - addUsedName(nonLocalEnclosingClass(ctx.owner).fullName, rename) + addUsedName(nonLocalEnclosingClass(ctx.owner), rename) case _ => } case Inlined(call, _, _) => @@ -338,7 +353,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp } } - protected def addDependency(symbol: Symbol): Unit = + protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = thisTreeTraverser.addDependency(symbol) } From f02dacba553b0f914686976eb5bf3ad30e345551 Mon Sep 17 00:00:00 2001 From: Thierry Treyer Date: Wed, 7 Jun 2017 19:33:09 +0200 Subject: [PATCH 011/101] Propagate class files through GenBCode pipeline Some of sbt's callbacks need the full name of the class that can only be accessed during the first step of the GenBCode pipeline. So we call the callbacks in the first step, generating at the same time the class files, and keep those files through the whole pipeline so the last step can write the bytecode in them. --- .../dotty/tools/backend/jvm/GenBCode.scala | 124 ++++++++++-------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index ca8c5f0807fc..426e6a03a2e0 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -92,15 +92,17 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter /* ---------------- q2 ---------------- */ - case class Item2(arrivalPos: Int, - mirror: asm.tree.ClassNode, - plain: asm.tree.ClassNode, - bean: asm.tree.ClassNode, - outFolder: scala.tools.nsc.io.AbstractFile) { + case class SubItem2(classNode: asm.tree.ClassNode, + file: scala.tools.nsc.io.AbstractFile) + + case class Item2(arrivalPos: Int, + mirror: SubItem2, + plain: SubItem2, + bean: SubItem2) { def isPoison = { arrivalPos == Int.MaxValue } } - private val poison2 = Item2(Int.MaxValue, null, null, null, null) + private val poison2 = Item2(Int.MaxValue, null, null, null) private val q2 = new _root_.java.util.LinkedList[Item2] /* ---------------- q3 ---------------- */ @@ -114,14 +116,14 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter */ case class SubItem3( jclassName: String, - jclassBytes: Array[Byte] + jclassBytes: Array[Byte], + jclassFile: scala.tools.nsc.io.AbstractFile ) case class Item3(arrivalPos: Int, mirror: SubItem3, plain: SubItem3, - bean: SubItem3, - outFolder: scala.tools.nsc.io.AbstractFile) { + bean: SubItem3) { def isPoison = { arrivalPos == Int.MaxValue } } @@ -132,11 +134,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter else 1 } } - private val poison3 = Item3(Int.MaxValue, null, null, null, null) + private val poison3 = Item3(Int.MaxValue, null, null, null) private val q3 = new java.util.PriorityQueue[Item3](1000, i3comparator) - private val srcClassNames = new mutable.HashMap[String, String] - /* * Pipeline that takes ClassDefs from queue-1, lowers them into an intermediate form, placing them on queue-2 */ @@ -231,21 +231,54 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter ) } else null - // ----------- hand over to pipeline-2 + // ----------- create files + + // @smarter try/catch around getFileForClassfile needed? + val mirrorFileC = + if (mirrorC != null && outF != null) + getFileForClassfile(outF, mirrorC.name, ".class") + else null + + val plainFileC = + if (outF == null) null + else getFileForClassfile(outF, plainC.name, ".class") + + val beanFileC = + if (beanC != null && outF != null) + getFileForClassfile(outF, beanC.name, ".class") + else null + + // ----------- sbt's callbacks - val srcClassName = ctx.atPhase(ctx.typerPhase) { implicit ctx => + val fullClassName = ctx.atPhase(ctx.typerPhase) { implicit ctx => ExtractDependencies.extractedName(claszSymbol) } - for (cls <- List(mirrorC, plainC, beanC)) { + val isLocal = fullClassName.contains("_$") + + for ((cls, clsFile) <- List((plainC, plainFileC), (mirrorC, mirrorFileC), (beanC, beanFileC))) { if (cls != null) { - srcClassNames += (cls.name -> srcClassName) + if (ctx.compilerCallback != null) + ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(clsFile), fullClassName) + if (ctx.sbtCallback != null) { + // ctx.sbtCallback.generatedClass(sourceFile.jfile.orElse(null), clsFile.file, fullClassName) + // TODO: Check + if (isLocal) + ctx.sbtCallback.generatedLocalClass(sourceFile.jfile.orElse(null), clsFile.file) + else { + ctx.sbtCallback.generatedNonLocalClass(sourceFile.jfile.orElse(null), clsFile.file, + cls.name, fullClassName) + } + } } } + // ----------- hand over to pipeline-2 + val item2 = Item2(arrivalPos, - mirrorC, plainC, beanC, - outF) + SubItem2(mirrorC, mirrorFileC), + SubItem2(plainC, plainFileC), + SubItem2(beanC, beanFileC)) q2 add item2 // at the very end of this method so that no Worker2 thread starts mutating before we're done. @@ -275,12 +308,12 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter } else { try { - localOptimizations(item.plain) + localOptimizations(item.plain.classNode) addToQ3(item) } catch { case ex: Throwable => ex.printStackTrace() - ctx.error(s"Error while emitting ${item.plain.name}\n${ex.getMessage}") + ctx.error(s"Error while emitting ${item.plain.classNode.name}\n${ex.getMessage}") } } } @@ -294,11 +327,14 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter cw.toByteArray } - val Item2(arrivalPos, mirror, plain, bean, outFolder) = item + val Item2(arrivalPos, + SubItem2(mirror, mirrorFile), + SubItem2(plain, plainFile), + SubItem2(bean, beanFile)) = item - val mirrorC = if (mirror == null) null else SubItem3(mirror.name, getByteArray(mirror)) - val plainC = SubItem3(plain.name, getByteArray(plain)) - val beanC = if (bean == null) null else SubItem3(bean.name, getByteArray(bean)) + val mirrorC = if (mirror == null) null else SubItem3(mirror.name, getByteArray(mirror), mirrorFile) + val plainC = SubItem3(plain.name, getByteArray(plain), plainFile) + val beanC = if (bean == null) null else SubItem3(bean.name, getByteArray(bean), beanFile) if (AsmUtils.traceSerializedClassEnabled && plain.name.contains(AsmUtils.traceSerializedClassPattern)) { if (mirrorC != null) AsmUtils.traceClass(mirrorC.jclassBytes) @@ -306,7 +342,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter if (beanC != null) AsmUtils.traceClass(beanC.jclassBytes) } - q3 add Item3(arrivalPos, mirrorC, plainC, beanC, outFolder) + q3 add Item3(arrivalPos, mirrorC, plainC, beanC) } @@ -406,35 +442,10 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter /* Pipeline that writes classfile representations to disk. */ private def drainQ3() = { - def sendToDisk(cfr: SubItem3, outFolder: scala.tools.nsc.io.AbstractFile): Unit = { + def sendToDisk(cfr: SubItem3): Unit = { if (cfr != null){ - val SubItem3(jclassName, jclassBytes) = cfr - try { - val outFile = - if (outFolder == null) null - else getFileForClassfile(outFolder, jclassName, ".class") - bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, outFile) - - val srcClassName = srcClassNames(jclassName) - - if (ctx.compilerCallback != null) - ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(outFile), srcClassName) - if (ctx.sbtCallback != null) { - // ctx.sbtCallback.generatedClass(sourceFile.jfile.orElse(null), outFile.file, className) - // TODO: Check - val isLocal = srcClassName.contains("_$") - if (isLocal) - ctx.sbtCallback.generatedLocalClass(sourceFile.jfile.orElse(null), outFile.file) - else { - ctx.sbtCallback.generatedNonLocalClass(sourceFile.jfile.orElse(null), outFile.file, - jclassName, srcClassName) - } - } - } - catch { - case e: FileConflictException => - ctx.error(s"error writing $jclassName: ${e.getMessage}") - } + val SubItem3(jclassName, jclassBytes, jclassFile) = cfr + bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, jclassFile) } } @@ -447,10 +458,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter moreComing = !incoming.isPoison if (moreComing) { val item = incoming - val outFolder = item.outFolder - sendToDisk(item.mirror, outFolder) - sendToDisk(item.plain, outFolder) - sendToDisk(item.bean, outFolder) + sendToDisk(item.mirror) + sendToDisk(item.plain) + sendToDisk(item.bean) expected += 1 } } From d7dba97d93da8f0f597fa43a7c8697ab06a467b7 Mon Sep 17 00:00:00 2001 From: Thierry Treyer Date: Wed, 7 Jun 2017 22:17:14 +0200 Subject: [PATCH 012/101] Catch FileConflictException creating class files A FileConflictException may occure when creating a class file. Add check for this error and refactor a bit of code around it. --- .../dotty/tools/backend/jvm/GenBCode.scala | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index 426e6a03a2e0..40841c7a51b2 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -233,20 +233,18 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter // ----------- create files - // @smarter try/catch around getFileForClassfile needed? - val mirrorFileC = - if (mirrorC != null && outF != null) - getFileForClassfile(outF, mirrorC.name, ".class") - else null - - val plainFileC = - if (outF == null) null - else getFileForClassfile(outF, plainC.name, ".class") - - val beanFileC = - if (beanC != null && outF != null) - getFileForClassfile(outF, beanC.name, ".class") - else null + val classNodes = List(mirrorC, plainC, beanC) + val classFiles = classNodes.map(cls => + if (outF != null && cls != null) { + try { + getFileForClassfile(outF, cls.name, ".class") + } catch { + case e: FileConflictException => + ctx.error(s"error writing ${cls.name}: ${e.getMessage}") + null + } + } else null + ) // ----------- sbt's callbacks @@ -255,7 +253,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter } val isLocal = fullClassName.contains("_$") - for ((cls, clsFile) <- List((plainC, plainFileC), (mirrorC, mirrorFileC), (beanC, beanFileC))) { + for ((cls, clsFile) <- classNodes.zip(classFiles)) { if (cls != null) { if (ctx.compilerCallback != null) ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(clsFile), fullClassName) @@ -276,9 +274,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter val item2 = Item2(arrivalPos, - SubItem2(mirrorC, mirrorFileC), - SubItem2(plainC, plainFileC), - SubItem2(beanC, beanFileC)) + SubItem2(mirrorC, classFiles(0)), + SubItem2(plainC, classFiles(1)), + SubItem2(beanC, classFiles(2))) q2 add item2 // at the very end of this method so that no Worker2 thread starts mutating before we're done. From fb9c61189a1b036596f4e6f8c817d8b589adb41a Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Thu, 12 Oct 2017 17:32:11 +0200 Subject: [PATCH 013/101] Adapt to latest Zinc --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 88 ++++---- .../tools/dotc/sbt/ExtractDependencies.scala | 178 ++++++++++----- .../dotty/tools/dotc/sbt/ThunkHolder.scala | 91 +------- .../tools/dotc/transform/patmat/Space.scala | 2 +- project/Build.scala | 96 ++++---- project/VersionUtil.scala | 2 +- project/build.properties | 2 +- project/plugins.sbt | 14 +- project/scripted.sbt | 4 +- sbt-bridge/src/xsbt/CompilerInterface.scala | 14 +- sbt-bridge/src/xsbt/DelegatingReporter.scala | 10 +- sbt-bridge/src/xsbt/Message.scala | 4 +- sbt-bridge/src/xsbt/Problem.scala | 12 + sbt-bridge/src/xsbt/ScaladocInterface.scala | 4 +- .../test/xsbt/DependencySpecification.scala | 136 +++++------ .../test/xsbt/ExtractAPISpecification.scala | 41 ++-- .../xsbt/ExtractUsedNamesSpecification.scala | 211 ++++++++++-------- .../xsbt/ScalaCompilerForUnitTesting.scala | 112 +++++----- sbt-bridge/test/xsbti/TestCallback.scala | 111 ++++++--- .../tools/sbtplugin/DottyIDEPlugin.scala | 8 +- .../dotty/tools/sbtplugin/DottyPlugin.scala | 102 ++++----- 21 files changed, 657 insertions(+), 585 deletions(-) create mode 100644 sbt-bridge/src/xsbt/Problem.scala diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 32325b43425c..a8e8c2a93e83 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -47,7 +47,7 @@ class ExtractAPI extends Phase { if ((ctx.sbtCallback != null || forceRun) && !unit.isJava) { val sourceFile = unit.source.file if (ctx.sbtCallback != null) - ctx.sbtCallback.startSource(sourceFile) + ctx.sbtCallback.startSource(sourceFile.file) val apiTraverser = new ExtractAPICollector val sources = apiTraverser.apiSource(unit.tpdTree) @@ -130,13 +130,13 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder private[this] object Constants { val emptyStringArray = Array[String]() - val local = new api.ThisQualifier - val public = new api.Public - val privateLocal = new api.Private(local) - val protectedLocal = new api.Protected(local) - val unqualified = new api.Unqualified - val thisPath = new api.This - val emptyType = new api.EmptyType + val local = api.ThisQualifier.create() + val public = api.Public.create() + val privateLocal = api.Private.create(local) + val protectedLocal = api.Protected.create(local) + val unqualified = api.Unqualified.create() + val thisPath = api.This.create() + val emptyType = api.EmptyType.create() val emptyModifiers = new api.Modifiers(false, false, false, false, false,false, false, false) } @@ -150,9 +150,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder * @param marker A special annotation to differentiate our type */ private def withMarker(tp: api.Type, marker: api.Annotation) = - new api.Annotated(tp, Array(marker)) + api.Annotated.of(tp, Array(marker)) private def marker(name: String) = - new api.Annotation(new api.Constant(Constants.emptyType, name), Array()) + api.Annotation.of(api.Constant.of(Constants.emptyType, name), Array()) val typeArgRefMarker = marker("TypeArgRef") val orMarker = marker("Or") val byNameMarker = marker("ByName") @@ -201,11 +201,11 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder if (c.isClass) apiType(c.typeRef) else - apiType(c.valRef) + apiType(c.termRef) ).toArray - val cl = new api.ClassLike( - name, acc, modifiers, anns, defType, strict2lzy(selfType), strict2lzy(structure), Constants.emptyStringArray, + val cl = api.ClassLike.of( + name, acc, modifiers, anns, defType, api.SafeLazy.strict(selfType), api.SafeLazy.strict(structure), Constants.emptyStringArray, childrenOfSealedClass, topLevel, tparams) // if (name.toString.contains("DottyPredef")) { @@ -220,7 +220,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder allNonLocalClassesInSrc += cl - new api.ClassLikeDef(name, acc, modifiers, anns, tparams, defType) + api.ClassLikeDef.of(name, acc, modifiers, anns, tparams, defType) } private[this] val LegacyAppClass = ctx.requiredClass("dotty.runtime.LegacyApp") @@ -260,7 +260,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // this works because of `classLikeCache` val apiInherited = lzy(apiDefinitions(inherited).toArray) - new api.Structure(strict2lzy(apiBases.toArray), strict2lzy(apiDecls.toArray), apiInherited) + api.Structure.of(api.SafeLazy.strict(apiBases.toArray), api.SafeLazy.strict(apiDecls.toArray), apiInherited) } def linearizedAncestorTypes(info: ClassInfo): List[Type] = { @@ -306,10 +306,10 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } else if (sym.isType) { apiTypeMember(sym.asType) } else if (sym.is(Mutable, butNot = Accessor)) { - new api.Var(sym.name.toString, apiAccess(sym), apiModifiers(sym), + api.Var.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, apiType(sym.info)) } else if (sym.isStable) { - new api.Val(sym.name.toString, apiAccess(sym), apiModifiers(sym), + api.Val.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, apiType(sym.info)) } else { apiDef(sym.asTerm) @@ -336,9 +336,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } else (0 until pnames.length).map(Function.const(false)) val params = (pnames, ptypes, defaults).zipped.map((pname, ptype, isDefault) => - new api.MethodParameter(pname.toString, apiType(ptype), + api.MethodParameter.of(pname.toString, apiType(ptype), isDefault, api.ParameterModifier.Plain)) - new api.ParameterList(params.toArray, mt.isImplicitMethod) :: paramLists(restpe, params.length) + api.ParameterList.of(params.toArray, mt.isImplicitMethod) :: paramLists(restpe, params.length) case _ => Nil } @@ -353,7 +353,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val vparamss = paramLists(sym.info) val retTp = sym.info.finalResultType.widenExpr - new api.Def(sym.name.toString, apiAccess(sym), apiModifiers(sym), + api.Def.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, tparams.toArray, vparamss.toArray, apiType(retTp)) } @@ -366,17 +366,17 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val tpe = sym.info if (sym.isAliasType) - new api.TypeAlias(name, access, modifiers, as.toArray, typeParams, apiType(tpe.bounds.hi)) + api.TypeAlias.of(name, access, modifiers, as.toArray, typeParams, apiType(tpe.bounds.hi)) else { assert(sym.isAbstractType) - new api.TypeDeclaration(name, access, modifiers, as.toArray, typeParams, apiType(tpe.bounds.lo), apiType(tpe.bounds.hi)) + api.TypeDeclaration.of(name, access, modifiers, as.toArray, typeParams, apiType(tpe.bounds.lo), apiType(tpe.bounds.hi)) } } // Hack to represent dotty types which don't have an equivalent in xsbti def combineApiTypes(apiTps: api.Type*): api.Type = { - new api.Structure(strict2lzy(apiTps.toArray), - strict2lzy(Array()), strict2lzy(Array())) + api.Structure.of(api.SafeLazy.strict(apiTps.toArray), + api.SafeLazy.strict(Array()), api.SafeLazy.strict(Array())) } def apiType(tp: Type): api.Type = { @@ -405,7 +405,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder sym.owner.thisType else tp.prefix - new api.Projection(apiType(prefix), sym.name.toString) + api.Projection.of(apiType(prefix), sym.name.toString) case AppliedType(tycon, args) => def processArg(arg: Type): api.Type = arg match { case arg @ TypeBounds(lo, hi) => // Handle wildcard parameters @@ -413,8 +413,8 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder Constants.emptyType else { val name = "_" - val ref = new api.ParameterRef(name) - new api.Existential(ref, + val ref = api.ParameterRef.of(name) + api.Existential.of(ref, Array(apiTypeParameter(name, 0, lo, hi))) } case _ => @@ -423,21 +423,21 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val apiTycon = apiType(tycon) val apiArgs = args.map(processArg) - new api.Parameterized(apiTycon, apiArgs.toArray) + api.Parameterized.of(apiTycon, apiArgs.toArray) case tl: TypeLambda => val apiTparams = tl.typeParams.map(apiTypeParameter) val apiRes = apiType(tl.resType) - new api.Polymorphic(apiRes, apiTparams.toArray) + api.Polymorphic.of(apiRes, apiTparams.toArray) case rt: RefinedType => val name = rt.refinedName.toString val parent = apiType(rt.parent) def typeRefinement(name: String, tp: TypeBounds): api.TypeMember = tp match { case TypeAlias(alias) => - new api.TypeAlias(name, + api.TypeAlias.of(name, Constants.public, Constants.emptyModifiers, Array(), Array(), apiType(alias)) case TypeBounds(lo, hi) => - new api.TypeDeclaration(name, + api.TypeDeclaration.of(name, Constants.public, Constants.emptyModifiers, Array(), Array(), apiType(lo), apiType(hi)) } val decl = rt.refinedInfo match { @@ -471,7 +471,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // `refinedTypeCache` is for. refinedTypeCache.getOrElseUpdate((parent, decl), { val adecl: Array[api.ClassDefinition] = if (decl == null) Array() else Array(decl) - new api.Structure(strict2lzy(Array(parent)), strict2lzy(adecl), strict2lzy(Array())) + api.Structure.of(api.SafeLazy.strict(Array(parent)), api.SafeLazy.strict(adecl), api.SafeLazy.strict(Array())) }) case tp: RecType => apiType(tp.parent) @@ -494,15 +494,15 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder case ExprType(resultType) => withMarker(apiType(resultType), byNameMarker) case ConstantType(constant) => - new api.Constant(apiType(constant.tpe), constant.stringValue) + api.Constant.of(apiType(constant.tpe), constant.stringValue) case AnnotatedType(tpe, annot) => - new api.Annotated(apiType(tpe), Array(apiAnnotation(annot))) + api.Annotated.of(apiType(tpe), Array(apiAnnotation(annot))) case tp: ThisType => apiThis(tp.cls) case tp: ParamRef => // TODO: Distinguishing parameters based on their names alone is not enough, // the binder is also needed (at least for type lambdas). - new api.ParameterRef(tp.paramName.toString) + api.ParameterRef.of(tp.paramName.toString) case tp: LazyRef => apiType(tp.ref) case tp: TypeVar => @@ -521,13 +521,13 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // TODO: The sbt api needs a convenient way to make a lazy type. // For now, we repurpose Structure for this. val apiTp = lzy(Array(apiType(tp))) - new api.Structure(apiTp, strict2lzy(Array()), strict2lzy(Array())) + api.Structure.of(apiTp, api.SafeLazy.strict(Array()), api.SafeLazy.strict(Array())) } def apiThis(sym: Symbol): api.Singleton = { val pathComponents = sym.ownersIterator.takeWhile(!_.isEffectiveRoot) - .map(s => new api.Id(s.name.toString)) - new api.Singleton(new api.Path(pathComponents.toArray.reverse ++ Array(Constants.thisPath))) + .map(s => api.Id.of(s.name.toString)) + api.Singleton.of(api.Path.of(pathComponents.toArray.reverse ++ Array(Constants.thisPath))) } def apiTypeParameter(tparam: ParamInfo): api.TypeParameter = @@ -535,7 +535,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder tparam.paramInfo.bounds.lo, tparam.paramInfo.bounds.hi) def apiTypeParameter(name: String, variance: Int, lo: Type, hi: Type): api.TypeParameter = - new api.TypeParameter(name, Array(), Array(), apiVariance(variance), + api.TypeParameter.of(name, Array(), Array(), apiVariance(variance), apiType(lo), apiType(hi)) def apiVariance(v: Int): api.Variance = { @@ -559,11 +559,11 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder if (sym.privateWithin eq NoSymbol) Constants.unqualified else - new api.IdQualifier(sym.privateWithin.fullName.toString) + api.IdQualifier.of(sym.privateWithin.fullName.toString) if (sym.is(Protected)) - new api.Protected(qualifier) + api.Protected.of(qualifier) else - new api.Private(qualifier) + api.Private.of(qualifier) } } @@ -608,8 +608,8 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // However, we still need to extract the annotation type in the way sbt expect // because sbt uses this information to find tests to run (for example // junit tests are annotated @org.junit.Test). - new api.Annotation( + api.Annotation.of( apiType(annot.tree.tpe), // Used by sbt to find tests to run - Array(new api.AnnotationArgument("FULLTREE", annot.tree.show.toString))) + Array(api.AnnotationArgument.of("FULLTREE", annot.tree.show.toString))) } } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 10954569302d..5d80684b4edf 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -3,6 +3,7 @@ package sbt import ast.{Trees, tpd} import core._, core.Decorators._ +import util.NoSource.{file => NoSourceFile} import Contexts._, Flags._, Phases._, Trees._, Types._, Symbols._ import Names._, NameOps._, StdNames._ @@ -52,7 +53,16 @@ class ExtractDependencies extends Phase { val forceRun = dumpInc || ctx.settings.YforceSbtPhases.value if ((ctx.sbtCallback != null || forceRun) && !unit.isJava) { val sourceFile = unit.source.file - val extractDeps = new ExtractDependenciesCollector + val responsibleOfImports = firstClassOrModule(unit.tpdTree) match { + case None => + ctx.warning("""|No class, trait or object is defined in the compilation unit. + |The incremental compiler cannot record the dependency information in such case. + |Some errors like unused import referring to a non-existent class might not be reported. + |""".stripMargin, unit.tpdTree.pos) + defn.RootClass + case Some(sym) => sym + } + val extractDeps = new ExtractDependenciesCollector(responsibleOfImports) extractDeps.traverse(unit.tpdTree) if (dumpInc) { @@ -71,7 +81,6 @@ class ExtractDependencies extends Phase { } finally pw.close() } - // println("extractDeps.usedNames: " + extractDeps.usedNames) if (ctx.sbtCallback != null) { extractDeps.usedNames.foreach{ case (rawClassName, usedNames) => @@ -90,13 +99,59 @@ class ExtractDependencies extends Phase { } } extractDeps.topLevelDependencies.foreach(dep => - recordDependency(sourceFile.file, dep, DependencyContext.DependencyByMemberRef)) + recordDependency(sourceFile.file, dep._2, DependencyContext.DependencyByMemberRef)(ctx.withOwner(dep._1))) extractDeps.topLevelInheritanceDependencies.foreach(dep => - recordDependency(sourceFile.file, dep, DependencyContext.DependencyByInheritance)) + recordDependency(sourceFile.file, dep._2, DependencyContext.DependencyByInheritance)(ctx.withOwner(dep._1))) + } + } + } + + private def firstClassOrModule(tree: tpd.Tree)(implicit ctx: Context): Option[Symbol] = { + import tpd._ + val acc = new TreeAccumulator[Option[Symbol]] { + def apply(x: Option[Symbol], t: Tree)(implicit ctx: Context) = + if (x.isDefined) x + else t match { + case moduleDef: Thicket => + Some(moduleDef.symbol) + case typeDef: TypeDef => + Some(typeDef.symbol) + case other => + foldOver(x, other) + } + } + acc(None, tree) + } + + private def classFile(sym: Symbol)(implicit ctx: Context): Option[AbstractFile] = { + // package can never have a corresponding class file; this test does not + // catch package objects (that do not have this flag set) + if (sym.is(Package)) None + else { + val file = Option(sym.associatedFile) + + Option(sym.associatedFile).flatMap { + case NoSourceFile => + if (isTopLevelModule(sym)) { + val linked = sym.companionClass + if (linked == NoSymbol) + None + else + classFile(linked) + } else + None + case file => + Some(file) } } } + protected def isTopLevelModule(sym: Symbol)(implicit ctx: Context): Boolean = + // enteringPhase(currentRun.picklerPhase.next) { + sym.is(ModuleClass) && sym.owner.is(PackageClass) + // } + + /** Record that `currentSourceFile` depends on the file where `dep` was loaded from. * * @param currentSourceFile The source file of the current unit @@ -105,34 +160,41 @@ class ExtractDependencies extends Phase { */ def recordDependency(currentSourceFile: File, dep: Symbol, context: DependencyContext) (implicit ctx: Context) = { - val depFile = dep.associatedFile - if (depFile != null) { - if (depFile.path.endsWith(".class")) { - /** Transform `List(java, lang, String.class)` into `java.lang.String` */ - def className(classSegments: List[String]) = - classSegments.mkString(".").stripSuffix(".class") - def binaryDependency(file: File, className: String) = - ctx.sbtCallback.binaryDependency(file, className, extractedName(currentClass), currentSourceFile, context) - - depFile match { - case ze: ZipArchive#Entry => - for (zip <- ze.underlyingSource; zipFile <- Option(zip.file)) { - val classSegments = Path(ze.path).segments - binaryDependency(zipFile, className(classSegments)) - } - case pf: PlainFile => - val packages = dep.ownersIterator - .filter(x => x.is(PackageClass) && !x.isEffectiveRoot).length - // We can recover the fully qualified name of a classfile from - // its path - val classSegments = pf.givenPath.segments.takeRight(packages + 1) - binaryDependency(pf.file, className(classSegments)) - case _ => - ctx.warning(s"sbt-deps: Ignoring dependency $depFile of class ${depFile.getClass}") - } - } else if (depFile.file != currentSourceFile) { - ctx.sbtCallback.classDependency(extractedName(dep.enclosingClass), extractedName(currentClass), context) + val onSource = dep.sourceFile + if (onSource == null) { + // Dependency is external -- source is undefined + classFile(dep) match { + case Some(at) => + def className(classSegments: List[String]) = + classSegments.mkString(".").stripSuffix(".class") + def binaryDependency(file: File, className: String) = { + ctx.sbtCallback.binaryDependency(file, className, extractedName(currentClass), currentSourceFile, context) + } + + at match { + case ze: ZipArchive#Entry => + for (zip <- ze.underlyingSource; zipFile <- Option(zip.file)) { + val classSegments = Path(ze.path).segments + binaryDependency(zipFile, className(classSegments)) + } + case pf: PlainFile => + val packages = dep.ownersIterator + .filter(x => x.is(PackageClass) && !x.isEffectiveRoot).length + // We can recover the fully qualified name of a classfile from + // its path + val classSegments = pf.givenPath.segments.takeRight(packages + 1) + binaryDependency(pf.file, className(classSegments)) + case _ => + ctx.warning(s"sbt-deps: Ignoring dependency $at of class ${at.getClass}") + } + + case None => + ctx.debuglog(s"No file for external symbol $dep") } + } else if (onSource.file != currentSourceFile) { + ctx.sbtCallback.classDependency(extractedName(dep.enclosingClass), extractedName(currentClass), context) + } else { + () } } } @@ -161,11 +223,13 @@ private final class NameUsedInClass { scopedNames.get(name) match { case None => case Some(otherScopes) => - builder.append(" in [") - otherScopes.forEach(new java.util.function.Consumer[UseScope]() { - def accept(scope: UseScope): Unit = + // Pickling tests fail when this is turned in an anonymous class + class Consumer extends java.util.function.Consumer[UseScope]() { + override def accept(scope: UseScope): Unit = builder.append(scope.name()).append(", ") - }) + } + builder.append(" in [") + otherScopes.forEach(new Consumer) builder.append("]") } builder.append(", ") @@ -182,13 +246,13 @@ private final class NameUsedInClass { * specially, see the subsection "Dependencies introduced by member reference and * inheritance" in the "Name hashing algorithm" section. */ -private class ExtractDependenciesCollector(implicit val ctx: Context) extends tpd.TreeTraverser { thisTreeTraverser => +private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implicit val ctx: Context) extends tpd.TreeTraverser { thisTreeTraverser => import tpd._ import ExtractDependencies._ private[this] val _usedNames = new mutable.HashMap[String, NameUsedInClass] - private[this] val _topLevelDependencies = new mutable.HashSet[Symbol] - private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[Symbol] + private[this] val _topLevelDependencies = new mutable.HashSet[(Symbol, Symbol)] + private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[(Symbol, Symbol)] /** The names used in this class, this does not include names which are only * defined and not referenced. @@ -199,15 +263,18 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp * because it refers to these classes or something defined in them. * This is always a superset of `topLevelInheritanceDependencies` by definition. */ - def topLevelDependencies: Set[Symbol] = _topLevelDependencies + def topLevelDependencies: Set[(Symbol, Symbol)] = _topLevelDependencies /** The set of top-level classes that the compilation unit extends or that * contain a non-top-level class that the compilaion unit extends. */ - def topLevelInheritanceDependencies: Set[Symbol] = _topLevelInheritanceDependencies + def topLevelInheritanceDependencies: Set[(Symbol, Symbol)] = _topLevelInheritanceDependencies private def addUsedName(enclosingSym: Symbol, name: Name) = { - val enclosingName = extractedName(enclosingSym) + val enclosingName = enclosingSym match { + case sym if sym == defn.RootClass => ExtractDependencies.extractedName(responsibleForImports) + case sym => extractedName(sym) + } val nameUsed = _usedNames.getOrElseUpdate(enclosingName, new NameUsedInClass) nameUsed.defaultNames += name // TODO: Set correct scope @@ -217,8 +284,14 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { val tlClass = sym.topLevelClass - if (tlClass.ne(NoSymbol)) // Some synthetic type aliases like AnyRef do not belong to any class - _topLevelDependencies += sym.topLevelClass + if (tlClass.ne(NoSymbol)) { + if (currentClass == defn.RootClass) { + _topLevelDependencies += ((responsibleForImports, tlClass)) + } else { + // Some synthetic type aliases like AnyRef do not belong to any class + _topLevelDependencies += ((currentClass, tlClass)) + } + } addUsedName(nonLocalEnclosingClass(ctx.owner), sym.name) } @@ -241,10 +314,10 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp sym.isAnonymousFunction || sym.isAnonymousClass - private def addInheritanceDependency(sym: Symbol): Unit = - _topLevelInheritanceDependencies += sym.topLevelClass + private def addInheritanceDependency(sym: Symbol)(implicit ctx: Context): Unit = + _topLevelInheritanceDependencies += ((currentClass, sym.topLevelClass)) - private object PatMatDependencyTraverser extends ExtractTypesCollector { + private class PatMatDependencyTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) { override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { if (!ignoreDependency(symbol) && symbol.is(Sealed)) { val encName = nonLocalEnclosingClass(ctx.owner).fullName.stripModuleClassSuffix.mangledString @@ -263,7 +336,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp override def traverse(tree: Tree)(implicit ctx: Context): Unit = { tree match { case v @ ValDef(_, tpt, _) if v.symbol.is(Case) && v.symbol.is(Synthetic) => - PatMatDependencyTraverser.traverse(tpt.tpe) + new PatMatDependencyTraverser(ctx).traverse(tpt.tpe) case Import(expr, selectors) => def lookupImported(name: Name) = expr.tpe.member(name).symbol def addImported(name: Name) = { @@ -276,8 +349,9 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp addImported(name) case Thicket(Ident(name) :: Ident(rename) :: Nil) => addImported(name) - if (rename ne nme.WILDCARD) + if (rename ne nme.WILDCARD) { addUsedName(nonLocalEnclosingClass(ctx.owner), rename) + } case _ => } case Inlined(call, _, _) => @@ -285,10 +359,10 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp // record it as a dependency traverse(call) case t: TypeTree => - usedTypeTraverser.traverse(t.tpe) + new usedTypeTraverser(ctx).traverse(t.tpe) case ref: RefTree => addDependency(ref.symbol) - usedTypeTraverser.traverse(ref.tpe) + new usedTypeTraverser(ctx).traverse(ref.tpe) case t @ Template(_, parents, _, _) => t.parents.foreach(p => addInheritanceDependency(p.tpe.classSymbol)) case _ => @@ -329,7 +403,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp * The tests in sbt `types-in-used-names-a`, `types-in-used-names-b`, * `as-seen-from-a` and `as-seen-from-b` rely on this. */ - private class ExtractTypesCollector extends TypeTraverser { + private class ExtractTypesCollector(ctx0: Context) extends TypeTraverser()(ctx0) { val seen = new mutable.HashSet[Type] def traverse(tp: Type): Unit = if (!seen.contains(tp)) { seen += tp @@ -357,5 +431,5 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp thisTreeTraverser.addDependency(symbol) } - private object usedTypeTraverser extends ExtractTypesCollector + private class usedTypeTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) } diff --git a/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala b/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala index 350819e3a3ce..2315c40955e4 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala @@ -25,97 +25,8 @@ private[sbt] trait ThunkHolder { * It will be forced by the next call to `forceThunks()` */ def lzy[T <: AnyRef](t: => T): api.Lazy[T] = { - val l = SafeLazyWrapper(() => t) + val l = api.SafeLazy.apply(() => t) thunks += l l } - - /** Store the parameter `s` in a `Lazy` container, since `s` is not by-name, there - * is nothing to force. - * - * TODO: Get rid of this method. It is only needed because some xsbti.api classes - * take lazy arguments when they could be strict, but this can be fixed in sbt, - * see https://github.com/sbt/zinc/issues/114 - */ - def strict2lzy[T <: AnyRef](t: T): api.Lazy[T] = - SafeLazyWrapper.strict(t) -} - -/** Wrapper around SafeLazy implementations. - * - * `xsbti.SafeLazy` is part of sbt but it is not part of the `interface` jar - * that dotty depends on, therefore we can only access it by reflection, - * and this will only succeed when dotty is run by sbt (otherwise - * `xsbti.SafeLazy` won't be on the classpath at all). - * - * For testing purposes, we still want to be able to run the sbt phases outside - * of sbt, using `-Yforce-sbt-phases` and `-Ydump-sbt-inc`, therefore we - * provide a copy of SafeLazy in `dotty.tools.dotc.sbt.SafeLazy` that we use - * when `xsbti.SafeLazy` is unavailable. - * - * This raises a question: why bother with `xsbti.SafeLazy` if we have our own - * version anyway? Because sbt uses Java serialization to persist the output of - * the incremental compilation analysis when sbt is stopped and restarted. If - * we used `dotty.tools.dotc.sbt.SafeLazy` with sbt, deserialization would fail - * and every restart of sbt would require a full recompilation. - * - * Note: this won't be needed once we switch to zinc 1.0 where `SafeLazy` becomes - * part of the `interface` jar, see https://github.com/sbt/zinc/issues/113 - */ -private object SafeLazyWrapper { - - @sharable private[this] val safeLazy = - try { - Class.forName("xsbti.SafeLazy") - } catch { - case e: ClassNotFoundException => - null - } - - @sharable private[this] val safeLazyApply = - if (safeLazy != null) - safeLazy.getMethod("apply", classOf[xsbti.F0[_]]) - else - null - @sharable private[this] val safeLazyStrict = - if (safeLazy != null) - safeLazy.getMethod("strict", classOf[Object]) - else - null - - def apply[T <: AnyRef](eval: () => T): xsbti.api.Lazy[T] = - if (safeLazyApply != null) - safeLazyApply - .invoke(null, new xsbti.F0[T] { def apply() = eval() }) - .asInstanceOf[xsbti.api.Lazy[T]] - else - SafeLazy(eval) - - def strict[T <: AnyRef](value: T): xsbti.api.Lazy[T] = - if (safeLazyStrict != null) - safeLazyStrict - .invoke(null, value) - .asInstanceOf[xsbti.api.Lazy[T]] - else - SafeLazy.strict(value) -} - -// Adapted from https://github.com/sbt/sbt/blob/0.13/compile/api/src/main/scala/xsbti/SafeLazy.scala -private object SafeLazy { - def apply[T <: AnyRef](eval: () => T): xsbti.api.Lazy[T] = - new Impl(eval) - - def strict[T <: AnyRef](value: T): xsbti.api.Lazy[T] = - new Strict(value) - - private[this] final class Impl[T <: AnyRef](private[this] var eval: () => T) extends xsbti.api.AbstractLazy[T] { - private[this] lazy val _t = { - val t = eval() - eval = null // clear the reference, ensuring the only memory we hold onto is the result - t - } - def get(): T = _t - } - - private[this] final class Strict[T <: AnyRef](val get: T) extends xsbti.api.Lazy[T] with java.io.Serializable } diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index ee17927a2598..cfbfea837365 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -501,7 +501,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { /** Decompose a type into subspaces -- assume the type can be decomposed */ def decompose(tp: Type): List[Space] = { - val children = tp.classSymbol.children + val children = tp.classSymbol.denot.children debug.println(s"candidates for ${tp.show} : [${children.map(_.show).mkString(", ")}]") diff --git a/project/Build.scala b/project/Build.scala index 2210837300ee..b2cf87ea902d 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -10,7 +10,6 @@ import scala.reflect.io.Path import sbt.Package.ManifestAttributes -// import sbt.ScriptedPlugin.autoImport._ import dotty.tools.sbtplugin.DottyPlugin.autoImport._ import dotty.tools.sbtplugin.DottyIDEPlugin.{ prepareCommand, runProcess } import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._ @@ -18,6 +17,16 @@ import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._ import pl.project13.scala.sbt.JmhPlugin import JmhPlugin.JmhKeys.Jmh +import sbt.ScriptedPlugin.autoImport._ + +import xerial.sbt.pack.PackPlugin.packSettings +import xerial.sbt.pack.PackPlugin.autoImport._ + +import org.scalajs.sbtplugin.ScalaJSPlugin +import ScalaJSPlugin.autoImport._ + +import com.typesafe.sbteclipse.plugin.EclipsePlugin.EclipseKeys + import Modes._ /* In sbt 0.13 the Build trait would expose all vals to the shell, where you @@ -129,7 +138,7 @@ object Build { resourceDirectory in Test := baseDirectory.value / "test-resources", // Prevent sbt from rewriting our dependencies - ivyScala ~= (_.map(_.withOverrideScalaVersion(false))) + scalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(false))) ) // Settings used for projects compiled only with Scala 2 @@ -151,7 +160,7 @@ object Build { // Avoid having to run `dotty-sbt-bridge/publishLocal` before compiling a bootstrapped project scalaCompilerBridgeSource := - (dottyOrganization %% "dotty-sbt-bridge" % "NOT_PUBLISHED" % Configurations.Component.name) + (dottyOrganization %% "dotty-sbt-bridge" % "NOT_PUBLISHED") .artifacts(Artifact.sources("dotty-sbt-bridge").withUrl( // We cannot use the `packageSrc` task because a setting cannot depend // on a task. Instead, we make `compile` below depend on the bridge `packageSrc` @@ -190,7 +199,7 @@ object Build { Seq( dottyOrganization % "dotty-library_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name, dottyOrganization % "dotty-compiler_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name - )//.map(_.withDottyCompat()) + )//.map(_.withDottyCompat(scalaVersion.value)) else Seq() }, @@ -273,8 +282,8 @@ object Build { // - publishes its own empty artifact "dotty" that depends on "dotty-library" and "dotty-compiler", // this is only necessary for compatibility with sbt which currently hardcodes the "dotty" artifact name lazy val dotty = project.in(file(".")).asDottyRoot(NonBootstrapped) - lazy val `dotty-bootstrapped` = project.asDottyRoot(Bootstrapped) - lazy val `dotty-optimised` = project.asDottyRoot(BootstrappedOptimised) + lazy val `dotty-bootstrapped` = project.asDottyRoot(Bootstrapped).disablePlugins(ScriptedPlugin) + lazy val `dotty-optimised` = project.asDottyRoot(BootstrappedOptimised).disablePlugins(ScriptedPlugin) lazy val `dotty-interfaces` = project.in(file("interfaces")). settings(commonScala2Settings). // Java-only project, so this is fine @@ -352,8 +361,8 @@ object Build { ) lazy val `dotty-doc` = project.in(file("doc-tool")).asDottyDoc(NonBootstrapped) - lazy val `dotty-doc-bootstrapped` = project.in(file("doc-tool")).asDottyDoc(Bootstrapped) - lazy val `dotty-doc-optimised` = project.in(file("doc-tool")).asDottyDoc(BootstrappedOptimised) + lazy val `dotty-doc-bootstrapped` = project.in(file("doc-tool")).asDottyDoc(Bootstrapped).disablePlugins(ScriptedPlugin) + lazy val `dotty-doc-optimised` = project.in(file("doc-tool")).asDottyDoc(BootstrappedOptimised).disablePlugins(ScriptedPlugin) def dottyDoc(implicit mode: Mode): Project = mode match { case NonBootstrapped => `dotty-doc` @@ -420,7 +429,7 @@ object Build { } catch { case _: UnsupportedOperationException | _: FileSystemException => // If the OS doesn't support symbolic links, copy the directory instead. - sbt.IO.copy(pairs, overwrite = true, preserveLastModified = true) + sbt.IO.copy(pairs, CopyOptions(overwrite = true, preserveLastModified = true, preserveExecutable = true)) } pairs.map(_._2) @@ -455,7 +464,7 @@ object Build { }.taskValue, // get libraries onboard - libraryDependencies ++= Seq("org.scala-sbt" % "compiler-interface" % "1.0.0-X16", + libraryDependencies ++= Seq("org.scala-sbt" % "compiler-interface" % "1.0.2", ("org.scala-lang.modules" % "scala-xml_2.12" % "1.0.6"), "com.novocode" % "junit-interface" % "0.11" % "test", "org.scala-lang" % "scala-library" % scalacVersion % "test"), @@ -498,7 +507,8 @@ object Build { println("Couldn't find scala-library on classpath, please run using script in bin dir instead") } else { val dottyLib = packageAll.value("dotty-library") - val exitCode = new java.lang.ProcessBuilder("java", "-classpath", s""".:$dottyLib:$scalaLib ${args.mkString(" ")}""") + val allArgs = Seq("java", "-classpath", s".:$dottyLib:$scalaLib") ++ args + val exitCode = new java.lang.ProcessBuilder(allArgs: _*) .inheritIO() .start() .waitFor() @@ -603,7 +613,8 @@ object Build { // used for tests that compile dotty path.contains("scala-asm") || // needed for the xsbti interface - path.contains("sbt-interface") + path.contains("compiler-interface") || + path.contains("util-interface") } yield "-Xbootclasspath/p:" + path val ci_build = // propagate if this is a ci build @@ -659,8 +670,8 @@ object Build { if (mode == NonBootstrapped) nonBootstrapedDottyCompilerSettings else bootstrapedDottyCompilerSettings lazy val `dotty-compiler` = project.in(file("compiler")).asDottyCompiler(NonBootstrapped) - lazy val `dotty-compiler-bootstrapped` = project.in(file("compiler")).asDottyCompiler(Bootstrapped) - lazy val `dotty-compiler-optimised` = project.in(file("compiler")).asDottyCompiler(BootstrappedOptimised) + lazy val `dotty-compiler-bootstrapped` = project.in(file("compiler")).asDottyCompiler(Bootstrapped).disablePlugins(ScriptedPlugin) + lazy val `dotty-compiler-optimised` = project.in(file("compiler")).asDottyCompiler(BootstrappedOptimised).disablePlugins(ScriptedPlugin) def dottyCompiler(implicit mode: Mode): Project = mode match { case NonBootstrapped => `dotty-compiler` @@ -677,8 +688,8 @@ object Build { ) lazy val `dotty-library` = project.in(file("library")).asDottyLibrary(NonBootstrapped) - lazy val `dotty-library-bootstrapped`: Project = project.in(file("library")).asDottyLibrary(Bootstrapped) - lazy val `dotty-library-optimised`: Project = project.in(file("library")).asDottyLibrary(BootstrappedOptimised) + lazy val `dotty-library-bootstrapped`: Project = project.in(file("library")).asDottyLibrary(Bootstrapped).disablePlugins(ScriptedPlugin) + lazy val `dotty-library-optimised`: Project = project.in(file("library")).asDottyLibrary(BootstrappedOptimised).disablePlugins(ScriptedPlugin) def dottyLibrary(implicit mode: Mode): Project = mode match { case NonBootstrapped => `dotty-library` @@ -710,10 +721,10 @@ object Build { description := "sbt compiler bridge for Dotty", resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api libraryDependencies ++= Seq( - "org.scala-sbt" % "compiler-interface" % "1.0.0-X16", - "org.scala-sbt" % "zinc-apiinfo_2.12" % "1.0.0-X16" % "test", - ("org.specs2" %% "specs2-core" % "3.9.1" % "test"),//.withDottyCompat() - ("org.specs2" %% "specs2-junit" % "3.9.1" % "test")//.withDottyCompat() + "org.scala-sbt" % "compiler-interface" % "1.0.2", + ("org.scala-sbt" %% "zinc-apiinfo" % "1.0.2" % "test").withDottyCompat(scalaVersion.value), + ("org.specs2" %% "specs2-core" % "3.9.1" % "test").withDottyCompat(scalaVersion.value), + ("org.specs2" %% "specs2-junit" % "3.9.1" % "test").withDottyCompat(scalaVersion.value) ), // The sources should be published with crossPaths := false since they // need to be compiled by the project using the bridge. @@ -727,7 +738,7 @@ object Build { ) lazy val `dotty-sbt-bridge` = project.in(file("sbt-bridge")).asDottySbtBridge(NonBootstrapped) - lazy val `dotty-sbt-bridge-bootstrapped` = project.in(file("sbt-bridge")).asDottySbtBridge(Bootstrapped) + lazy val `dotty-sbt-bridge-bootstrapped` = project.in(file("sbt-bridge")).asDottySbtBridge(Bootstrapped).disablePlugins(ScriptedPlugin) lazy val `dotty-language-server` = project.in(file("language-server")). dependsOn(dottyCompiler(Bootstrapped)). @@ -762,7 +773,7 @@ object Build { runTask(Runtime, mainClass, allArgs: _*) }.dependsOn(compile in (`vscode-dotty`, Compile)).evaluated - ) + ).disablePlugins(ScriptedPlugin) /** A sandbox to play with the Scala.js back-end of dotty. * @@ -807,8 +818,8 @@ object Build { ))) lazy val `dotty-bench` = project.in(file("bench")).asDottyBench(NonBootstrapped) - lazy val `dotty-bench-bootstrapped` = project.in(file("bench")).asDottyBench(Bootstrapped) - lazy val `dotty-bench-optimised` = project.in(file("bench")).asDottyBench(BootstrappedOptimised) + lazy val `dotty-bench-bootstrapped` = project.in(file("bench")).asDottyBench(Bootstrapped).disablePlugins(ScriptedPlugin) + lazy val `dotty-bench-optimised` = project.in(file("bench")).asDottyBench(BootstrappedOptimised).disablePlugins(ScriptedPlugin) // Depend on dotty-library so that sbt projects using dotty automatically // depend on the dotty-library @@ -846,22 +857,18 @@ object Build { // Keep in sync with inject-sbt-dotty.sbt libraryDependencies ++= Seq( Dependencies.`jackson-databind`, - "org.scala-sbt" % "compiler-interface" % "1.0.0-X16", - // "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value + "org.scala-sbt" % "compiler-interface" % "1.0.2" ), unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", - - sbtPlugin := true, - version := "0.1.7", - ScriptedPlugin.scriptedSettings, - ScriptedPlugin.sbtTestDirectory := baseDirectory.value / "sbt-test", - ScriptedPlugin.scriptedLaunchOpts += "-Dplugin.version=" + version.value, - ScriptedPlugin.scriptedLaunchOpts += "-Dplugin.scalaVersion=" + dottyVersion, - // By default scripted tests use $HOME/.ivy2 for the ivy cache. We need to override this value for the CI. - ScriptedPlugin.scriptedLaunchOpts ++= ivyPaths.value.ivyHome.map("-Dsbt.ivy.home=" + _.getAbsolutePath).toList, - ScriptedPlugin.scripted := ScriptedPlugin.scripted.dependsOn(Def.task { + version := "0.1.6-SNAPSHOT", + sbtTestDirectory := baseDirectory.value / "sbt-test", + scriptedLaunchOpts += "-Dplugin.version=" + version.value, + scriptedLaunchOpts += "-Dplugin.scalaVersion=" + dottyVersion, + // By default scripted tests use $HOME/.ivy2 for the ivy cache. We need to override this value for the CI. + scriptedLaunchOpts ++= ivyPaths.value.ivyHome.map("-Dsbt.ivy.home=" + _.getAbsolutePath).toList, + scripted := scripted.dependsOn(Def.task { val x0 = (publishLocal in `dotty-sbt-bridge-bootstrapped`).value val x1 = (publishLocal in `dotty-interfaces`).value val x2 = (publishLocal in `dotty-compiler-bootstrapped`).value @@ -875,7 +882,7 @@ object Build { lazy val `vscode-dotty` = project.in(file("vscode-dotty")). settings(commonSettings). settings( - EclipseKeys.skipProject := true, + EclipseKeys.skipProject := true, version := "0.1.2", // Keep in sync with package.json @@ -1005,7 +1012,8 @@ object Build { compile := { val inputs = (compileInputs in compile).value - import inputs.config._ + val inputOptions = inputs.options() + import inputOptions._ val s = streams.value val logger = s.log @@ -1028,6 +1036,7 @@ object Build { // Compile + val run = (runner in compile).value val cachedCompile = FileFunction.cached(cacheDir / "compile", FilesInfo.lastModified, FilesInfo.exists) { dependencies => @@ -1058,13 +1067,12 @@ object Build { } def doCompile(sourcesArgs: List[String]): Unit = { - val run = (runner in compile).value run.run("dotty.tools.dotc.Main", compilerCp, "-classpath" :: cpStr :: "-d" :: classesDirectory.getAbsolutePath() :: - options ++: + scalacOptions ++: sourcesArgs, - patchedLogger) foreach sys.error + patchedLogger) } // Work around the Windows limitation on command line length. @@ -1087,7 +1095,7 @@ object Build { cachedCompile((sources ++ allMyDependencies).toSet) // We do not have dependency analysis when compiling externally - sbt.inc.Analysis.Empty + sbt.internal.inc.Analysis.Empty } )) } @@ -1117,8 +1125,8 @@ object Build { ) lazy val dist = project.asDist(NonBootstrapped) - lazy val `dist-bootstrapped` = project.asDist(Bootstrapped) - lazy val `dist-optimised` = project.asDist(BootstrappedOptimised) + lazy val `dist-bootstrapped` = project.asDist(Bootstrapped).disablePlugins(ScriptedPlugin) + lazy val `dist-optimised` = project.asDist(BootstrappedOptimised).disablePlugins(ScriptedPlugin) implicit class ProjectDefinitions(val project: Project) extends AnyVal { diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala index 399a468591c8..c127c8fee000 100644 --- a/project/VersionUtil.scala +++ b/project/VersionUtil.scala @@ -6,7 +6,7 @@ object VersionUtil { if (System.getProperty("os.name").toLowerCase.contains("windows")) s"cmd.exe /c project\\scripts\\build\\$scriptName.bat -p" else s"project/scripts/build/$scriptName" - Process(cmd).lines.head.trim + Process(cmd).lineStream.head.trim } /** Seven letters of the SHA hash is considered enough to uniquely identify a diff --git a/project/build.properties b/project/build.properties index cd66fd542cf2..b7dd3cb2ae83 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.0.0-M6 +sbt.version=1.0.2 diff --git a/project/plugins.sbt b/project/plugins.sbt index 6b24922932e3..ef60384df746 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -3,17 +3,17 @@ // e.g. addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.1.0") // Scala IDE project file generator -addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.1.0") +addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.3") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.14") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.21") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.4") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") -addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.8.2") +addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.9.1") -addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.24") +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.27") diff --git a/project/scripted.sbt b/project/scripted.sbt index c3b5976d568e..a7d7ecccf2a9 100644 --- a/project/scripted.sbt +++ b/project/scripted.sbt @@ -1,4 +1,2 @@ // Used by the subproject dotty-bridge -// libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value -// val sbtV = sbtVersion.value -//addSbtPlugin("org.scala-sbt" %% "scripted-plugin" % "1.0.0-M6") +libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value diff --git a/sbt-bridge/src/xsbt/CompilerInterface.scala b/sbt-bridge/src/xsbt/CompilerInterface.scala index 144dcbc6e17e..631524e17ebb 100644 --- a/sbt-bridge/src/xsbt/CompilerInterface.scala +++ b/sbt-bridge/src/xsbt/CompilerInterface.scala @@ -3,7 +3,7 @@ */ package xsbt -import xsbti.{ AnalysisCallback, Logger, Problem, Reporter, Severity } +import xsbti.{ AnalysisCallback, Logger, Reporter, Severity } import xsbti.compile._ import Log.debug import java.io.File @@ -15,19 +15,19 @@ import dotty.tools.dotc.interfaces._ import java.net.URLClassLoader final class CompilerInterface { - def newCompiler(options: Array[String], output: Output, initialLog: Logger, - initialDelegate: Reporter, resident: Boolean): CachedCompiler = { + def newCompiler(options: Array[String], output: Output, initialLog: xsbti.Logger, + initialDelegate: xsbti.Reporter): CachedCompiler = { // The classloader that sbt uses to load the compiler bridge is broken // (see CompilerClassLoader#fixBridgeLoader for details). To workaround // this we construct our own ClassLoader and then run the following code // with it: - // new CachedCompilerImpl(options, output, resident) + // new CachedCompilerImpl(options, output) val bridgeLoader = getClass.getClassLoader val fixedLoader = CompilerClassLoader.fixBridgeLoader(bridgeLoader) val cciClass = fixedLoader.loadClass("xsbt.CachedCompilerImpl") cciClass.getConstructors.head - .newInstance(options, output, resident: java.lang.Boolean) + .newInstance(options, output) .asInstanceOf[CachedCompiler] } @@ -36,7 +36,7 @@ final class CompilerInterface { cached.run(sources, changes, callback, log, delegate, progress) } -class CachedCompilerImpl(args: Array[String], output: Output, resident: Boolean) extends CachedCompiler { +class CachedCompilerImpl(args: Array[String], output: Output) extends CachedCompiler { val outputArgs = output match { case multi: MultipleOutput => @@ -66,6 +66,6 @@ class CachedCompilerImpl(args: Array[String], output: Output, resident: Boolean) } } -class InterfaceCompileFailed(override val arguments: Array[String], override val problems: Array[Problem]) extends xsbti.CompileFailed { +class InterfaceCompileFailed(override val arguments: Array[String], override val problems: Array[xsbti.Problem]) extends xsbti.CompileFailed { override val toString = "Compilation failed" } diff --git a/sbt-bridge/src/xsbt/DelegatingReporter.scala b/sbt-bridge/src/xsbt/DelegatingReporter.scala index 0b096a2336e3..6ac533a9cb13 100644 --- a/sbt-bridge/src/xsbt/DelegatingReporter.scala +++ b/sbt-bridge/src/xsbt/DelegatingReporter.scala @@ -9,7 +9,7 @@ import reporting._ import reporting.diagnostic.MessageContainer import reporting.diagnostic.messages import core.Contexts._ -import xsbti.Position +import xsbti.{Position, Severity} import java.util.Optional final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter @@ -23,9 +23,9 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter def doReport(cont: MessageContainer)(implicit ctx: Context): Unit = { val severity = cont match { - case _: messages.Error => xsbti.Severity.Error - case _: messages.Warning => xsbti.Severity.Warn - case _ => xsbti.Severity.Info + case _: messages.Error => Severity.Error + case _: messages.Warning => Severity.Warn + case _ => Severity.Info } val position = @@ -52,7 +52,7 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter sb.append(explanation(cont.contained())) } - delegate.log(position, sb.toString(), severity) + delegate.log(Problem(position, sb.toString(), severity)) } private[this] def maybe[T](opt: Option[T]): Optional[T] = opt match { diff --git a/sbt-bridge/src/xsbt/Message.scala b/sbt-bridge/src/xsbt/Message.scala index 48f24f53349f..ef45577a7739 100644 --- a/sbt-bridge/src/xsbt/Message.scala +++ b/sbt-bridge/src/xsbt/Message.scala @@ -3,6 +3,8 @@ */ package xsbt +import java.util.function.Supplier + object Message { - def apply[T](s: => T) = new xsbti.F0[T] { def apply() = s } + def apply[T](s: => T) = new Supplier[T] { def get() = s } } diff --git a/sbt-bridge/src/xsbt/Problem.scala b/sbt-bridge/src/xsbt/Problem.scala new file mode 100644 index 000000000000..f92d8c284f89 --- /dev/null +++ b/sbt-bridge/src/xsbt/Problem.scala @@ -0,0 +1,12 @@ +package xsbt + +import xsbti.{Position, Severity} + +final case class Problem(override val position: Position, + override val message: String, + override val severity: Severity) extends xsbti.Problem { + override val category = "" + override def toString = s"[$severity] $position: $message" + +} + diff --git a/sbt-bridge/src/xsbt/ScaladocInterface.scala b/sbt-bridge/src/xsbt/ScaladocInterface.scala index 387b54e13673..c5124d8996e0 100644 --- a/sbt-bridge/src/xsbt/ScaladocInterface.scala +++ b/sbt-bridge/src/xsbt/ScaladocInterface.scala @@ -13,12 +13,12 @@ class ScaladocInterface { } class DottydocRunner(args: Array[String], log: Logger, delegate: xsbti.Reporter) { - def run(): Unit = delegate.log( + def run(): Unit = delegate.log(Problem( NoPosition, """|The dotty sbt-bridge currently does not support doc generation directly |via sbt. Please see the dotty documentation at dotty.epfl.ch""".stripMargin, Severity.Error - ) + )) private[this] val NoPosition = new xsbti.Position { val line = Optional.empty[Integer] diff --git a/sbt-bridge/test/xsbt/DependencySpecification.scala b/sbt-bridge/test/xsbt/DependencySpecification.scala index 60545091b666..0fbd285ee35d 100644 --- a/sbt-bridge/test/xsbt/DependencySpecification.scala +++ b/sbt-bridge/test/xsbt/DependencySpecification.scala @@ -8,80 +8,80 @@ import xsbt.api.SameAPI import org.specs2.mutable.Specification import org.specs2.runner.JUnitRunner -import ScalaCompilerForUnitTesting.ExtractedSourceDependencies +import xsbti.TestCallback.ExtractedClassDependencies @RunWith(classOf[JUnitRunner]) class DependencySpecification extends Specification { "Extracted source dependencies from public members" in { - val sourceDependencies = extractSourceDependenciesPublic - val memberRef = sourceDependencies.memberRef - val inheritance = sourceDependencies.inheritance - memberRef('A) === Set.empty - inheritance('A) === Set.empty - memberRef('B) === Set('A, 'D) - inheritance('B) === Set('D) - memberRef('C) === Set('A) - inheritance('C) === Set.empty - memberRef('D) === Set.empty - inheritance('D) === Set.empty - memberRef('E) === Set.empty - inheritance('E) === Set.empty - memberRef('F) === Set('A, 'B, 'C, 'D, 'E, 'G) - inheritance('F) === Set('A, 'E) - memberRef('H) === Set('B, 'E, 'G) + val classDependencies = extractClassDependenciesPublic + val memberRef = classDependencies.memberRef + val inheritance = classDependencies.inheritance + memberRef("A") === Set.empty + inheritance("A") === Set.empty + memberRef("B") === Set("A", "D") + inheritance("B") === Set("D") + memberRef("C") === Set("A") + inheritance("C") === Set.empty + memberRef("D") === Set.empty + inheritance("D") === Set.empty + memberRef("E") === Set.empty + inheritance("E") === Set.empty + memberRef("F") === Set("A", "B", "C", "D", "E", "G") + inheritance("F") === Set("A", "E") + memberRef("H") === Set("B", "E", "G") // aliases and applied type constructors are expanded so we have inheritance dependency on B - inheritance('H) === Set('B, 'E) + inheritance("H") === Set("B", "E") } "Extracted source dependencies from private members" in { - val sourceDependencies = extractSourceDependenciesPrivate - val memberRef = sourceDependencies.memberRef - val inheritance = sourceDependencies.inheritance - memberRef('A) === Set.empty - inheritance('A) === Set.empty - memberRef('B) === Set.empty - inheritance('B) === Set.empty - memberRef('C) === Set('A) - inheritance('C) === Set('A) - memberRef('D) === Set('B) - inheritance('D) === Set('B) + val classDependencies = extractClassDependenciesPrivate + val memberRef = classDependencies.memberRef + val inheritance = classDependencies.inheritance + memberRef("A") === Set.empty + inheritance("A") === Set.empty + memberRef("B") === Set.empty + inheritance("B") === Set.empty + memberRef("C.Inner1") === Set("A") + inheritance("C.Inner1") === Set("A") + memberRef("D._$Inner2") === Set("B") + inheritance("D._$Inner2") === Set("B") } "Extracted source dependencies with trait as first parent" in { - val sourceDependencies = extractSourceDependenciesTraitAsFirstPatent - val memberRef = sourceDependencies.memberRef - val inheritance = sourceDependencies.inheritance - memberRef('A) === Set.empty - inheritance('A) === Set.empty - memberRef('B) === Set('A) - inheritance('B) === Set('A) + val classDependencies = extractClassDependenciesTraitAsFirstPatent + val memberRef = classDependencies.memberRef + val inheritance = classDependencies.inheritance + memberRef("A") === Set.empty + inheritance("A") === Set.empty + memberRef("B") === Set("A") + inheritance("B") === Set("A") // verify that memberRef captures the oddity described in documentation of `Relations.inheritance` // we are mainly interested whether dependency on A is captured in `memberRef` relation so // the invariant that says that memberRef is superset of inheritance relation is preserved - memberRef('C) === Set('A, 'B) - inheritance('C) === Set('A, 'B) + memberRef("C") === Set("A", "B") + inheritance("C") === Set("A", "B") // same as above but indirect (C -> B -> A), note that only A is visible here - memberRef('D) === Set('A, 'C) - inheritance('D) === Set('A, 'C) + memberRef("D") === Set("A", "C") + inheritance("D") === Set("A", "C") } /* "Extracted source dependencies from macro arguments" in { - val sourceDependencies = extractSourceDependenciesFromMacroArgument - val memberRef = sourceDependencies.memberRef - val inheritance = sourceDependencies.inheritance - - memberRef('A) === Set('B, 'C) - inheritance('A) === Set.empty - memberRef('B) === Set.empty - inheritance('B) === Set.empty - memberRef('C) === Set.empty - inheritance('C) === Set.empty + val classDependencies = extractClassDependenciesFromMacroArgument + val memberRef = classDependencies.memberRef + val inheritance = classDependencies.inheritance + + memberRef("A") === Set("B", "C") + inheritance("A") === Set.empty + memberRef("B") === Set.empty + inheritance("B") === Set.empty + memberRef("C") === Set.empty + inheritance("C") === Set.empty } */ - private def extractSourceDependenciesPublic: ExtractedSourceDependencies = { + private def extractClassDependenciesPublic: ExtractedClassDependencies = { val srcA = "class A" val srcB = "class B extends D[A]" val srcC = """|class C { @@ -96,38 +96,38 @@ class DependencySpecification extends Specification { // E verifies the core type gets pulled out val srcH = "trait H extends G.T[Int] with (E[Int] @unchecked)" - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val sourceDependencies = compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, - 'D -> srcD, 'E -> srcE, 'F -> srcF, 'G -> srcG, 'H -> srcH) - sourceDependencies + val compilerForTesting = new ScalaCompilerForUnitTesting + val classDependencies = compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, + srcD, srcE, srcF, srcG, srcH) + classDependencies } - private def extractSourceDependenciesPrivate: ExtractedSourceDependencies = { + private def extractClassDependenciesPrivate: ExtractedClassDependencies = { val srcA = "class A" val srcB = "class B" val srcC = "class C { private class Inner1 extends A }" val srcD = "class D { def foo: Unit = { class Inner2 extends B } }" - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val sourceDependencies = - compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD) - sourceDependencies + val compilerForTesting = new ScalaCompilerForUnitTesting + val classDependencies = + compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, srcD) + classDependencies } - private def extractSourceDependenciesTraitAsFirstPatent: ExtractedSourceDependencies = { + private def extractClassDependenciesTraitAsFirstPatent: ExtractedClassDependencies = { val srcA = "class A" val srcB = "trait B extends A" val srcC = "trait C extends B" val srcD = "class D extends C" - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val sourceDependencies = - compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD) - sourceDependencies + val compilerForTesting = new ScalaCompilerForUnitTesting + val classDependencies = + compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, srcD) + classDependencies } /* - private def extractSourceDependenciesFromMacroArgument: ExtractedSourceDependencies = { + private def extractClassDependenciesFromMacroArgument: ExtractedClassDependencies = { val srcA = "class A { println(B.printTree(C.foo)) }" val srcB = """ |import scala.language.experimental.macros @@ -143,9 +143,9 @@ class DependencySpecification extends Specification { val srcC = "object C { val foo = 1 }" val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val sourceDependencies = + val classDependencies = compilerForTesting.extractDependenciesFromSrcs(List(Map('B -> srcB, 'C -> srcC), Map('A -> srcA))) - sourceDependencies + classDependencies } */ } diff --git a/sbt-bridge/test/xsbt/ExtractAPISpecification.scala b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala index ce87134bc16d..8d867511e899 100644 --- a/sbt-bridge/test/xsbt/ExtractAPISpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala @@ -16,26 +16,25 @@ class ExtractAPISpecification extends Specification { def stableExistentialNames: Boolean = { def compileAndGetFooMethodApi(src: String): Def = { - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = false) + val compilerForTesting = new ScalaCompilerForUnitTesting val sourceApi = compilerForTesting.extractApiFromSrc(src) - val FooApi = sourceApi.definitions().find(_.name() == "Foo").get.asInstanceOf[ClassLike] + val FooApi = sourceApi.find(_.name() == "Foo").get.asInstanceOf[ClassLike] val fooMethodApi = FooApi.structure().declared().find(_.name == "foo").get fooMethodApi.asInstanceOf[Def] } val src1 = """ - |class Box[T] - |class Foo { - | def foo: Box[_] = null - | - }""".stripMargin + |class Box[T] + |class Foo { + | def foo: Box[_] = null + | + }""".stripMargin val fooMethodApi1 = compileAndGetFooMethodApi(src1) val src2 = """ - |class Box[T] - |class Foo { - | def bar: Box[_] = null - | def foo: Box[_] = null - | - }""".stripMargin + |class Box[T] + |class Foo { + | def bar: Box[_] = null + | def foo: Box[_] = null + |}""".stripMargin val fooMethodApi2 = compileAndGetFooMethodApi(src2) fooMethodApi1 == fooMethodApi2 @@ -52,13 +51,11 @@ class ExtractAPISpecification extends Specification { * See https://github.com/sbt/sbt/issues/2504 */ "Self variable and no self type" in { - def selectNamer(api: SourceAPI): ClassLike = { + def selectNamer(api: Seq[Definition]): ClassLike = { def selectClass(defs: Iterable[Definition], name: String): ClassLike = defs.collectFirst { case cls: ClassLike if cls.name == name => cls }.get - val global = selectClass(api.definitions, "Global") - val foo = selectClass(global.structure.declared, "Global.Foo") - selectClass(foo.structure.inherited, "Namers.Namer") + selectClass(api, "Namers.Namer") } val src1 = """|class Namers { @@ -70,7 +67,7 @@ class ExtractAPISpecification extends Specification { | class Foo extends Namers |} |""".stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = false) + val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApisFromSrcs(reuseCompilerInstance = false)(List(src1, src2), List(src2)) val _ :: src2Api1 :: src2Api2 :: Nil = apis.toList val namerApi1 = selectNamer(src2Api1) @@ -86,7 +83,7 @@ class ExtractAPISpecification extends Specification { * with our without a self variable. */ "Self type" in { - def collectFirstClass(defs: Array[Definition]): ClassLike = defs.collectFirst { + def collectFirstClass(defs: Iterable[Definition]): ClassLike = defs.collectFirst { case c: ClassLike => c }.get val srcX = "trait X" @@ -99,11 +96,11 @@ class ExtractAPISpecification extends Specification { val srcC6 = "class C6 extends AnyRef with X { self: X with Y => }" // val srcC7 = "class C7 { _ => }" // DOTTY: Syntax not supported val srcC8 = "class C8 { self => }" - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = false) + val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApisFromSrcs(reuseCompilerInstance = true)( List(srcX, srcY, srcC1, srcC2, srcC3, srcC4, srcC5, srcC6, srcC8) - ).map(x => collectFirstClass(x.definitions)) - val emptyType = new EmptyType + ).map(collectFirstClass) + val emptyType = EmptyType.create() def hasSelfType(c: ClassLike): Boolean = c.selfType != emptyType val (withSelfType, withoutSelfType) = apis.partition(hasSelfType) diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index 5044c771872e..eda9533fcee4 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -26,64 +26,64 @@ class ExtractUsedNamesSpecification extends Specification { "Unit" ) - "imported name" in { - val src = """ - |package a { class A } - |package b { - | import a.{A => A2} - |}""".stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) - val expectedNames = standardNames ++ Set("a", "A", "A2", "b") - usedNames === expectedNames - } + "imported name" in { + val src = """ + |package a { class A } + |package b { + | import a.{A => A2} + |}""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) + val expectedNames = standardNames ++ Set("a", "A", "A2", "b") + usedNames("a.A") === expectedNames + } // test covers https://github.com/gkossakowski/sbt/issues/6 "names in type tree" in { val srcA = """| - |package a { - | class A { - | class C { class D } - | } - | class B[T] - | class BB - |}""".stripMargin + |package a { + | class A { + | class C { class D } + | } + | class B[T] + | class BB + |}""".stripMargin val srcB = """| - |package b { - | abstract class X { - | def foo: a.A#C#D - | def bar: a.B[a.BB] - | } - |}""".stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) + |package b { + | abstract class X { + | def foo: a.A#C#D + | def bar: a.B[a.BB] + | } + |}""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) // DOTTY: unlike the scalac sbt phase, this does not contain "X", I believe this is safe // TODO: report issue against sbt suggesting that they do the same val expectedNames = standardNames ++ Set("a", "A", "B", "C", "D", "b", "BB") - usedNames === expectedNames + usedNames("b.X") === expectedNames } - // test for https://github.com/gkossakowski/sbt/issues/5 - "symbolic names" in { - val srcA = """| - |class A { - | def `=`: Int = 3 - |}""".stripMargin - val srcB = """| - |class B { - | def foo(a: A) = a.`=` - |}""".stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) + // test for https://github.com/gkossakowski/sbt/issues/5 + "symbolic names" in { + val srcA = """| + |class A { + | def `=`: Int = 3 + |}""".stripMargin + val srcB = """| + |class B { + | def foo(a: A) = a.`=` + |}""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - // DOTTY TODO: "Int" is not actually used, but we collect it because - // it's the inferred return type so it appears in a TypeTree - // We could avoid this by checking if the untyped tree has a return type - // but is it worth it? Revisit this after https://github.com/sbt/sbt/issues/1104 - // has landed. - val expectedNames = standardNames ++ Set("A", "a", "=", "Int") - usedNames === expectedNames - } + // DOTTY TODO: "Int" is not actually used, but we collect it because + // it's the inferred return type so it appears in a TypeTree + // We could avoid this by checking if the untyped tree has a return type + // but is it worth it? Revisit this after https://github.com/sbt/sbt/issues/1104 + // has landed. + val expectedNames = standardNames ++ Set("A", "a", "=", "Int") + usedNames("B") === expectedNames + } "extract names in the types of trees" in { val src1 = """|class X0 @@ -104,55 +104,86 @@ class ExtractUsedNamesSpecification extends Specification { | def foo(m: M): N = ??? | def bar[Param >: P1 <: P0](p: Param): Param = ??? |}""".stripMargin - val src2 = """|object Test { + val src2 = """|object Test_lista { | val x = B.lista - | val y = B.at - | val z = B.as - | B.foo(???) - | B.bar(???) - |}""".stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) + |} + |object Test_at { + | val x = B.at + |} + |object Test_as { + | val x = B.as + |} + |object Test_foo { + | val x = B.foo(???) + |} + |object Test_bar { + | val x = B.bar(???) + |} + |""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(src1, src2) - val expectedNames = standardNames ++ Set("Test", "Test$", "B", "B$", - "Predef", "Predef$", "???", "Nothing", - "lista", "List", "A", - "at", "T", "X1", "X0", - "as", "S", "Y", - "foo", "M", "N", - "bar", "P1", "P0") - usedNames === expectedNames + val expectedNames_lista = standardNames ++ Set("Test_lista", "Test_lista$", "B", "B$", "lista", "List", "A") + val expectedNames_at = standardNames ++ Set("Test_at", "Test_at$", "B", "B$", "at", "A", "T", "X0", "X1") + val expectedNames_as = standardNames ++ Set("Test_as", "Test_as$", "B", "B$", "as", "S", "Y") + val expectedNames_foo = standardNames ++ Set("Test_foo", + "Test_foo$", + "B", + "B$", + "foo", + "M", + "N", + "Predef", + "Predef$", + "???", + "Nothing") + val expectedNames_bar = standardNames ++ Set("Test_bar", + "Test_bar$", + "B", + "B$", + "bar", + "P1", + "P0", + "Predef", + "Predef$", + "???", + "Nothing") + usedNames("Test_lista") === expectedNames_lista + usedNames("Test_at") === expectedNames_at + usedNames("Test_as") === expectedNames_as + usedNames("Test_foo") === expectedNames_foo + usedNames("Test_bar") === expectedNames_bar } - // test for https://github.com/gkossakowski/sbt/issues/3 - "used names from the same compilation unit" in { - val src = "class A { def foo: Int = 0; def bar: Int = foo }" - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) - val expectedNames = standardNames ++ Set("A", "foo", "Int") - usedNames === expectedNames - } + // test for https://github.com/gkossakowski/sbt/issues/3 + "used names from the same compilation unit" in { + val src = "class A { def foo: Int = 0; def bar: Int = foo }" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) + val expectedNames = standardNames ++ Set("A", "foo", "Int") + usedNames("A") === expectedNames + } - // pending test for https://issues.scala-lang.org/browse/SI-7173 - "names of constants" in { - val src = "class A { final val foo = 12; def bar: Int = foo }" - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) - val expectedNames = standardNames ++ Set("A", "foo", "Int") - usedNames === expectedNames - } + // pending test for https://issues.scala-lang.org/browse/SI-7173 + "names of constants" in { + val src = "class A { final val foo = 12; def bar: Int = foo }" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) + val expectedNames = standardNames ++ Set("A", "foo", "Int") + usedNames("A") === expectedNames + } - // pending test for https://github.com/gkossakowski/sbt/issues/4 - // TODO: we should fix it by having special treatment of `selectDynamic` and `applyDynamic` calls - "names from method calls on Dynamic" in { - val srcA = """|import scala.language.dynamics - |class A extends Dynamic { - | def selectDynamic(name: String): Int = name.length - |}""".stripMargin - val srcB = "class B { def foo(a: A): Int = a.bla }" - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - val expectedNames = standardNames ++ Set("B", "A", "a", "Int", "selectDynamic", "bla") - usedNames === expectedNames - }.pendingUntilFixed("Call to Dynamic is desugared in type checker so Select nodes is turned into string literal.") + // pending test for https://github.com/gkossakowski/sbt/issues/4 + // TODO: we should fix it by having special treatment of `selectDynamic` and `applyDynamic` calls + "names from method calls on Dynamic" in { + val srcA = """|import scala.language.dynamics + |class A extends Dynamic { + | def selectDynamic(name: String): Int = name.length + |}""".stripMargin + val srcB = "class B { def foo(a: A): Int = a.bla }" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) + val expectedNames = standardNames ++ Set("B", "A", "a", "Int", "selectDynamic", "bla") + usedNames("") === expectedNames + }.pendingUntilFixed("Call to Dynamic is desugared in type checker so Select nodes is turned into string literal.") } diff --git a/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala b/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala index fb27f9b9d276..e81d58a07744 100644 --- a/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala +++ b/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala @@ -4,29 +4,26 @@ package xsbt import xsbti.compile.SingleOutput import java.io.File import xsbti._ -import xsbti.api.SourceAPI -import sbt.IO._ -import xsbti.api.ClassLike -import xsbti.api.Definition -import xsbti.api.Def +import sbt.io.IO +import xsbti.api.{ ClassLike, Def, DependencyContext } +import DependencyContext._ import xsbt.api.SameAPI -import sbt.ConsoleLogger -import xsbti.DependencyContext._ +import sbt.internal.util.ConsoleLogger -import ScalaCompilerForUnitTesting.ExtractedSourceDependencies +import TestCallback.ExtractedClassDependencies /** * Provides common functionality needed for unit tests that require compiling * source code using Scala compiler. */ -class ScalaCompilerForUnitTesting(nameHashing: Boolean, includeSynthToNameHashing: Boolean = false) { +class ScalaCompilerForUnitTesting { import scala.language.reflectiveCalls /** * Compiles given source code using Scala compiler and returns API representation * extracted by ExtractAPI class. */ - def extractApiFromSrc(src: String): SourceAPI = { + def extractApiFromSrc(src: String): Seq[ClassLike] = { val (Seq(tempSrcFile), analysisCallback) = compileSrcs(src) analysisCallback.apis(tempSrcFile) } @@ -35,27 +32,50 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean, includeSynthToNameHashin * Compiles given source code using Scala compiler and returns API representation * extracted by ExtractAPI class. */ - def extractApisFromSrcs(reuseCompilerInstance: Boolean)(srcs: List[String]*): Seq[SourceAPI] = { + def extractApisFromSrcs(reuseCompilerInstance: Boolean)(srcs: List[String]*): Seq[Seq[ClassLike]] = { val (tempSrcFiles, analysisCallback) = compileSrcs(srcs.toList, reuseCompilerInstance) tempSrcFiles.map(analysisCallback.apis) } - def extractUsedNamesFromSrc(src: String): Set[String] = { - val (Seq(tempSrcFile), analysisCallback) = compileSrcs(src) - analysisCallback.usedNames(tempSrcFile) - } - /** * Extract used names from src provided as the second argument. + * If `assertDefaultScope` is set to true it will fail if there is any name used in scope other then Default * * The purpose of the first argument is to define names that the second * source is going to refer to. Both files are compiled in the same compiler * Run but only names used in the second src file are returned. */ - def extractUsedNamesFromSrc(definitionSrc: String, actualSrc: String): Set[String] = { + def extractUsedNamesFromSrc( + definitionSrc: String, + actualSrc: String, + assertDefaultScope: Boolean = true + ): Map[String, Set[String]] = { // we drop temp src file corresponding to the definition src file val (Seq(_, tempSrcFile), analysisCallback) = compileSrcs(definitionSrc, actualSrc) - analysisCallback.usedNames(tempSrcFile) + + if (assertDefaultScope) for { + (className, used) <- analysisCallback.usedNamesAndScopes + analysisCallback.TestUsedName(name, scopes) <- used + } assert(scopes.size() == 1 && scopes.contains(UseScope.Default), s"$className uses $name in $scopes") + + val classesInActualSrc = analysisCallback.classNames(tempSrcFile).map(_._1) + classesInActualSrc.map(className => className -> analysisCallback.usedNames(className)).toMap + } + + /** + * Extract used names from the last source file in `sources`. + * + * The previous source files are provided to successfully compile examples. + * Only the names used in the last src file are returned. + */ + def extractUsedNamesFromSrc(sources: String*): Map[String, Set[String]] = { + val (srcFiles, analysisCallback) = compileSrcs(sources: _*) + srcFiles + .map { srcFile => + val classesInSrc = analysisCallback.classNames(srcFile).map(_._1) + classesInSrc.map(className => className -> analysisCallback.usedNames(className)).toMap + } + .reduce(_ ++ _) } /** @@ -70,42 +90,23 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean, includeSynthToNameHashin * Symbols are used to express extracted dependencies between source code snippets. This way we have * file system-independent way of testing dependencies between source code "files". */ - def extractDependenciesFromSrcs(srcs: List[Map[Symbol, String]]): ExtractedSourceDependencies = { - val rawGroupedSrcs = srcs.map(_.values.toList) - val symbols = srcs.flatMap(_.keys) - val (tempSrcFiles, testCallback) = compileSrcs(rawGroupedSrcs, reuseCompilerInstance = true) - val fileToSymbol = (tempSrcFiles zip symbols).toMap - - val memberRefFileDeps = testCallback.sourceDependencies collect { - // false indicates that those dependencies are not introduced by inheritance + def extractDependenciesFromSrcs(srcs: List[List[String]]): ExtractedClassDependencies = { + val (_, testCallback) = compileSrcs(srcs, reuseCompilerInstance = true) + + val memberRefDeps = testCallback.classDependencies collect { case (target, src, DependencyByMemberRef) => (src, target) } - val inheritanceFileDeps = testCallback.sourceDependencies collect { - // true indicates that those dependencies are introduced by inheritance + val inheritanceDeps = testCallback.classDependencies collect { case (target, src, DependencyByInheritance) => (src, target) } - def toSymbols(src: File, target: File): (Symbol, Symbol) = (fileToSymbol(src), fileToSymbol(target)) - val memberRefDeps = memberRefFileDeps map { case (src, target) => toSymbols(src, target) } - val inheritanceDeps = inheritanceFileDeps map { case (src, target) => toSymbols(src, target) } - def pairsToMultiMap[A, B](pairs: Seq[(A, B)]): Map[A, Set[B]] = { - import scala.collection.mutable.{ HashMap, MultiMap } - val emptyMultiMap = new HashMap[A, scala.collection.mutable.Set[B]] with MultiMap[A, B] - val multiMap = pairs.foldLeft(emptyMultiMap) { - case (acc, (key, value)) => - acc.addBinding(key, value) - } - // convert all collections to immutable variants - multiMap.toMap.mapValues(_.toSet).withDefaultValue(Set.empty) + val localInheritanceDeps = testCallback.classDependencies collect { + case (target, src, LocalDependencyByInheritance) => (src, target) } - - ExtractedSourceDependencies(pairsToMultiMap(memberRefDeps), pairsToMultiMap(inheritanceDeps)) + ExtractedClassDependencies.fromPairs(memberRefDeps, inheritanceDeps, localInheritanceDeps) } - def extractDependenciesFromSrcs(srcs: (Symbol, String)*): ExtractedSourceDependencies = { - val symbols = srcs.map(_._1) - assert(symbols.distinct.size == symbols.size, - s"Duplicate symbols for srcs detected: $symbols") - extractDependenciesFromSrcs(List(srcs.toMap)) + def extractDependenciesFromSrcs(srcs: String*): ExtractedClassDependencies = { + extractDependenciesFromSrcs(List(srcs.toList)) } /** @@ -124,12 +125,12 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean, includeSynthToNameHashin * The sequence of temporary files corresponding to passed snippets and analysis * callback is returned as a result. */ - private def compileSrcs(groupedSrcs: List[List[String]], + def compileSrcs(groupedSrcs: List[List[String]], reuseCompilerInstance: Boolean): (Seq[File], TestCallback) = { // withTemporaryDirectory { temp => { - val temp = createTemporaryDirectory - val analysisCallback = new TestCallback(nameHashing, includeSynthToNameHashing) + val temp = IO.createTemporaryDirectory + val analysisCallback = new TestCallback val classesDir = new File(temp, "classes") classesDir.mkdir() @@ -158,13 +159,13 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean, includeSynthToNameHashin } } - private def compileSrcs(srcs: String*): (Seq[File], TestCallback) = { + def compileSrcs(srcs: String*): (Seq[File], TestCallback) = { compileSrcs(List(srcs.toList), reuseCompilerInstance = true) } private def prepareSrcFile(baseDir: File, fileName: String, src: String): File = { val srcFile = new File(baseDir, fileName) - sbt.IO.write(srcFile, src) + IO.write(srcFile, src) srcFile } @@ -184,14 +185,11 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean, includeSynthToNameHashin def hasErrors: Boolean = false def hasWarnings: Boolean = false def printWarnings(): Unit = () - def problems: Array[Problem] = Array.empty - def log(pos: Position, msg: String, sev: Severity): Unit = println(msg) + def problems(): Array[xsbti.Problem] = Array.empty + def log(problem: xsbti.Problem): Unit = println(problem.message) def comment(pos: Position, msg: String): Unit = () def printSummary(): Unit = () } } -object ScalaCompilerForUnitTesting { - case class ExtractedSourceDependencies(memberRef: Map[Symbol, Set[Symbol]], inheritance: Map[Symbol, Set[Symbol]]) -} diff --git a/sbt-bridge/test/xsbti/TestCallback.scala b/sbt-bridge/test/xsbti/TestCallback.scala index 99c8d963d555..7a065d5abdc9 100644 --- a/sbt-bridge/test/xsbti/TestCallback.scala +++ b/sbt-bridge/test/xsbti/TestCallback.scala @@ -3,33 +3,90 @@ package xsbti import java.io.File import scala.collection.mutable.ArrayBuffer -import xsbti.api.SourceAPI -import xsbti.DependencyContext._ +import xsbti.api.ClassLike +import xsbti.api.DependencyContext +import DependencyContext._ +import java.util.EnumSet -class TestCallback(override val nameHashing: Boolean, override val includeSynthToNameHashing: Boolean) extends AnalysisCallback +class TestCallback extends AnalysisCallback { - val sourceDependencies = new ArrayBuffer[(File, File, DependencyContext)] - val binaryDependencies = new ArrayBuffer[(File, String, File, DependencyContext)] - val products = new ArrayBuffer[(File, File, String)] - val usedNames = scala.collection.mutable.Map.empty[File, Set[String]].withDefaultValue(Set.empty) - val apis: scala.collection.mutable.Map[File, SourceAPI] = scala.collection.mutable.Map.empty - - def sourceDependency(dependsOn: File, source: File, inherited: Boolean): Unit = { - val context = if(inherited) DependencyByInheritance else DependencyByMemberRef - sourceDependency(dependsOn, source, context) - } - def sourceDependency(dependsOn: File, source: File, context: DependencyContext): Unit = { sourceDependencies += ((dependsOn, source, context)) } - def binaryDependency(binary: File, name: String, source: File, inherited: Boolean): Unit = { - val context = if(inherited) DependencyByInheritance else DependencyByMemberRef - binaryDependency(binary, name, source, context) - } - def binaryDependency(binary: File, name: String, source: File, context: DependencyContext): Unit = { binaryDependencies += ((binary, name, source, context)) } - def generatedClass(source: File, module: File, name: String): Unit = { products += ((source, module, name)) } - - def usedName(source: File, name: String): Unit = { usedNames(source) += name } - def api(source: File, sourceAPI: SourceAPI): Unit = { - assert(!apis.contains(source), s"The `api` method should be called once per source file: $source") - apis(source) = sourceAPI - } - def problem(category: String, pos: xsbti.Position, message: String, severity: xsbti.Severity, reported: Boolean): Unit = () + case class TestUsedName(name: String, scopes: EnumSet[UseScope]) + val classDependencies = new ArrayBuffer[(String, String, DependencyContext)] + val binaryDependencies = new ArrayBuffer[(File, String, String, File, DependencyContext)] + val products = new ArrayBuffer[(File, File)] + val usedNamesAndScopes = scala.collection.mutable.Map.empty[String, Set[TestUsedName]].withDefaultValue(Set.empty) + val classNames = scala.collection.mutable.Map.empty[File, Set[(String, String)]].withDefaultValue(Set.empty) + val apis: scala.collection.mutable.Map[File, Seq[ClassLike]] = scala.collection.mutable.Map.empty + + def usedNames = usedNamesAndScopes.mapValues(_.map(_.name)) + + override def startSource(source: File): Unit = { + assert(!apis.contains(source), s"startSource can be called only once per source file: $source") + apis(source) = Seq.empty + } + + override def binaryDependency(binary: File, name: String, fromClassName: String, source: File, context: DependencyContext): Unit = { + binaryDependencies += ((binary, name, fromClassName, source, context)) + } + + def generatedNonLocalClass(source: File, + module: File, + binaryClassName: String, + srcClassName: String): Unit = { + products += ((source, module)) + classNames(source) += ((srcClassName, binaryClassName)) + () + } + + def generatedLocalClass(source: File, module: File): Unit = { + products += ((source, module)) + () + } + + + override def classDependency(onClassName: String, sourceClassName: String, context: DependencyContext): Unit = { + if (onClassName != sourceClassName) classDependencies += ((onClassName, sourceClassName, context)) + } + + override def usedName(className: String, name: String, scopes: EnumSet[UseScope]): Unit = { + usedNamesAndScopes(className) += TestUsedName(name, scopes) + } + override def api(source: File, classApi: ClassLike): Unit = { + apis(source) = classApi +: apis(source) + } + override def problem(category: String, pos: xsbti.Position, message: String, severity: xsbti.Severity, reported: Boolean): Unit = () + override def dependencyPhaseCompleted(): Unit = () + override def apiPhaseCompleted(): Unit = () + override def enabled(): Boolean = true + def mainClass(source: File, className: String): Unit = () + +} + +object TestCallback { + case class ExtractedClassDependencies(memberRef: Map[String, Set[String]], + inheritance: Map[String, Set[String]], + localInheritance: Map[String, Set[String]]) + object ExtractedClassDependencies { + def fromPairs( + memberRefPairs: Seq[(String, String)], + inheritancePairs: Seq[(String, String)], + localInheritancePairs: Seq[(String, String)] + ): ExtractedClassDependencies = { + ExtractedClassDependencies(pairsToMultiMap(memberRefPairs), + pairsToMultiMap(inheritancePairs), + pairsToMultiMap(localInheritancePairs)) + } + + private def pairsToMultiMap[A, B](pairs: Seq[(A, B)]): Map[A, Set[B]] = { + import scala.collection.mutable.{ HashMap, MultiMap } + val emptyMultiMap = new HashMap[A, scala.collection.mutable.Set[B]] with MultiMap[A, B] + val multiMap = pairs.foldLeft(emptyMultiMap) { + case (acc, (key, value)) => + acc.addBinding(key, value) + } + // convert all collections to immutable variants + multiMap.toMap.mapValues(_.toSet).withDefaultValue(Set.empty) + } + } } + diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala index 240e51479ce3..cfb913bb236f 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala @@ -55,7 +55,7 @@ object DottyIDEPlugin extends AutoPlugin { else { def matchingSetting(setting: Setting[_]) = setting.key.key == scalaVersion.key && - setting.key.scope.project.fold(ref => projRefs.contains(ref), ifGlobal = true, ifThis = true) + setting.key.scope.project.fold(ref => projRefs.contains(ref), ifZero = true, ifThis = true) val newSettings = extracted.session.mergeSettings.collect { case setting if matchingSetting(setting) => @@ -205,9 +205,9 @@ object DottyIDEPlugin extends AutoPlugin { origState } - private def projectConfigTask(config: Configuration): Initialize[Task[Option[ProjectConfig]]] = Def.task { - if ((sources in config).value.isEmpty) None - else { + private def projectConfigTask(config: Configuration): Initialize[Task[Option[ProjectConfig]]] = Def.taskDyn { + if ((sources in config).value.isEmpty) Def.task { None } + else Def.task { // Not needed to generate the config, but this guarantees that the // generated config is usable by an IDE without any extra compilation // step. diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index f413efb5520d..611677351d0d 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -51,38 +51,35 @@ object DottyPlugin extends AutoPlugin { nightly } - // implicit class DottyCompatModuleID(moduleID: ModuleID) { - // /** If this ModuleID cross-version is a Dotty version, replace it - // * by the Scala 2.x version that the Dotty version is retro-compatible with, - // * otherwise do nothing. - // * - // * This setting is useful when your build contains dependencies that have only - // * been published with Scala 2.x, if you have: - // * {{{ - // * libraryDependencies += "a" %% "b" % "c" - // * }}} - // * you can replace it by: - // * {{{ - // * libraryDependencies += ("a" %% "b" % "c").withDottyCompat() - // * }}} - // * This will have no effect when compiling with Scala 2.x, but when compiling - // * with Dotty this will change the cross-version to a Scala 2.x one. This - // * works because Dotty is currently retro-compatible with Scala 2.x. - // * - // * NOTE: Dotty's retro-compatibility with Scala 2.x will be dropped before - // * Dotty is released, you should not rely on it. - // */ - // def withDottyCompat(): ModuleID = - // moduleID.crossVersion match { - // case _: librarymanagement.Binary => - // moduleID.cross(CrossVersion.binaryMapped { - // case version if version.startsWith("0.") => "2.11" - // case version => version - // }) - // case _ => - // moduleID - // } - // } + implicit class DottyCompatModuleID(moduleID: ModuleID) { + /** If this ModuleID cross-version is a Dotty version, replace it + * by the Scala 2.x version that the Dotty version is retro-compatible with, + * otherwise do nothing. + * + * This setting is useful when your build contains dependencies that have only + * been published with Scala 2.x, if you have: + * {{{ + * libraryDependencies += "a" %% "b" % "c" + * }}} + * you can replace it by: + * {{{ + * libraryDependencies += ("a" %% "b" % "c").withDottyCompat(scalaVersion.value) + * }}} + * This will have no effect when compiling with Scala 2.x, but when compiling + * with Dotty this will change the cross-version to a Scala 2.x one. This + * works because Dotty is currently retro-compatible with Scala 2.x. + * + * NOTE: Dotty's retro-compatibility with Scala 2.x will be dropped before + * Dotty is released, you should not rely on it. + */ + def withDottyCompat(scalaVersion: String): ModuleID = + moduleID.crossVersion match { + case _: librarymanagement.Binary if scalaVersion.startsWith("0.") => + moduleID.cross(CrossVersion.constant("2.12")) + case _ => + moduleID + } + } } import autoImport._ @@ -90,7 +87,7 @@ object DottyPlugin extends AutoPlugin { override def requires: Plugins = plugins.JvmPlugin override def trigger = allRequirements - // Adapted from CrossVersionUtil#sbtApiVersion + // Adapted from CrossVersioconstant nUtil#sbtApiVersion private def sbtFullVersion(v: String): Option[(Int, Int, Int)] = { val ReleaseV = """(\d+)\.(\d+)\.(\d+)(-\d+)?""".r @@ -104,27 +101,6 @@ object DottyPlugin extends AutoPlugin { } } - // Copy-pasted from sbt where it's private - private case class WrappedClassFileManager(internal: ClassFileManager, - external: Option[ClassFileManager]) - extends ClassFileManager { - - override def delete(classes: Array[File]): Unit = { - external.foreach(_.delete(classes)) - internal.delete(classes) - } - - override def complete(success: Boolean): Unit = { - external.foreach(_.complete(success)) - internal.complete(success) - } - - override def generated(classes: Array[File]): Unit = { - external.foreach(_.generated(classes)) - internal.generated(classes) - } - } - /** Patches the IncOptions so that .tasty and .hasTasty files are pruned as needed. * * This code is adapted from `scalaJSPatchIncOptions` in Scala.js, which needs @@ -154,15 +130,14 @@ object DottyPlugin extends AutoPlugin { def complete(success: Boolean): Unit = {} } val inheritedHooks = incOptions.externalHooks - val hooks = new ExternalHooks { - override def externalClassFileManager() = Option(inheritedHooks.externalClassFileManager.orElse(null)) match { + val externalClassFileManager: Optional[ClassFileManager] = Option(inheritedHooks.getExternalClassFileManager.orElse(null)) match { case Some(prevManager) => - Optional.of(WrappedClassFileManager(prevManager, Some(tastyFileManager))) + Optional.of(WrappedClassFileManager.of(prevManager, Optional.of(tastyFileManager))) case None => Optional.of(tastyFileManager) } - override def externalLookup() = inheritedHooks.externalLookup() - } + + val hooks = new DefaultExternalHooks(inheritedHooks.getExternalLookup, externalClassFileManager) incOptions.withExternalHooks(hooks) } @@ -194,6 +169,15 @@ object DottyPlugin extends AutoPlugin { inc }, + scalaCompilerBridgeSource := { + val scalaBridge = scalaCompilerBridgeSource.value + val dottyBridge = (scalaOrganization.value % "dotty-sbt-bridge" % scalaVersion.value).withConfigurations(Some(Configurations.Compile.name)).sources() + if (isDotty.value) + dottyBridge + else + scalaBridge + }, + scalaBinaryVersion := { if (isDotty.value) scalaVersion.value.split("\\.").take(2).mkString(".") // Not needed with sbt >= 0.13.16 From aef68c286f949adeabb0825a2dc0b439cfd1d947 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Sat, 28 Oct 2017 19:02:45 +0200 Subject: [PATCH 014/101] Compile only the bridge, not the whole compiler --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index b2cf87ea902d..fef3ad48ed97 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1161,7 +1161,7 @@ object Build { settings(dottyDocSettings) def asDottySbtBridge(implicit mode: Mode): Project = project.withCommonSettings. - dependsOn(dottyCompiler). + dependsOn(dottyCompiler % Provided). settings(dottySbtBridgeSettings) def asDottyBench(implicit mode: Mode): Project = project.withCommonSettings. From 0f13174d61dc55e66ecafd9eed15f27b7d6a6856 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 12:05:46 +0200 Subject: [PATCH 015/101] Adapt to new main class detection in Zinc 1 --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index a8e8c2a93e83..08e4ee4c6323 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -2,17 +2,28 @@ package dotty.tools.dotc package sbt import ast.{Trees, tpd} -import core._, core.Decorators._ -import Annotations._, Contexts._, Flags._, Phases._, Trees._, Types._, Symbols._ -import Names._, NameOps._, StdNames._ +import core._ +import core.Decorators._ +import Annotations._ +import Contexts._ +import Flags._ +import Phases._ +import Trees._ +import Types._ +import Symbols._ +import Names._ +import NameOps._ +import StdNames._ import NameKinds.DefaultGetterName import typer.Inliner import typer.ErrorReporting.cyclicErrorMsg import transform.SymUtils._ - import dotty.tools.io.Path import java.io.PrintWriter +import dotty.tools.dotc.config.JavaPlatform +import xsbti.api.DefinitionType + import scala.collection.mutable /** This phase sends a representation of the API of classes to sbt via callbacks. @@ -51,6 +62,7 @@ class ExtractAPI extends Phase { val apiTraverser = new ExtractAPICollector val sources = apiTraverser.apiSource(unit.tpdTree) + val mainClasses = apiTraverser.mainClasses if (dumpInc) { // Append to existing file that should have been created by ExtractDependencies @@ -61,8 +73,10 @@ class ExtractAPI extends Phase { } finally pw.close() } - if (ctx.sbtCallback != null) + if (ctx.sbtCallback != null) { sources.foreach(ctx.sbtCallback.api(sourceFile.file, _)) + mainClasses.foreach(ctx.sbtCallback.mainClass(sourceFile.file, _)) + } } } } @@ -127,6 +141,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder private[this] val refinedTypeCache = new mutable.HashMap[(api.Type, api.Definition), api.Structure] private[this] val allNonLocalClassesInSrc = new mutable.HashSet[xsbti.api.ClassLike] + private[this] val _mainClasses = new mutable.HashSet[String] private[this] object Constants { val emptyStringArray = Array[String]() @@ -177,6 +192,11 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder def apiClass(sym: ClassSymbol): api.ClassLikeDef = classLikeCache.getOrElseUpdate(sym, computeClass(sym)) + def mainClasses: Set[String] = { + forceThunks() + _mainClasses.toSet + } + private def computeClass(sym: ClassSymbol): api.ClassLikeDef = { import xsbti.api.{DefinitionType => dt} val defType = @@ -220,6 +240,11 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder allNonLocalClassesInSrc += cl + val javaPlatform = ctx.platform.asInstanceOf[JavaPlatform] + if (sym.isStatic && defType == DefinitionType.Module && javaPlatform.hasJavaMainMethod(sym)) { + _mainClasses += name + } + api.ClassLikeDef.of(name, acc, modifiers, anns, tparams, defType) } From 323b4512c365e6db7cc5712773671184e2513857 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 23 Oct 2017 09:34:44 +0200 Subject: [PATCH 016/101] Re-enable `dist-*` projects --- build.sbt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index b547156c2d76..9fbaee50a7f4 100644 --- a/build.sbt +++ b/build.sbt @@ -22,9 +22,9 @@ val `scala-library` = Build.`scala-library` val `scala-compiler` = Build.`scala-compiler` val `scala-reflect` = Build.`scala-reflect` val scalap = Build.scalap -// val dist = Build.dist -// val `dist-bootstrapped` = Build.`dist-bootstrapped` -// val `dist-optimised` = Build.`dist-optimised` +val dist = Build.dist +val `dist-bootstrapped` = Build.`dist-bootstrapped` +val `dist-optimised` = Build.`dist-optimised` val `sbt-dotty` = Build.`sbt-dotty` val `vscode-dotty` = Build.`vscode-dotty` From c05353aaefcae16f6c3559f0ae954dab469fa53a Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 23 Oct 2017 09:35:05 +0200 Subject: [PATCH 017/101] Fix `bin/dot*` scripts --- dist/bin/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/bin/common b/dist/bin/common index b5239ce28af0..660b25f220b3 100755 --- a/dist/bin/common +++ b/dist/bin/common @@ -118,7 +118,7 @@ DOTTY_LIB=$(find_lib "*dotty-library*") SCALA_ASM=$(find_lib "*scala-asm*") SCALA_LIB=$(find_lib "*scala-library*") SCALA_XML=$(find_lib "*scala-xml*") -SBT_INTF=$(find_lib "*sbt-interface*") +SBT_INTF=$(find_lib "*compiler-interface*") # debug DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 From 4c91ed29a5674e8d5d845e4256cab69d3c6d4e2e Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 11:27:26 +0200 Subject: [PATCH 018/101] Fix `source-dependencies/abstract-type-override` --- .../abstract-type-override/build.sbt | 14 ++++++++------ .../abstract-type-override/test | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt index 92d2093771e4..6c2c11e0926a 100644 --- a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt @@ -1,7 +1,9 @@ -InputKey[Unit]("check-number-of-compiler-iterations") <<= inputTask { (argTask: TaskKey[Seq[String]]) => - (argTask, compile in Compile) map { (args: Seq[String], a: sbt.inc.Analysis) => - assert(args.size == 1) - val expectedIterationsNumber = args(0).toInt - assert(a.compilations.allCompilations.size == expectedIterationsNumber, "a.compilations.allCompilations.size = %d (expected %d)".format(a.compilations.allCompilations.size, expectedIterationsNumber)) - } +import complete.DefaultParsers._ + +InputKey[Unit]("check-number-of-compiler-iterations") := { + val args = spaceDelimited("").parsed + val a = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + assert(args.size == 1) + val expectedIterationsNumber = args(0).toInt + assert(a.compilations.allCompilations.size == expectedIterationsNumber, "a.compilations.allCompilations.size = %d (expected %d)".format(a.compilations.allCompilations.size, expectedIterationsNumber)) } diff --git a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test index b0bec415eadb..9ffa4fb17ccd 100644 --- a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test +++ b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test @@ -11,4 +11,4 @@ $ copy-file changes/Bar1.scala src/main/scala/Bar.scala # second iteration #> compile # check if there are only two compile iterations performed -> check-number-of-compiler-iterations 2 +> checkNumberOfCompilerIterations 2 From 2cf0abe34fda81f43e45915456fc5d3b48c68150 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 11:27:49 +0200 Subject: [PATCH 019/101] Fix `source-dependencies/transitive-memberRef` --- .../transitive-memberRef/build.sbt | 40 +++++++++---------- .../transitive-memberRef/test | 2 +- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt index d24e304b1bc1..5180981ce13c 100644 --- a/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt @@ -1,40 +1,36 @@ logLevel := Level.Debug -incOptions := incOptions.value.withNameHashing(true) - -// disable sbt's heauristic which recompiles everything in case +// disable sbt's heuristic which recompiles everything in case // some fraction (e.g. 50%) of files is scheduled to be recompiled // in this test we want precise information about recompiled files // which that heuristic would distort -incOptions := incOptions.value.copy(recompileAllFraction = 1.0) +incOptions := incOptions.value.withRecompileAllFraction(1.0) /* Performs checks related to compilations: * a) checks in which compilation given set of files was recompiled * b) checks overall number of compilations performed */ TaskKey[Unit]("check-compilations") := { - val analysis = (compile in Compile).value + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] val srcDir = (scalaSource in Compile).value - def relative(f: java.io.File): java.io.File = f.relativeTo(srcDir) getOrElse f val allCompilations = analysis.compilations.allCompilations - val recompiledFiles: Seq[Set[java.io.File]] = allCompilations map { c => - val recompiledFiles = analysis.apis.internal.collect { - case (file, api) if api.compilation.startTime == c.startTime => relative(file) + val recompiledClasses: Seq[Set[String]] = allCompilations map { c => + val recompiledClasses = analysis.apis.internal.collect { + case (clazz, api) if api.compilationTimestamp() == c.getStartTime() => clazz } - recompiledFiles.toSet + recompiledClasses.toSet } - def recompiledFilesInIteration(iteration: Int, fileNames: Set[String]) = { - val files = fileNames.map(new java.io.File(_)) - assert(recompiledFiles(iteration) == files, "%s != %s".format(recompiledFiles(iteration), files)) + def recompiledClassesInIteration(iteration: Int, classNames: Set[String]): Unit = { + assert(recompiledClasses(iteration) == classNames, "%s != %s".format(recompiledClasses(iteration), classNames)) } - // Y.scala is compiled only at the beginning as changes to A.scala do not affect it - recompiledFilesInIteration(0, Set("X.scala", "Y.scala")) - // A.scala is changed and recompiled - recompiledFilesInIteration(1, Set("A.scala")) - // change in A.scala causes recompilation of B.scala, C.scala, D.scala which depend on transtiviely - // and by inheritance on A.scala - // X.scala is also recompiled because it depends by member reference on B.scala - // Note that Y.scala is not recompiled because it depends just on X through member reference dependency - recompiledFilesInIteration(2, Set("B.scala", "C.scala", "D.scala")) + // test.Y is compiled only at the beginning as changes to test.A do not affect it + recompiledClassesInIteration(0, Set("test.X", "test.Y")) + // test.A is changed and recompiled + recompiledClassesInIteration(1, Set("test.A")) + // change in test.A causes recompilation of test.B, test.C, test.D which depend on transitively + // and by inheritance on test.A + // test.X is also recompiled because it depends by member reference on test.B + // Note that test.Y is not recompiled because it depends just on X through member reference dependency + recompiledClassesInIteration(2, Set("test.B", "test.C", "test.D")) assert(allCompilations.size == 3) } diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/test b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/test index 395f90229b5c..a39fe13a99ed 100644 --- a/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/test +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/test @@ -8,4 +8,4 @@ $ copy-file changes/A1.scala src/main/scala/A.scala # second iteration > compile # check in which compile iteration given source file got recompiled -> check-compilations +> checkCompilations From f232fbe9723b1ab38a4220da6d95f252d6a22fac Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 12:11:36 +0200 Subject: [PATCH 020/101] Disable `source-dependencies/inherited-deps-java` That test depended on NameHashing being disabled, which is no longer supported with Zinc 1.0 --- .../source-dependencies/inherited-deps-java/{test => disabled} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sbt-dotty/sbt-test/source-dependencies/inherited-deps-java/{test => disabled} (100%) diff --git a/sbt-dotty/sbt-test/source-dependencies/inherited-deps-java/test b/sbt-dotty/sbt-test/source-dependencies/inherited-deps-java/disabled similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/inherited-deps-java/test rename to sbt-dotty/sbt-test/source-dependencies/inherited-deps-java/disabled From 494beb96d99b51ae719ee056e8c2e2585750de18 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 12:25:33 +0200 Subject: [PATCH 021/101] Fix test `source-dependencies/compactify` --- .../sbt-test/source-dependencies/compactify/build.sbt | 7 ++++--- sbt-dotty/sbt-test/source-dependencies/compactify/test | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/compactify/build.sbt b/sbt-dotty/sbt-test/source-dependencies/compactify/build.sbt index f44ca08623f2..121f59cd756b 100644 --- a/sbt-dotty/sbt-test/source-dependencies/compactify/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/compactify/build.sbt @@ -1,6 +1,7 @@ -TaskKey[Unit]("output-empty") <<= classDirectory in Configurations.Compile map { outputDirectory => - def classes = (outputDirectory ** "*.class").get - if(!classes.isEmpty) sys.error("Classes existed:\n\t" + classes.mkString("\n\t")) else () +TaskKey[Unit]("output-empty") := { + val outputDirectory = (classDirectory in Compile).value + val classes = (outputDirectory ** "*.class").get + if (classes.nonEmpty) sys.error("Classes existed:\n\t" + classes.mkString("\n\t")) else () } // apparently Travis CI stopped allowing long file names diff --git a/sbt-dotty/sbt-test/source-dependencies/compactify/test b/sbt-dotty/sbt-test/source-dependencies/compactify/test index e2abf578b8c0..b56be3e5d4aa 100644 --- a/sbt-dotty/sbt-test/source-dependencies/compactify/test +++ b/sbt-dotty/sbt-test/source-dependencies/compactify/test @@ -1,8 +1,8 @@ # Marked pending due to https://github.com/sbt/sbt/issues/1553 -> output-empty +> outputEmpty > compile --> output-empty +-> outputEmpty $ delete src/main/scala/For.scala src/main/scala/Nested.scala > compile -> output-empty \ No newline at end of file +> outputEmpty \ No newline at end of file From b749648d94bae6df7fbbbe12bcaf5c1e186140b5 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 12:31:43 +0200 Subject: [PATCH 022/101] Mark test `source-dependencies/binary` pending It isn't passing in sbt/sbt either. See sbt/sbt#3691 --- .../sbt-test/source-dependencies/binary/build.sbt | 5 +++++ .../source-dependencies/binary/{test => pending} | 0 .../source-dependencies/binary/project/P.scala | 10 ---------- 3 files changed, 5 insertions(+), 10 deletions(-) create mode 100644 sbt-dotty/sbt-test/source-dependencies/binary/build.sbt rename sbt-dotty/sbt-test/source-dependencies/binary/{test => pending} (100%) diff --git a/sbt-dotty/sbt-test/source-dependencies/binary/build.sbt b/sbt-dotty/sbt-test/source-dependencies/binary/build.sbt new file mode 100644 index 000000000000..40d7ea353760 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/binary/build.sbt @@ -0,0 +1,5 @@ +lazy val dep = project.in(file("dep")) +lazy val use = project.in(file("use")). + settings( + unmanagedJars in Compile := Attributed.blank(packageBin.in(dep, Compile).value) :: Nil + ) diff --git a/sbt-dotty/sbt-test/source-dependencies/binary/test b/sbt-dotty/sbt-test/source-dependencies/binary/pending similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/binary/test rename to sbt-dotty/sbt-test/source-dependencies/binary/pending diff --git a/sbt-dotty/sbt-test/source-dependencies/binary/project/P.scala b/sbt-dotty/sbt-test/source-dependencies/binary/project/P.scala index 9cabc95a4e82..e69de29bb2d1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/binary/project/P.scala +++ b/sbt-dotty/sbt-test/source-dependencies/binary/project/P.scala @@ -1,10 +0,0 @@ -import sbt._ -import Keys._ - -object B extends Build -{ - lazy val dep = Project("dep", file("dep")) - lazy val use = Project("use", file("use")) settings( - unmanagedJars in Compile <+= packageBin in (dep, Compile) map Attributed.blank - ) -} From dd7841dcdf1db4303afca8634262c3de4609cf45 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 12:37:48 +0200 Subject: [PATCH 023/101] Fix test source-dependencies/export-jars --- .../sbt-test/source-dependencies/export-jars/build.sbt | 2 ++ .../source-dependencies/export-jars/changes/build2.sbt | 3 +++ .../source-dependencies/export-jars/project/Build.scala | 7 ------- 3 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 sbt-dotty/sbt-test/source-dependencies/export-jars/build.sbt delete mode 100644 sbt-dotty/sbt-test/source-dependencies/export-jars/project/Build.scala diff --git a/sbt-dotty/sbt-test/source-dependencies/export-jars/build.sbt b/sbt-dotty/sbt-test/source-dependencies/export-jars/build.sbt new file mode 100644 index 000000000000..8b39c7cf680e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/export-jars/build.sbt @@ -0,0 +1,2 @@ +lazy val root = project.in(file(".")).dependsOn(a) +lazy val a = project.in(file("a")) diff --git a/sbt-dotty/sbt-test/source-dependencies/export-jars/changes/build2.sbt b/sbt-dotty/sbt-test/source-dependencies/export-jars/changes/build2.sbt index 0f5735bc81d0..3fa7cbb370fb 100644 --- a/sbt-dotty/sbt-test/source-dependencies/export-jars/changes/build2.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/export-jars/changes/build2.sbt @@ -1 +1,4 @@ +lazy val root = Project("root", file(".")) dependsOn(a) +lazy val a = Project("a", file("a")) + exportJars := true \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/export-jars/project/Build.scala b/sbt-dotty/sbt-test/source-dependencies/export-jars/project/Build.scala deleted file mode 100644 index 4a783acbe158..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/export-jars/project/Build.scala +++ /dev/null @@ -1,7 +0,0 @@ -import sbt._ - -object Build extends Build -{ - lazy val root = Project("root", file(".")) dependsOn(a) - lazy val a = Project("a", file("a")) -} \ No newline at end of file From 98c9e8da83a54ce47089c0ad2c6489f88f72631b Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 7 Nov 2017 11:26:56 +0100 Subject: [PATCH 024/101] Update test `source-dependencies/import-class` It has been changed in sbt/zinc. --- sbt-dotty/sbt-test/source-dependencies/import-class/B.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbt-dotty/sbt-test/source-dependencies/import-class/B.scala b/sbt-dotty/sbt-test/source-dependencies/import-class/B.scala index 0489f4a26c29..eb81ff6bd6e7 100644 --- a/sbt-dotty/sbt-test/source-dependencies/import-class/B.scala +++ b/sbt-dotty/sbt-test/source-dependencies/import-class/B.scala @@ -1 +1,3 @@ import a.A + +class B From 479c6c2f39470959637b869a8076552cfa77aecb Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 13:24:47 +0200 Subject: [PATCH 025/101] Fix test source-dependencies/trait-member-modified --- .../trait-member-modified/build.sbt | 21 ++++++++----------- .../trait-member-modified/test | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt index 949d782317c0..1ebe8fad1a41 100644 --- a/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt @@ -3,25 +3,22 @@ * b) checks overall number of compilations performed */ TaskKey[Unit]("check-compilations") := { - val analysis = (compile in Compile).value - val srcDir = (scalaSource in Compile).value - def relative(f: java.io.File): java.io.File = f.relativeTo(srcDir) getOrElse f + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] val allCompilations = analysis.compilations.allCompilations - val recompiledFiles: Seq[Set[java.io.File]] = allCompilations map { c => - val recompiledFiles = analysis.apis.internal.collect { - case (file, api) if api.compilation.startTime == c.startTime => relative(file) + val recompiledClasses: Seq[Set[String]] = allCompilations map { c => + val recompiledClasses = analysis.apis.internal.collect { + case (clazz, api) if api.compilationTimestamp() == c.getStartTime() => clazz } - recompiledFiles.toSet + recompiledClasses.toSet } - def recompiledFilesInIteration(iteration: Int, fileNames: Set[String]) = { - val files = fileNames.map(new java.io.File(_)) - assert(recompiledFiles(iteration) == files, "%s != %s".format(recompiledFiles(iteration), files)) + def recompiledFilesInIteration(iteration: Int, classNames: Set[String]): Unit = { + assert(recompiledClasses(iteration) == classNames, "%s != %s".format(recompiledClasses(iteration), classNames)) } assert(allCompilations.size == 2) // B.scala is just compiled at the beginning - recompiledFilesInIteration(0, Set("B.scala")) + recompiledFilesInIteration(0, Set("B")) // A.scala is changed and recompiled - recompiledFilesInIteration(1, Set("A.scala")) + recompiledFilesInIteration(1, Set("A")) } logLevel := Level.Debug diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/test b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/test index f8f7cb076b2b..183e1d40e805 100644 --- a/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/test +++ b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/test @@ -6,4 +6,4 @@ $ copy-file changes/A1.scala src/main/scala/A.scala # only A.scala should be recompiled > compile # check if there are only two compile iterations performed -> check-compilations +> checkCompilations From 240e133f7390ee7565ea03bfc692ba630a182581 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 13:29:31 +0200 Subject: [PATCH 026/101] Fix test source-dependencies/java-analyis-serialization-error --- .../java-analysis-serialization-error/build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/java-analysis-serialization-error/build.sbt b/sbt-dotty/sbt-test/source-dependencies/java-analysis-serialization-error/build.sbt index 1b1ddefb98ce..f78f33916fce 100644 --- a/sbt-dotty/sbt-test/source-dependencies/java-analysis-serialization-error/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/java-analysis-serialization-error/build.sbt @@ -1 +1 @@ -incOptions := incOptions.value.withNameHashing(true).withApiDebug(true) +incOptions := incOptions.value.withApiDebug(true) From 08e09b8800857bd0eb3af67ce2a4d534dd4eb63f Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 13:38:59 +0200 Subject: [PATCH 027/101] Fix test source-dependencies/canon --- sbt-dotty/sbt-test/source-dependencies/canon/build.sbt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt b/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt index d23dff7054d2..d7524d433978 100644 --- a/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt @@ -3,8 +3,10 @@ import complete.DefaultParsers._ val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") checkIterations := { - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = (compile in Compile).value.compilations.allCompilations.size - assert(expected == actual, s"Expected $expected compilations, got $actual") + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + + val expected: Int = (Space ~> NatBasic).parsed + val actual: Int = analysis.compilations.allCompilations.size + assert(expected == actual, s"Expected $expected compilations, got $actual") } From 939dd314678130b431d8a5d4fc76a841a0b27800 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 13:44:40 +0200 Subject: [PATCH 028/101] Fix test source-dependencies/restore-classes --- .../source-dependencies/restore-classes/build.sbt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt b/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt index 2231204ea3bf..cf38564cc570 100644 --- a/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt @@ -5,8 +5,10 @@ crossTarget in Compile := target.value val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") checkIterations := { - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = (compile in Compile).value.compilations.allCompilations.size - assert(expected == actual, s"Expected $expected compilations, got $actual") + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + + val expected: Int = (Space ~> NatBasic).parsed + val actual: Int = analysis.compilations.allCompilations.size + assert(expected == actual, s"Expected $expected compilations, got $actual") } From 4ee6fd528c2472cc7b404dfbadbca8c02409c9e8 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 13:50:57 +0200 Subject: [PATCH 029/101] Fix test source-dependencies/type-alias --- sbt-dotty/sbt-test/source-dependencies/type-alias/build.sbt | 2 -- 1 file changed, 2 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/type-alias/build.sbt b/sbt-dotty/sbt-test/source-dependencies/type-alias/build.sbt index c5a1099aacad..00edfde1d056 100644 --- a/sbt-dotty/sbt-test/source-dependencies/type-alias/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/type-alias/build.sbt @@ -1,3 +1 @@ logLevel in compile := Level.Debug - -incOptions := incOptions.value.withNameHashing(true) From 159a19e10a7fe4a547a56617a10b755e35fa203a Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 13:57:40 +0200 Subject: [PATCH 030/101] Fix test source-dependencies/typeref-only --- sbt-dotty/sbt-test/source-dependencies/typeref-only/build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/typeref-only/build.sbt b/sbt-dotty/sbt-test/source-dependencies/typeref-only/build.sbt index 02813797f231..ea80ab8d990d 100644 --- a/sbt-dotty/sbt-test/source-dependencies/typeref-only/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/typeref-only/build.sbt @@ -2,4 +2,4 @@ logLevel := Level.Debug // disable recompile all which causes full recompile which // makes it more difficult to test dependency tracking -incOptions ~= { _.copy(recompileAllFraction = 1.0) } +incOptions := incOptions.value.withRecompileAllFraction(1.0) From 149c8b1b2277a2593aa72f8a13b61f90073698b5 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:01:45 +0200 Subject: [PATCH 031/101] Fix test source-dependencies/less-inter-inv-java --- .../source-dependencies/less-inter-inv-java/build.sbt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt index d23dff7054d2..d7524d433978 100644 --- a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt @@ -3,8 +3,10 @@ import complete.DefaultParsers._ val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") checkIterations := { - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = (compile in Compile).value.compilations.allCompilations.size - assert(expected == actual, s"Expected $expected compilations, got $actual") + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + + val expected: Int = (Space ~> NatBasic).parsed + val actual: Int = analysis.compilations.allCompilations.size + assert(expected == actual, s"Expected $expected compilations, got $actual") } From 389cdcc99686baa3c7c8287b833081474bd8f4ca Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:10:50 +0200 Subject: [PATCH 032/101] Fix test source-dependencies/backtick-qupted-names --- .../sbt-test/source-dependencies/backtick-quoted-names/build.sbt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 sbt-dotty/sbt-test/source-dependencies/backtick-quoted-names/build.sbt diff --git a/sbt-dotty/sbt-test/source-dependencies/backtick-quoted-names/build.sbt b/sbt-dotty/sbt-test/source-dependencies/backtick-quoted-names/build.sbt deleted file mode 100644 index 8a38ef41424b..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/backtick-quoted-names/build.sbt +++ /dev/null @@ -1 +0,0 @@ -incOptions := incOptions.value.withNameHashing(true) From ca7774385dded4462942e462c580e468ce6a094c Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:35:04 +0200 Subject: [PATCH 033/101] Fix test source-dependencies/replace-test-a --- .../replace-test-a/build.sbt | 14 ++++++++++++++ .../replace-test-a/project/Build.scala | 19 ------------------- .../source-dependencies/replace-test-a/test | 8 ++++---- 3 files changed, 18 insertions(+), 23 deletions(-) create mode 100644 sbt-dotty/sbt-test/source-dependencies/replace-test-a/build.sbt delete mode 100644 sbt-dotty/sbt-test/source-dependencies/replace-test-a/project/Build.scala diff --git a/sbt-dotty/sbt-test/source-dependencies/replace-test-a/build.sbt b/sbt-dotty/sbt-test/source-dependencies/replace-test-a/build.sbt new file mode 100644 index 000000000000..c63b7bc8a91a --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/replace-test-a/build.sbt @@ -0,0 +1,14 @@ +import java.net.URLClassLoader + +lazy val root = project.in(file(".")). + settings( + TaskKey[Unit]("check-first") := checkTask("First").value, + TaskKey[Unit]("check-second") := checkTask("Second").value + ) + +def checkTask(className: String) = Def.task { + val runClasspath = (fullClasspath in Runtime).value + val cp = runClasspath.map(_.data.toURI.toURL).toArray + Class.forName(className, false, new URLClassLoader(cp)) + () +} diff --git a/sbt-dotty/sbt-test/source-dependencies/replace-test-a/project/Build.scala b/sbt-dotty/sbt-test/source-dependencies/replace-test-a/project/Build.scala deleted file mode 100644 index 9c2678540442..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/replace-test-a/project/Build.scala +++ /dev/null @@ -1,19 +0,0 @@ -import sbt._ -import Keys._ -import java.net.URLClassLoader - -object B extends Build -{ - lazy val root = Project("root", file(".")) settings( ss : _*) - - def ss = Seq( - TaskKey[Unit]("check-first") <<= checkTask("First"), - TaskKey[Unit]("check-second") <<= checkTask("Second") - ) - private def checkTask(className: String) = - fullClasspath in Configurations.Runtime map { runClasspath => - val cp = runClasspath.map(_.data.toURI.toURL).toArray - Class.forName(className, false, new URLClassLoader(cp)) - () - } -} diff --git a/sbt-dotty/sbt-test/source-dependencies/replace-test-a/test b/sbt-dotty/sbt-test/source-dependencies/replace-test-a/test index 4b4ad3a2b953..21dec1db9924 100644 --- a/sbt-dotty/sbt-test/source-dependencies/replace-test-a/test +++ b/sbt-dotty/sbt-test/source-dependencies/replace-test-a/test @@ -1,9 +1,9 @@ $ copy-file changes/first.scala src/main/scala/A.scala > compile -> check-first --> check-second +> checkFirst +-> checkSecond $ copy-file changes/second.scala src/main/scala/A.scala > compile --> check-first -> check-second \ No newline at end of file +-> checkFirst +> checkSecond \ No newline at end of file From e4f092dddf421b96d78dee1699a4cfe3607fc1ef Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:43:08 +0200 Subject: [PATCH 034/101] Fix test source-dependencies/inherited_type_params --- .../inherited_type_params/build.sbt | 11 ++++++----- .../source-dependencies/inherited_type_params/test | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/build.sbt b/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/build.sbt index a5982f901fd7..e25f1beeaaba 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/build.sbt @@ -1,7 +1,8 @@ name := "test" -TaskKey[Unit]("check-same") <<= compile in Configurations.Compile map { analysis => - analysis.apis.internal foreach { case (_, api) => - assert( xsbt.api.SameAPI(api.api, api.api) ) - } -} \ No newline at end of file +TaskKey[Unit]("check-same") := { + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + analysis.apis.internal.foreach { case (_, api) => + assert(xsbt.api.SameAPI(api.api, api.api)) + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/test b/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/test index 8434347c5a23..353461049b5f 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/test +++ b/sbt-dotty/sbt-test/source-dependencies/inherited_type_params/test @@ -1 +1 @@ -> check-same \ No newline at end of file +> checkSame \ No newline at end of file From ce237c749571ef14d013db4a98d2fa6472619185 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:45:32 +0200 Subject: [PATCH 035/101] Fix test source-dependencies/same-file-used-names --- .../sbt-test/source-dependencies/same-file-used-names/build.sbt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 sbt-dotty/sbt-test/source-dependencies/same-file-used-names/build.sbt diff --git a/sbt-dotty/sbt-test/source-dependencies/same-file-used-names/build.sbt b/sbt-dotty/sbt-test/source-dependencies/same-file-used-names/build.sbt deleted file mode 100644 index 8a38ef41424b..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/same-file-used-names/build.sbt +++ /dev/null @@ -1 +0,0 @@ -incOptions := incOptions.value.withNameHashing(true) From b46a4b3652d5e8f5d7b962292442c6048e16fdc3 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:48:27 +0200 Subject: [PATCH 036/101] Fix test source-dependencies/ext --- sbt-dotty/sbt-test/source-dependencies/ext/build.sbt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/ext/build.sbt b/sbt-dotty/sbt-test/source-dependencies/ext/build.sbt index 8aaec76ecfc2..bbc053fa6385 100644 --- a/sbt-dotty/sbt-test/source-dependencies/ext/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/ext/build.sbt @@ -3,7 +3,9 @@ import complete.DefaultParsers._ val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") checkIterations := { - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = (compile in Compile).value.compilations.allCompilations.size - assert(expected == actual, s"Expected $expected compilations, got $actual") + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + + val expected: Int = (Space ~> NatBasic).parsed + val actual: Int = analysis.compilations.allCompilations.size + assert(expected == actual, s"Expected $expected compilations, got $actual") } \ No newline at end of file From 9281d1ca3fb590874403e42a82316bc2010fee48 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:53:23 +0200 Subject: [PATCH 037/101] Fix test source-dependencies/less-inter-inv --- .../sbt-test/source-dependencies/less-inter-inv/build.sbt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt index d23dff7054d2..d7524d433978 100644 --- a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt @@ -3,8 +3,10 @@ import complete.DefaultParsers._ val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") checkIterations := { - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = (compile in Compile).value.compilations.allCompilations.size - assert(expected == actual, s"Expected $expected compilations, got $actual") + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + + val expected: Int = (Space ~> NatBasic).parsed + val actual: Int = analysis.compilations.allCompilations.size + assert(expected == actual, s"Expected $expected compilations, got $actual") } From ff34abb401a276278faa778c4daa1a170d343141 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 14:57:55 +0200 Subject: [PATCH 038/101] Fix test sbt-dotty/example-project --- sbt-dotty/sbt-test/sbt-dotty/example-project/build.sbt | 3 ++- .../sbt-dotty/example-project/project/build.properties | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 sbt-dotty/sbt-test/sbt-dotty/example-project/project/build.properties diff --git a/sbt-dotty/sbt-test/sbt-dotty/example-project/build.sbt b/sbt-dotty/sbt-test/sbt-dotty/example-project/build.sbt index 07fd238624a3..6e0adfaf4d08 100644 --- a/sbt-dotty/sbt-test/sbt-dotty/example-project/build.sbt +++ b/sbt-dotty/sbt-test/sbt-dotty/example-project/build.sbt @@ -1,3 +1,4 @@ scalaVersion := sys.props("plugin.scalaVersion") -libraryDependencies += ("org.scala-lang.modules" %% "scala-xml" % "1.0.6").withDottyCompat() +libraryDependencies += +("org.scala-lang.modules" %% "scala-xml" % "1.0.6").withDottyCompat(scalaVersion.value) diff --git a/sbt-dotty/sbt-test/sbt-dotty/example-project/project/build.properties b/sbt-dotty/sbt-test/sbt-dotty/example-project/project/build.properties deleted file mode 100644 index 64317fdae59f..000000000000 --- a/sbt-dotty/sbt-test/sbt-dotty/example-project/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=0.13.15 From 805ecebaa413d43ff5a6fc2210f36732aaf3c972 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 15:10:09 +0200 Subject: [PATCH 039/101] Fix test compilerReporter/simple --- .../simple/project/Reporter.scala | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/sbt-dotty/sbt-test/compilerReporter/simple/project/Reporter.scala b/sbt-dotty/sbt-test/compilerReporter/simple/project/Reporter.scala index d2dae1fc202a..1d72caa02cab 100644 --- a/sbt-dotty/sbt-test/compilerReporter/simple/project/Reporter.scala +++ b/sbt-dotty/sbt-test/compilerReporter/simple/project/Reporter.scala @@ -3,38 +3,29 @@ import Keys._ import KeyRanks.DTask object Reporter { - import xsbti.{Reporter, Problem, Position, Severity, Maybe} + 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[Option[xsbti.Reporter]]("compilerReporter", "Experimental hook to listen (or send) compilation failure messages.", DTask) - - lazy val reporter = - Some(new xsbti.Reporter { + 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(pos: Position, msg: String, sev: Severity): Unit = { - object MyProblem extends Problem { - def category: String = null - def severity: Severity = sev - def message: String = msg - def position: Position = pos - override def toString = s"custom: $position:$severity: $message" - } - buffer.append(MyProblem) - } + 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).mapFailure( _ => { - val problems = reporter.get.problems + check := (compile in Compile).failure.map(_ => { + val problems = reporter.problems println(problems.toList) assert(problems.size == 1) @@ -43,6 +34,6 @@ object Reporter { // assert(problems.forall(_.position.offset.isDefined)) assert(problems.count(_.severity == Severity.Error) == 1) // not found: er1, - }) + }).value ) } From 4475e9e3f158b95ccb3a4da04e5d2d7d29d9b88e Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 23 Oct 2017 07:03:14 +0200 Subject: [PATCH 040/101] Fix test source-dependencies/value-class-underlying --- .../value-class-underlying/C.scala | 1 + .../project/DottyInjectedPlugin.scala | 12 ++++++++++++ .../value-class-underlying/project/plugins.sbt | 1 + 3 files changed, 14 insertions(+) create mode 100644 sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/plugins.sbt diff --git a/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala index 1a9a42bde96f..0c09ea764fe5 100644 --- a/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala +++ b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala @@ -1,5 +1,6 @@ object C { def main(args: Array[String]): Unit = { val x = B.foo + println("x: " + x) // Need to use x in an expression to see if it crashes or not } } diff --git a/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) From 5b5b260e3cf0ea51849f6bcef5a40e87fa14c6bb Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 20 Oct 2017 15:30:44 +0200 Subject: [PATCH 041/101] Disable test source-dependencies/trait-private-var Reverted while implementing class-based NameHashing. See: - https://github.com/sbt/zinc/commit/189a2a52042535dcb830cece29f26ad2a99df759 - https://github.com/sbt/zinc/pull/86 --- .../source-dependencies/trait-private-var/{test => pending} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sbt-dotty/sbt-test/source-dependencies/trait-private-var/{test => pending} (100%) diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-var/test b/sbt-dotty/sbt-test/source-dependencies/trait-private-var/pending similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/trait-private-var/test rename to sbt-dotty/sbt-test/source-dependencies/trait-private-var/pending From df2ac081c77209432a98190ee7457e3af79cb0f1 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 6 Nov 2017 21:32:24 +0100 Subject: [PATCH 042/101] Always run scripted tests --- .drone.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index eb340cae3d24..8835e0f9a5ce 100644 --- a/.drone.yml +++ b/.drone.yml @@ -47,9 +47,9 @@ pipeline: commands: - cp -R . /tmp/4/ && cd /tmp/4/ - ./project/scripts/sbt sbt-dotty/scripted - when: + # when: # sbt scripted tests are slow and don't run on PRs - event: [ push, tag, deployment ] + # event: [ push, tag, deployment ] # DOCUMENTATION: documentation: From d818a2ce61029c07c0b5746fa6e85bc6990961aa Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 7 Nov 2017 09:06:43 +0100 Subject: [PATCH 043/101] Split scripted tests in two groups --- .drone.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 8835e0f9a5ce..384bc45cb0c9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -41,12 +41,22 @@ pipeline: - cp -R . /tmp/3/ && cd /tmp/3/ - ./project/scripts/sbt dotty-optimised/testAll - test_sbt: + test_sbt_1of2: group: test image: lampepfl/dotty:2017-10-20 commands: - cp -R . /tmp/4/ && cd /tmp/4/ - - ./project/scripts/sbt sbt-dotty/scripted + - ./project/scripts/sbt "sbt-dotty/scripted compilerReporter/* discovery/* sbt-dotty/* source-dependencies/*1of2" + # when: + # sbt scripted tests are slow and don't run on PRs + # event: [ push, tag, deployment ] + + test_sbt_2of2: + group: test + image: lampepfl/dotty:2017-10-20 + commands: + - cp -R . /tmp/5/ && cd /tmp/5/ + - ./project/scripts/sbt "sbt-dotty/scripted source-dependencies/*2of2" # when: # sbt scripted tests are slow and don't run on PRs # event: [ push, tag, deployment ] From 2075f13a2219b0ac4c8539a5fbdd75fa5a1e1131 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 7 Nov 2017 14:47:20 +0100 Subject: [PATCH 044/101] Remove `Message` and `Log` Their goal was to offer a simpler alternative to sbt's `F0`. Since `F0` got replaced by `Supplier`, they are no longer required. --- sbt-bridge/src/xsbt/CompilerInterface.scala | 3 +-- sbt-bridge/src/xsbt/Log.scala | 10 ---------- sbt-bridge/src/xsbt/Message.scala | 10 ---------- 3 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 sbt-bridge/src/xsbt/Log.scala delete mode 100644 sbt-bridge/src/xsbt/Message.scala diff --git a/sbt-bridge/src/xsbt/CompilerInterface.scala b/sbt-bridge/src/xsbt/CompilerInterface.scala index 631524e17ebb..ac828b996957 100644 --- a/sbt-bridge/src/xsbt/CompilerInterface.scala +++ b/sbt-bridge/src/xsbt/CompilerInterface.scala @@ -5,7 +5,6 @@ package xsbt import xsbti.{ AnalysisCallback, Logger, Reporter, Severity } import xsbti.compile._ -import Log.debug import java.io.File import dotty.tools.dotc.core.Contexts.ContextBase @@ -52,7 +51,7 @@ class CachedCompilerImpl(args: Array[String], output: Output) extends CachedComp run(sources.toList, changes, callback, log, delegate, progress) } private[this] def run(sources: List[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, compileProgress: CompileProgress): Unit = { - debug(log, args.mkString("Calling Dotty compiler with arguments (CompilerInterface):\n\t", "\n\t", "")) + log.debug(() => args.mkString("Calling Dotty compiler with arguments (CompilerInterface):\n\t", "\n\t", "")) val ctx = (new ContextBase).initialCtx.fresh .setSbtCallback(callback) .setReporter(new DelegatingReporter(delegate)) diff --git a/sbt-bridge/src/xsbt/Log.scala b/sbt-bridge/src/xsbt/Log.scala deleted file mode 100644 index e514d7abbc46..000000000000 --- a/sbt-bridge/src/xsbt/Log.scala +++ /dev/null @@ -1,10 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2008, 2009 Mark Harrah - */ -package xsbt - -object Log { - def debug(log: xsbti.Logger, msg: => String) = log.debug(Message(msg)) - def settingsError(log: xsbti.Logger): String => Unit = - s => log.error(Message(s)) -} diff --git a/sbt-bridge/src/xsbt/Message.scala b/sbt-bridge/src/xsbt/Message.scala deleted file mode 100644 index ef45577a7739..000000000000 --- a/sbt-bridge/src/xsbt/Message.scala +++ /dev/null @@ -1,10 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2008, 2009 Mark Harrah - */ -package xsbt - -import java.util.function.Supplier - -object Message { - def apply[T](s: => T) = new Supplier[T] { def get() = s } -} From 39ac06b6c43d42d20a987736d8f554b3cae387ce Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 7 Nov 2017 15:02:21 +0100 Subject: [PATCH 045/101] Upgrade to sbt 1.0.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index b7dd3cb2ae83..9abea1294a1f 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.0.2 +sbt.version=1.0.3 From f35894c5d7d000867d709b4994bb0f309aa6a4fa Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 7 Nov 2017 15:28:01 +0100 Subject: [PATCH 046/101] Change name of scala-library jar in tests For many tests, we need the `scala-library` jar on the classpath, and we used to search through the classpath for a JAR whose name contained `scala-library-2.`. This works great if the `scala-library` on the classpath comes from Ivy. However, if we use the same version of Scala as sbt, the `scala-library` will not be taken ouf of the Ivy cache but from sbt's boot directory. In this case, the JAR will simply be named `scala-library.jar`. --- compiler/test/dotty/Jars.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/test/dotty/Jars.scala b/compiler/test/dotty/Jars.scala index dd06dc2a6fee..588cbd7167da 100644 --- a/compiler/test/dotty/Jars.scala +++ b/compiler/test/dotty/Jars.scala @@ -26,7 +26,7 @@ object Jars { dottyLib :: dottyCompiler :: dottyInterfaces :: dottyExtras def scalaLibrary: String = sys.env.get("DOTTY_SCALA_LIBRARY") - .getOrElse(findJarFromRuntime("scala-library-2.")) + .getOrElse(findJarFromRuntime("scala-library")) /** Gets the scala 2.* library at runtime, note that doing this is unsafe * unless you know that the library will be on the classpath of the running From ef10d7cc59efc7a02d55b346e74caed8dc7f65b7 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 8 Nov 2017 10:18:33 +0100 Subject: [PATCH 047/101] Address review comments --- project/Build.scala | 4 +- .../dotty/tools/sbtplugin/DottyPlugin.scala | 60 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index fef3ad48ed97..33803f5246c7 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -160,7 +160,7 @@ object Build { // Avoid having to run `dotty-sbt-bridge/publishLocal` before compiling a bootstrapped project scalaCompilerBridgeSource := - (dottyOrganization %% "dotty-sbt-bridge" % "NOT_PUBLISHED") + (dottyOrganization %% "dotty-sbt-bridge" % dottyVersion) .artifacts(Artifact.sources("dotty-sbt-bridge").withUrl( // We cannot use the `packageSrc` task because a setting cannot depend // on a task. Instead, we make `compile` below depend on the bridge `packageSrc` @@ -199,7 +199,7 @@ object Build { Seq( dottyOrganization % "dotty-library_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name, dottyOrganization % "dotty-compiler_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name - )//.map(_.withDottyCompat(scalaVersion.value)) + ).map(_.withDottyCompat(scalaVersion.value)) else Seq() }, diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index 611677351d0d..201273b9026d 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -51,35 +51,35 @@ object DottyPlugin extends AutoPlugin { nightly } - implicit class DottyCompatModuleID(moduleID: ModuleID) { - /** If this ModuleID cross-version is a Dotty version, replace it - * by the Scala 2.x version that the Dotty version is retro-compatible with, - * otherwise do nothing. - * - * This setting is useful when your build contains dependencies that have only - * been published with Scala 2.x, if you have: - * {{{ - * libraryDependencies += "a" %% "b" % "c" - * }}} - * you can replace it by: - * {{{ - * libraryDependencies += ("a" %% "b" % "c").withDottyCompat(scalaVersion.value) - * }}} - * This will have no effect when compiling with Scala 2.x, but when compiling - * with Dotty this will change the cross-version to a Scala 2.x one. This - * works because Dotty is currently retro-compatible with Scala 2.x. - * - * NOTE: Dotty's retro-compatibility with Scala 2.x will be dropped before - * Dotty is released, you should not rely on it. - */ - def withDottyCompat(scalaVersion: String): ModuleID = - moduleID.crossVersion match { - case _: librarymanagement.Binary if scalaVersion.startsWith("0.") => - moduleID.cross(CrossVersion.constant("2.12")) - case _ => - moduleID - } - } + implicit class DottyCompatModuleID(moduleID: ModuleID) { + /** If this ModuleID cross-version is a Dotty version, replace it + * by the Scala 2.x version that the Dotty version is retro-compatible with, + * otherwise do nothing. + * + * This setting is useful when your build contains dependencies that have only + * been published with Scala 2.x, if you have: + * {{{ + * libraryDependencies += "a" %% "b" % "c" + * }}} + * you can replace it by: + * {{{ + * libraryDependencies += ("a" %% "b" % "c").withDottyCompat(scalaVersion.value) + * }}} + * This will have no effect when compiling with Scala 2.x, but when compiling + * with Dotty this will change the cross-version to a Scala 2.x one. This + * works because Dotty is currently retro-compatible with Scala 2.x. + * + * NOTE: Dotty's retro-compatibility with Scala 2.x will be dropped before + * Dotty is released, you should not rely on it. + */ + def withDottyCompat(scalaVersion: String): ModuleID = + moduleID.crossVersion match { + case _: librarymanagement.Binary if scalaVersion.startsWith("0.") => + moduleID.cross(CrossVersion.constant("2.12")) + case _ => + moduleID + } + } } import autoImport._ @@ -87,7 +87,7 @@ object DottyPlugin extends AutoPlugin { override def requires: Plugins = plugins.JvmPlugin override def trigger = allRequirements - // Adapted from CrossVersioconstant nUtil#sbtApiVersion + // Adapted from CrossVersionUtil#sbtApiVersion private def sbtFullVersion(v: String): Option[(Int, Int, Int)] = { val ReleaseV = """(\d+)\.(\d+)\.(\d+)(-\d+)?""".r From 80d36d521819a72d21522dceab0411e220338f6d Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 8 Nov 2017 10:34:55 +0100 Subject: [PATCH 048/101] Port sbt/zinc#444 --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 14 ++++++++++++-- .../value-class-underlying/C.scala | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 08e4ee4c6323..a91edbbb041b 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -17,6 +17,7 @@ import StdNames._ import NameKinds.DefaultGetterName import typer.Inliner import typer.ErrorReporting.cyclicErrorMsg +import transform.ValueClasses import transform.SymUtils._ import dotty.tools.io.Path import java.io.PrintWriter @@ -254,8 +255,17 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val cinfo = csym.classInfo val bases = - try linearizedAncestorTypes(cinfo) - catch { + try { + val ancestorTypes0 = linearizedAncestorTypes(cinfo) + if (ValueClasses.isDerivedValueClass(csym)) { + val underlying = ValueClasses.valueClassUnbox(csym).info.finalResultType + // The underlying type of a value class should be part of the name hash + // of the value class (see the test `value-class-underlying`), this is accomplished + // by adding the underlying type to the list of parent types. + underlying :: ancestorTypes0 + } else + ancestorTypes0 + } catch { case ex: CyclicReference => // See neg/i1750a for an example where a cyclic error can arise. // The root cause in this example is an illegal "override" of an inner trait diff --git a/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala index 0c09ea764fe5..9a6a97533086 100644 --- a/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala +++ b/sbt-dotty/sbt-test/source-dependencies/value-class-underlying/C.scala @@ -1,6 +1,6 @@ object C { def main(args: Array[String]): Unit = { - val x = B.foo - println("x: " + x) // Need to use x in an expression to see if it crashes or not + val duck = B.foo + println("duck: " + duck) // Need to use duck in an expression to see if it crashes or not } } From 77051245455087ad89f36fc825c842427116c64e Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Thu, 9 Nov 2017 10:14:14 +0100 Subject: [PATCH 049/101] Address review comments --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 37 ++++++++++--------- project/Build.scala | 6 +-- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index a91edbbb041b..3b9135dbdd93 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -254,24 +254,25 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder def apiClassStructure(csym: ClassSymbol): api.Structure = { val cinfo = csym.classInfo - val bases = - try { - val ancestorTypes0 = linearizedAncestorTypes(cinfo) - if (ValueClasses.isDerivedValueClass(csym)) { - val underlying = ValueClasses.valueClassUnbox(csym).info.finalResultType - // The underlying type of a value class should be part of the name hash - // of the value class (see the test `value-class-underlying`), this is accomplished - // by adding the underlying type to the list of parent types. - underlying :: ancestorTypes0 - } else - ancestorTypes0 - } catch { - case ex: CyclicReference => - // See neg/i1750a for an example where a cyclic error can arise. - // The root cause in this example is an illegal "override" of an inner trait - ctx.error(cyclicErrorMsg(ex), csym.pos) - defn.ObjectType :: Nil - } + val bases = { + val ancestorTypes0 = + try linearizedAncestorTypes(cinfo) + catch { + case ex: CyclicReference => + // See neg/i1750a for an example where a cyclic error can arise. + // The root cause in this example is an illegal "override" of an inner trait + ctx.error(cyclicErrorMsg(ex), csym.pos) + defn.ObjectType :: Nil + } + if (ValueClasses.isDerivedValueClass(csym)) { + val underlying = ValueClasses.valueClassUnbox(csym).info.finalResultType + // The underlying type of a value class should be part of the name hash + // of the value class (see the test `value-class-underlying`), this is accomplished + // by adding the underlying type to the list of parent types. + underlying :: ancestorTypes0 + } else + ancestorTypes0 + } val apiBases = bases.map(apiType) diff --git a/project/Build.scala b/project/Build.scala index 33803f5246c7..62681ccefde8 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -197,8 +197,8 @@ object Build { libraryDependencies ++= { if (bootstrapFromPublishedJars.value) Seq( - dottyOrganization % "dotty-library_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name, - dottyOrganization % "dotty-compiler_2.11" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name + dottyOrganization %% "dotty-library" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name, + dottyOrganization %% "dotty-compiler" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name ).map(_.withDottyCompat(scalaVersion.value)) else Seq() @@ -862,7 +862,7 @@ object Build { unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", sbtPlugin := true, - version := "0.1.6-SNAPSHOT", + version := "0.1.8", sbtTestDirectory := baseDirectory.value / "sbt-test", scriptedLaunchOpts += "-Dplugin.version=" + version.value, scriptedLaunchOpts += "-Dplugin.scalaVersion=" + dottyVersion, From a438ed6c6a595b6fbe45cfde2cc37fe7da69d8e7 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 19 Jan 2018 18:25:08 +0100 Subject: [PATCH 050/101] Update dependencies and plugins version --- project/Build.scala | 18 +++++++++--------- project/Dependencies.scala | 19 ++++++++++++++++++- project/build.properties | 2 +- project/inject-sbt-dotty.sbt | 2 +- project/plugins.sbt | 9 ++++----- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 7edb4617c8dd..4048fa401951 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -498,9 +498,9 @@ object Build { // get libraries onboard libraryDependencies ++= Seq( "org.scala-lang.modules" % "scala-asm" % "6.0.0-scala-1", // used by the backend - "com.typesafe.sbt" % "sbt-interface" % sbtVersion.value, ("org.scala-lang.modules" %% "scala-xml" % "1.0.6").withDottyCompat(scalaVersion.value), - "org.scala-lang" % "scala-library" % scalacVersion % "test" + "org.scala-lang" % "scala-library" % scalacVersion % "test", + Dependencies.`compiler-interface`, ), // For convenience, change the baseDirectory when running the compiler @@ -699,7 +699,7 @@ object Build { packageAll := { (packageAll in `dotty-compiler`).value ++ Seq( ("dotty-compiler" -> (packageBin in Compile).value.getAbsolutePath), - ("dotty-library" -> (packageBin in (dottyLibrary(Bootstrapped), Compile)).value.getAbsolutePath) + ("dotty-library" -> (packageBin in (`dotty-library-bootstrapped`, Compile)).value.getAbsolutePath) ) } ) @@ -750,10 +750,10 @@ object Build { description := "sbt compiler bridge for Dotty", resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api libraryDependencies ++= Seq( - "org.scala-sbt" % "compiler-interface" % "1.0.2", - ("org.scala-sbt" %% "zinc-apiinfo" % "1.0.2" % "test").withDottyCompat(scalaVersion.value), - ("org.specs2" %% "specs2-core" % "3.9.1" % "test").withDottyCompat(scalaVersion.value), - ("org.specs2" %% "specs2-junit" % "3.9.1" % "test").withDottyCompat(scalaVersion.value) + Dependencies.`compiler-interface`, + (Dependencies.`zinc-apiinfo` % Test).withDottyCompat(scalaVersion.value), + ("org.specs2" %% "specs2-core" % "3.9.1" % Test).withDottyCompat(scalaVersion.value), + ("org.specs2" %% "specs2-junit" % "3.9.1" % Test).withDottyCompat(scalaVersion.value) ), // The sources should be published with crossPaths := false since they // need to be compiled by the project using the bridge. @@ -882,11 +882,10 @@ object Build { lazy val `sbt-dotty` = project.in(file("sbt-dotty")). settings(commonSettings). settings( - scalaVersion := "2.12.2", // Keep in sync with inject-sbt-dotty.sbt libraryDependencies ++= Seq( Dependencies.`jackson-databind`, - "org.scala-sbt" % "compiler-interface" % "1.0.2" + Dependencies.`compiler-interface` ), unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", @@ -897,6 +896,7 @@ object Build { scriptedLaunchOpts += "-Dplugin.scalaVersion=" + dottyVersion, // By default scripted tests use $HOME/.ivy2 for the ivy cache. We need to override this value for the CI. scriptedLaunchOpts ++= ivyPaths.value.ivyHome.map("-Dsbt.ivy.home=" + _.getAbsolutePath).toList, + scriptedBufferLog := false, scripted := scripted.dependsOn(Def.task { val x0 = (publishLocal in `dotty-sbt-bridge-bootstrapped`).value val x1 = (publishLocal in `dotty-interfaces`).value diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 99d1dcb79d3e..2d63ab9cd915 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -1,3 +1,6 @@ +import java.io.FileInputStream; +import java.util.Properties + import sbt._ /** A dependency shared between multiple projects should be put here @@ -9,4 +12,18 @@ object Dependencies { "com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion val `jackson-dataformat-yaml` = "com.fasterxml.jackson.dataformat" % "jackson-dataformat-yaml" % jacksonVersion -} + + private def readPropertyFile(file: String): Properties = { + val prop = new Properties() + val input = new FileInputStream(file) + try { + prop.load(input) + prop + } + finally input.close + } + + private val sbtVersion = readPropertyFile("project/build.properties").getProperty("sbt.version") + val `compiler-interface` = "org.scala-sbt" % "compiler-interface" % sbtVersion + val `zinc-apiinfo` = "org.scala-sbt" %% "zinc-apiinfo" % sbtVersion +} \ No newline at end of file diff --git a/project/build.properties b/project/build.properties index 9abea1294a1f..8b697bbb94f3 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.0.3 +sbt.version=1.1.0 diff --git a/project/inject-sbt-dotty.sbt b/project/inject-sbt-dotty.sbt index d63d6da5d1d4..d2962d3d901e 100644 --- a/project/inject-sbt-dotty.sbt +++ b/project/inject-sbt-dotty.sbt @@ -7,7 +7,7 @@ unmanagedSourceDirectories in Compile += baseDirectory.value / "../sbt-dotty/src // Keep in sync with `sbt-dotty` config in Build.scala libraryDependencies ++= Seq( Dependencies.`jackson-databind`, - "org.scala-sbt" % "compiler-interface" % "1.0.0-X16" + Dependencies.`compiler-interface` ) unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config" diff --git a/project/plugins.sbt b/project/plugins.sbt index 66276fdb27fb..b7cee145605a 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -3,17 +3,16 @@ // e.g. addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.1.0") // Scala IDE project file generator -addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.3") +addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.21") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.1") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.10.1") -addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.27") - +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.3.2") From 627826444eacb7b8e42696b693bf3a6c0c28d8f9 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 19 Jan 2018 18:25:43 +0100 Subject: [PATCH 051/101] Workaround sbt/sbt#3469 --- .gitignore | 1 + project/Build.scala | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index b8e3c9e0f96e..775c65d02558 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ project/local-plugins.sbt .history .ensime .ensime_cache/ +.sbt-scripted/ # npm node_modules diff --git a/project/Build.scala b/project/Build.scala index 4048fa401951..10cf59e39f24 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -892,11 +892,14 @@ object Build { sbtPlugin := true, version := "0.1.8", sbtTestDirectory := baseDirectory.value / "sbt-test", - scriptedLaunchOpts += "-Dplugin.version=" + version.value, - scriptedLaunchOpts += "-Dplugin.scalaVersion=" + dottyVersion, + scriptedLaunchOpts ++= Seq( + "-Dplugin.version=" + version.value, + "-Dplugin.scalaVersion=" + dottyVersion, + "-Dsbt.boot.directory=" + ((baseDirectory in ThisBuild).value / ".sbt-scripted").getAbsolutePath // Workaround sbt/sbt#3469 + ), // By default scripted tests use $HOME/.ivy2 for the ivy cache. We need to override this value for the CI. scriptedLaunchOpts ++= ivyPaths.value.ivyHome.map("-Dsbt.ivy.home=" + _.getAbsolutePath).toList, - scriptedBufferLog := false, + scriptedBufferLog := true, scripted := scripted.dependsOn(Def.task { val x0 = (publishLocal in `dotty-sbt-bridge-bootstrapped`).value val x1 = (publishLocal in `dotty-interfaces`).value From 59a0e55ccad0a494f396a6ef552c889bcdd8df73 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 19 Jan 2018 18:32:50 +0100 Subject: [PATCH 052/101] Fix merge breakages + Cleanup --- .../tools/dotc/core/SymDenotations.scala | 12 ++------- .../src/dotty/tools/dotc/core/Symbols.scala | 4 +-- .../tools/dotc/sbt/ExtractDependencies.scala | 26 +++++-------------- .../tools/dotc/transform/patmat/Space.scala | 2 +- .../src/dotty/tools/io/AbstractFile.scala | 2 +- compiler/src/dotty/tools/io/Path.scala | 9 +------ project/Build.scala | 5 ++-- .../dotty/tools/sbtplugin/DottyPlugin.scala | 18 +------------ 8 files changed, 17 insertions(+), 61 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index a3e732cde493..07d29625fac0 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -340,14 +340,6 @@ object SymDenotations { case Nil => Nil } - final def children(implicit ctx: Context): List[Symbol] = - this.annotations.filter(_.symbol == ctx.definitions.ChildAnnot).map { annot => - // refer to definition of Annotation.makeChild - annot.tree match { - case Apply(TypeApply(_, List(tpTree)), _) => tpTree.symbol - } - } - /** The denotation is completed: info is not a lazy type and attributes have defined values */ final def isCompleted: Boolean = !myInfo.isInstanceOf[LazyType] @@ -934,7 +926,7 @@ object SymDenotations { * except for a toplevel module, where its module class is returned. */ final def topLevelClass(implicit ctx: Context): Symbol = { - def topLevel(d: SymDenotation): Symbol = { + @tailrec def topLevel(d: SymDenotation): Symbol = { if (d.isTopLevelClass) d.symbol else topLevel(d.owner) } @@ -944,7 +936,7 @@ object SymDenotations { } final def isTopLevelClass(implicit ctx: Context): Boolean = - this.isEffectiveRoot || (this is PackageClass) || (this.owner is PackageClass) + !this.exists || this.isEffectiveRoot || (this is PackageClass) || (this.owner is PackageClass) /** The package class containing this denotation */ final def enclosingPackageClass(implicit ctx: Context): Symbol = diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index e1998ca12833..9baa027fefbf 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -549,13 +549,13 @@ object Symbols { /** The class file from which this class was generated, null if not applicable. */ final def binaryFile(implicit ctx: Context): AbstractFile = { val file = associatedFile - if (file != null && file.path.endsWith("class")) file else null + if (file != null && file.extension == "class") file else null } /** The source file from which this class was generated, null if not applicable. */ final def sourceFile(implicit ctx: Context): AbstractFile = { val file = associatedFile - if (file != null && !file.path.endsWith("class")) file + if (file != null && file.extension != "class") file else { val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase)) topLevelCls.getAnnotation(defn.SourceFileAnnot) match { diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 5d80684b4edf..7443459094c3 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -9,7 +9,9 @@ import Names._, NameOps._, StdNames._ import scala.collection.{Set, mutable} -import dotty.tools.io.{AbstractFile, Path, ZipArchive, PlainFile} +import dotty.tools.io +import dotty.tools.io.{AbstractFile, ZipArchive, PlainFile} + import java.io.File import java.util.{Arrays, Comparator, EnumSet} @@ -73,7 +75,7 @@ class ExtractDependencies extends Phase { Arrays.sort(deps) Arrays.sort(inhDeps) - val pw = Path(sourceFile.jpath).changeExtension("inc").toFile.printWriter() + val pw = io.File(sourceFile.jpath).changeExtension("inc").toFile.printWriter() try { pw.println(s"// usedNames: ${names.mkString(",")}") pw.println(s"// topLevelDependencies: ${deps.mkString(",")}") @@ -127,23 +129,7 @@ class ExtractDependencies extends Phase { // package can never have a corresponding class file; this test does not // catch package objects (that do not have this flag set) if (sym.is(Package)) None - else { - val file = Option(sym.associatedFile) - - Option(sym.associatedFile).flatMap { - case NoSourceFile => - if (isTopLevelModule(sym)) { - val linked = sym.companionClass - if (linked == NoSymbol) - None - else - classFile(linked) - } else - None - case file => - Some(file) - } - } + else Option(sym.associatedFile) } protected def isTopLevelModule(sym: Symbol)(implicit ctx: Context): Boolean = @@ -174,7 +160,7 @@ class ExtractDependencies extends Phase { at match { case ze: ZipArchive#Entry => for (zip <- ze.underlyingSource; zipFile <- Option(zip.file)) { - val classSegments = Path(ze.path).segments + val classSegments = io.File(ze.path).segments binaryDependency(zipFile, className(classSegments)) } case pf: PlainFile => diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 5ab0344b59e9..81b00c4572e7 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -502,7 +502,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { /** Decompose a type into subspaces -- assume the type can be decomposed */ def decompose(tp: Type): List[Space] = { - val children = tp.classSymbol.denot.children + val children = tp.classSymbol.children debug.println(s"candidates for ${tp.show} : [${children.map(_.show).mkString(", ")}]") diff --git a/compiler/src/dotty/tools/io/AbstractFile.scala b/compiler/src/dotty/tools/io/AbstractFile.scala index d0155ace3711..6ab93f7328ce 100644 --- a/compiler/src/dotty/tools/io/AbstractFile.scala +++ b/compiler/src/dotty/tools/io/AbstractFile.scala @@ -94,7 +94,7 @@ abstract class AbstractFile extends Iterable[AbstractFile] { /** Checks extension case insensitively. */ def hasExtension(other: String) = extension == other.toLowerCase - private val extension: String = Path.extension(name) + val extension: String = Path.extension(name) /** The absolute file, if this is a relative file. */ def absolute: AbstractFile diff --git a/compiler/src/dotty/tools/io/Path.scala b/compiler/src/dotty/tools/io/Path.scala index fbd2a4ac92c7..e5223a580a7d 100644 --- a/compiler/src/dotty/tools/io/Path.scala +++ b/compiler/src/dotty/tools/io/Path.scala @@ -138,14 +138,7 @@ class Path private[io] (val jpath: JPath) { if (p isSame this) Nil else p :: p.parents } // if name ends with an extension (e.g. "foo.jpg") returns the extension ("jpg"), otherwise "" - def extension: String = { - var i = name.length - 1 - while (i >= 0 && name.charAt(i) != '.') - i -= 1 - - if (i < 0) "" - else name.substring(i + 1) - } + def extension: String = Path.extension(name) // compares against extensions in a CASE INSENSITIVE way. def hasExtension(ext: String, exts: String*) = { val lower = extension.toLowerCase diff --git a/project/Build.scala b/project/Build.scala index 10cf59e39f24..fc3d1d8411e0 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -544,7 +544,8 @@ object Build { // used for tests that compile dotty path.contains("scala-asm") || // needed for the xsbti interface - path.contains("sbt-interface") + path.contains("compiler-interface") || + path.contains("util-interface") } yield "-Xbootclasspath/p:" + path val ci_build = // propagate if this is a ci build @@ -890,7 +891,7 @@ object Build { unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", sbtPlugin := true, - version := "0.1.8", + version := "0.2.0", sbtTestDirectory := baseDirectory.value / "sbt-test", scriptedLaunchOpts ++= Seq( "-Dplugin.version=" + version.value, diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index 201273b9026d..c069d7e4c500 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -143,17 +143,8 @@ object DottyPlugin extends AutoPlugin { override def projectSettings: Seq[Setting[_]] = { Seq( - isDotty := { - val log = sLog.value + isDotty := scalaVersion.value.startsWith("0."), - sbtFullVersion(sbtVersion.value) match { - case Some((sbtMajor, sbtMinor, sbtPatch)) if sbtMajor == 0 && sbtMinor == 13 && sbtPatch < 15 => - log.error(s"The sbt-dotty plugin cannot work with this version of sbt (${sbtVersion.value}), sbt >= 0.13.15 is required.") - false - case _ => - scalaVersion.value.startsWith("0.") - } - }, scalaOrganization := { if (isDotty.value) "ch.epfl.lamp" @@ -176,13 +167,6 @@ object DottyPlugin extends AutoPlugin { dottyBridge else scalaBridge - }, - - scalaBinaryVersion := { - if (isDotty.value) - scalaVersion.value.split("\\.").take(2).mkString(".") // Not needed with sbt >= 0.13.16 - else - scalaBinaryVersion.value } ) } From a13bc6b3519bc1f0704ccf8867efa4b4194ae91a Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 23 Jan 2018 13:18:06 +0100 Subject: [PATCH 053/101] wip --- .drone.yml | 56 +++--- .../dotty/tools/backend/jvm/GenBCode.scala | 6 +- .../src/dotty/tools/dotc/core/Phases.scala | 3 + .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 7 +- .../tools/dotc/sbt/ExtractDependencies.scala | 138 ++++++------- compiler/test/dotty/Jars.scala | 2 +- project/Build.scala | 182 +++++++++--------- project/plugins.sbt | 4 +- .../binary/{pending => test} | 0 .../resident-package-object/build.sbt | 3 + 10 files changed, 196 insertions(+), 205 deletions(-) rename sbt-dotty/sbt-test/source-dependencies/binary/{pending => test} (100%) create mode 100644 sbt-dotty/sbt-test/source-dependencies/resident-package-object/build.sbt diff --git a/.drone.yml b/.drone.yml index 2b77ca8a8cb4..3b67040bfe27 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,37 +12,37 @@ pipeline: commands: - ./project/scripts/ci-clone - # TESTS: - # We run tests in parallel. Tests run in a copy of the working directory to avoid conflict - test_legacy: - group: test - image: lampepfl/dotty:2018-01-17 - commands: - - cp -R . /tmp/0/ && cd /tmp/0/ - - ./project/scripts/sbt legacyTests + # # TESTS: + # # We run tests in parallel. Tests run in a copy of the working directory to avoid conflict + # test_legacy: + # group: test + # image: lampepfl/dotty:2018-01-17 + # commands: + # - cp -R . /tmp/0/ && cd /tmp/0/ + # - ./project/scripts/sbt legacyTests - test: - group: test - image: lampepfl/dotty:2018-01-17 - commands: - - cp -R . /tmp/1/ && cd /tmp/1/ - - ./project/scripts/sbt ";compile ;test" - - ./project/scripts/sbtTests + # test: + # group: test + # image: lampepfl/dotty:2018-01-17 + # commands: + # - cp -R . /tmp/1/ && cd /tmp/1/ + # - ./project/scripts/sbt ";compile ;test" + # - ./project/scripts/sbtTests - test_bootstrapped: - group: test - image: lampepfl/dotty:2018-01-17 - commands: - - cp -R . /tmp/2/ && cd /tmp/2/ - - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" - - ./project/scripts/sbtBootstrappedTests + # test_bootstrapped: + # group: test + # image: lampepfl/dotty:2018-01-17 + # commands: + # - cp -R . /tmp/2/ && cd /tmp/2/ + # - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" + # - ./project/scripts/sbtBootstrappedTests - test_optimised: - group: test - image: lampepfl/dotty:2018-01-17 - commands: - - cp -R . /tmp/3/ && cd /tmp/3/ - - ./project/scripts/sbt dotty-optimised/test + # test_optimised: + # group: test + # image: lampepfl/dotty:2018-01-17 + # commands: + # - cp -R . /tmp/3/ && cd /tmp/3/ + # - ./project/scripts/sbt dotty-optimised/test test_sbt: group: test diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index 19480a0bcc02..f2fa235b9447 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -261,9 +261,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter // ----------- sbt's callbacks - val fullClassName = - ExtractDependencies.extractedName(claszSymbol)(ctx.withPhase(ctx.typerPhase)) - val isLocal = fullClassName.contains("_$") + val (fullClassName, isLocal) = ctx.atPhase(ctx.sbtExtractDependenciesPhase) { implicit ctx => + (ExtractDependencies.classNameAsString(claszSymbol), ExtractDependencies.isLocal(claszSymbol)) + } for ((cls, clsFile) <- classNodes.zip(classFiles)) { if (cls != null) { diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 0abc540448a0..3943e63f0ddb 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -210,6 +210,7 @@ object Phases { } private[this] var myTyperPhase: Phase = _ + private[this] var mySbtExtractDependenciesPhase: Phase = _ private[this] var myPicklerPhase: Phase = _ private[this] var myRefChecksPhase: Phase = _ private[this] var myPatmatPhase: Phase = _ @@ -224,6 +225,7 @@ object Phases { private[this] var myGenBCodePhase: Phase = _ final def typerPhase = myTyperPhase + final def sbtExtractDependenciesPhase = mySbtExtractDependenciesPhase final def picklerPhase = myPicklerPhase final def refchecksPhase = myRefChecksPhase final def patmatPhase = myPatmatPhase @@ -241,6 +243,7 @@ object Phases { def phaseOfClass(pclass: Class[_]) = phases.find(pclass.isInstance).getOrElse(NoPhase) myTyperPhase = phaseOfClass(classOf[FrontEnd]) + mySbtExtractDependenciesPhase = phaseOfClass(classOf[sbt.ExtractDependencies]) myPicklerPhase = phaseOfClass(classOf[Pickler]) myRefChecksPhase = phaseOfClass(classOf[RefChecks]) myElimRepeatedPhase = phaseOfClass(classOf[ElimRepeated]) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index ee40e7510010..af34402728fb 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -19,7 +19,7 @@ import typer.Inliner import typer.ErrorReporting.cyclicErrorMsg import transform.ValueClasses import transform.SymUtils._ -import dotty.tools.io.Path +import dotty.tools.io.File import java.io.PrintWriter import dotty.tools.dotc.config.JavaPlatform @@ -67,7 +67,7 @@ class ExtractAPI extends Phase { if (dumpInc) { // Append to existing file that should have been created by ExtractDependencies - val pw = new PrintWriter(Path(sourceFile.jpath).changeExtension("inc").toFile + val pw = new PrintWriter(File(sourceFile.jpath).changeExtension("inc").toFile .bufferedWriter(append = true), true) try { sources.foreach(source => pw.println(DefaultShowAPI(source))) @@ -127,7 +127,6 @@ class ExtractAPI extends Phase { private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder { import tpd._ import xsbti.api - import ExtractDependencies.extractedName /** This cache is necessary for correctness, see the comment about inherited * members in `apiClassStructure` @@ -208,7 +207,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val selfType = apiType(sym.givenSelfType) - val name = extractedName(sym) + val name = ExtractDependencies.classNameAsString(sym) val tparams = sym.typeParams.map(apiTypeParameter).toArray diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 7443459094c3..d223a99755f6 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -17,6 +17,7 @@ import java.io.File import java.util.{Arrays, Comparator, EnumSet} import xsbti.api.DependencyContext +import xsbti.api.DependencyContext._ import xsbti.UseScope @@ -100,10 +101,10 @@ class ExtractDependencies extends Phase { ctx.sbtCallback.usedName(className, useName, useScopes) } } - extractDeps.topLevelDependencies.foreach(dep => - recordDependency(sourceFile.file, dep._2, DependencyContext.DependencyByMemberRef)(ctx.withOwner(dep._1))) - extractDeps.topLevelInheritanceDependencies.foreach(dep => - recordDependency(sourceFile.file, dep._2, DependencyContext.DependencyByInheritance)(ctx.withOwner(dep._1))) + + // FIXME: https://github.com/sbt/zinc/commit/05482d131346d645375263e1420d2cd19b2ea6ef + extractDeps.topLevelDependencies.foreach(dep => recordDependency(dep, DependencyByMemberRef, allowLocal = true)) + extractDeps.topLevelInheritanceDependencies.foreach(dep => recordDependency(dep, DependencyByInheritance, allowLocal = true)) } } } @@ -125,76 +126,67 @@ class ExtractDependencies extends Phase { acc(None, tree) } - private def classFile(sym: Symbol)(implicit ctx: Context): Option[AbstractFile] = { - // package can never have a corresponding class file; this test does not - // catch package objects (that do not have this flag set) - if (sym.is(Package)) None - else Option(sym.associatedFile) - } - - protected def isTopLevelModule(sym: Symbol)(implicit ctx: Context): Boolean = - // enteringPhase(currentRun.picklerPhase.next) { - sym.is(ModuleClass) && sym.owner.is(PackageClass) - // } + /* + * Handles dependency on given symbol by trying to figure out if represents a term + * that is coming from either source code (not necessarily compiled in this compilation + * run) or from class file and calls respective callback method. + */ + def recordDependency(dep: ClassDependency, context: DependencyContext, allowLocal: Boolean)(implicit ctx: Context): Unit = { + val fromClassName = classNameAsString(dep.from) + val sourceFile = ctx.compilationUnit.source.file.file + def binaryDependency(file: File, binaryClassName: String) = + ctx.sbtCallback.binaryDependency(file, binaryClassName, fromClassName, sourceFile, context) - /** Record that `currentSourceFile` depends on the file where `dep` was loaded from. - * - * @param currentSourceFile The source file of the current unit - * @param dep The dependency - * @param context Describes how `currentSourceFile` depends on `dep` - */ - def recordDependency(currentSourceFile: File, dep: Symbol, context: DependencyContext) - (implicit ctx: Context) = { - val onSource = dep.sourceFile - if (onSource == null) { - // Dependency is external -- source is undefined - classFile(dep) match { - case Some(at) => - def className(classSegments: List[String]) = + def processExternalDependency(depFile: AbstractFile) = { + def binaryClassName(classSegments: List[String]) = classSegments.mkString(".").stripSuffix(".class") - def binaryDependency(file: File, className: String) = { - ctx.sbtCallback.binaryDependency(file, className, extractedName(currentClass), currentSourceFile, context) - } - at match { - case ze: ZipArchive#Entry => - for (zip <- ze.underlyingSource; zipFile <- Option(zip.file)) { - val classSegments = io.File(ze.path).segments - binaryDependency(zipFile, className(classSegments)) - } - case pf: PlainFile => - val packages = dep.ownersIterator - .filter(x => x.is(PackageClass) && !x.isEffectiveRoot).length - // We can recover the fully qualified name of a classfile from - // its path - val classSegments = pf.givenPath.segments.takeRight(packages + 1) - binaryDependency(pf.file, className(classSegments)) - case _ => - ctx.warning(s"sbt-deps: Ignoring dependency $at of class ${at.getClass}") + depFile match { + case ze: ZipArchive#Entry => // The dependency comes from a JAR + for (zip <- ze.underlyingSource; zipFile <- Option(zip.file)) { + val classSegments = io.File(ze.path).segments + binaryDependency(zipFile, binaryClassName(classSegments)) } - case None => - ctx.debuglog(s"No file for external symbol $dep") + case pf: PlainFile => // The dependency comes from a class file + val packages = dep.to.ownersIterator + .filter(x => x.is(PackageClass) && !x.isEffectiveRoot).length + // We can recover the fully qualified name of a classfile from + // its path + val classSegments = pf.givenPath.segments.takeRight(packages + 1) + binaryDependency(pf.file, binaryClassName(classSegments)) + + case _ => + ctx.warning(s"sbt-deps: Ignoring dependency $depFile of class ${depFile.getClass}}") + } + } + + val depFile = dep.to.associatedFile + if (depFile != null) { + if (depFile.extension == "class") { + // Dependency is external -- source is undefined + processExternalDependency(depFile) + } else if (allowLocal || depFile.file != sourceFile) { + // We cannot ignore dependencies coming from the same source file because + // the dependency info needs to propagate. See source-dependencies/trait-trait-211. + val toClassName = classNameAsString(dep.to) + ctx.sbtCallback.classDependency(toClassName, fromClassName, context) } - } else if (onSource.file != currentSourceFile) { - ctx.sbtCallback.classDependency(extractedName(dep.enclosingClass), extractedName(currentClass), context) - } else { - () } } } object ExtractDependencies { - def extractedName(sym: Symbol)(implicit ctx: Context): String = - // ctx.atPhase(ctx.flattenPhase.next) { implicit ctx => - if (sym.is(ModuleClass)) - sym.fullName.stripModuleClassSuffix.toString - else - sym.fullName.toString - // } + def classNameAsString(sym: Symbol)(implicit ctx: Context): String = + sym.fullName.stripModuleClassSuffix.mangledString // fullName in scalac strips module class suffix + + def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = + sym.ownersIterator.exists(_.isTerm) } +private case class ClassDependency(from: Symbol, to: Symbol) + private final class NameUsedInClass { // Default names and other scopes are separated for performance reasons val defaultNames: mutable.Set[Name] = new mutable.HashSet[Name] @@ -237,8 +229,8 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic import ExtractDependencies._ private[this] val _usedNames = new mutable.HashMap[String, NameUsedInClass] - private[this] val _topLevelDependencies = new mutable.HashSet[(Symbol, Symbol)] - private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[(Symbol, Symbol)] + private[this] val _topLevelDependencies = new mutable.HashSet[ClassDependency] + private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[ClassDependency] /** The names used in this class, this does not include names which are only * defined and not referenced. @@ -249,18 +241,17 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic * because it refers to these classes or something defined in them. * This is always a superset of `topLevelInheritanceDependencies` by definition. */ - def topLevelDependencies: Set[(Symbol, Symbol)] = _topLevelDependencies + def topLevelDependencies: Set[ClassDependency] = _topLevelDependencies /** The set of top-level classes that the compilation unit extends or that * contain a non-top-level class that the compilaion unit extends. */ - def topLevelInheritanceDependencies: Set[(Symbol, Symbol)] = _topLevelInheritanceDependencies + def topLevelInheritanceDependencies: Set[ClassDependency] = _topLevelInheritanceDependencies private def addUsedName(enclosingSym: Symbol, name: Name) = { - val enclosingName = enclosingSym match { - case sym if sym == defn.RootClass => ExtractDependencies.extractedName(responsibleForImports) - case sym => extractedName(sym) - } + val enclosingName = + if (enclosingSym == defn.RootClass) classNameAsString(responsibleForImports) + else classNameAsString(enclosingSym) val nameUsed = _usedNames.getOrElseUpdate(enclosingName, new NameUsedInClass) nameUsed.defaultNames += name // TODO: Set correct scope @@ -272,18 +263,15 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic val tlClass = sym.topLevelClass if (tlClass.ne(NoSymbol)) { if (currentClass == defn.RootClass) { - _topLevelDependencies += ((responsibleForImports, tlClass)) + _topLevelDependencies += ClassDependency(responsibleForImports, tlClass) } else { // Some synthetic type aliases like AnyRef do not belong to any class - _topLevelDependencies += ((currentClass, tlClass)) + _topLevelDependencies += ClassDependency(currentClass, tlClass) } } addUsedName(nonLocalEnclosingClass(ctx.owner), sym.name) } - private def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = - sym.ownersIterator.exists(_.isTerm) - private def nonLocalEnclosingClass(sym: Symbol)(implicit ctx: Context): Symbol = sym.enclosingClass match { case NoSymbol => NoSymbol @@ -300,8 +288,8 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic sym.isAnonymousFunction || sym.isAnonymousClass - private def addInheritanceDependency(sym: Symbol)(implicit ctx: Context): Unit = - _topLevelInheritanceDependencies += ((currentClass, sym.topLevelClass)) + private def addInheritanceDependency(parent: Symbol)(implicit ctx: Context): Unit = + _topLevelInheritanceDependencies += ClassDependency(currentClass, parent.topLevelClass) private class PatMatDependencyTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) { override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { diff --git a/compiler/test/dotty/Jars.scala b/compiler/test/dotty/Jars.scala index 1c3654c3b6ec..f759e241c5b5 100644 --- a/compiler/test/dotty/Jars.scala +++ b/compiler/test/dotty/Jars.scala @@ -30,7 +30,7 @@ object Jars { dottyLib :: dottyCompiler :: dottyInterfaces :: dottyExtras /** Dotty runtime with compiler dependencies, used for quoted.Expr.run */ - val dottyRunWithCompiler: List[String] = + lazy val dottyRunWithCompiler: List[String] = dottyLib :: dottyCompiler :: dottyInterfaces :: scalaAsm :: Nil def scalaLibrary: String = sys.env.get("DOTTY_SCALA_LIBRARY") diff --git a/project/Build.scala b/project/Build.scala index fc3d1d8411e0..ea801da240f1 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -8,8 +8,6 @@ import java.util.Calendar import scala.reflect.io.Path -import sbtassembly.AssemblyKeys.assembly - import xerial.sbt.pack.PackPlugin import xerial.sbt.pack.PackPlugin.autoImport._ @@ -29,9 +27,6 @@ import sbt.ScriptedPlugin.autoImport._ import xerial.sbt.pack.PackPlugin.packSettings import xerial.sbt.pack.PackPlugin.autoImport._ -import org.scalajs.sbtplugin.ScalaJSPlugin -import ScalaJSPlugin.autoImport._ - import com.typesafe.sbteclipse.plugin.EclipsePlugin.EclipseKeys import Modes._ @@ -52,21 +47,20 @@ object Build { val dottyOrganization = "ch.epfl.lamp" val dottyGithubUrl = "https://github.com/lampepfl/dotty" + + val isRelease = sys.env.get("RELEASEBUILD") == Some("yes") + val dottyVersion = { - val isNightly = sys.env.get("NIGHTLYBUILD") == Some("yes") - val isRelease = sys.env.get("RELEASEBUILD") == Some("yes") - if (isNightly) - baseVersion + "-bin-" + VersionUtil.commitDate + "-" + VersionUtil.gitHash + "-NIGHTLY" - else if (isRelease) + def isNightly = sys.env.get("NIGHTLYBUILD") == Some("yes") + if (isRelease) baseVersion + else if (isNightly) + baseVersion + "-bin-" + VersionUtil.commitDate + "-" + VersionUtil.gitHash + "-NIGHTLY" else baseVersion + "-bin-SNAPSHOT" } val dottyNonBootstrappedVersion = dottyVersion + "-nonbootstrapped" - val jenkinsMemLimit = List("-Xmx1500m") - - val JENKINS_BUILD = "dotty.jenkins.build" val DRONE_MEM = "dotty.drone.mem" @@ -205,7 +199,7 @@ object Build { ) // Settings used when compiling dotty using Scala 2 - lazy val commonNonBootstrappedSettings = commonSettings ++ publishSettings ++ Seq( + lazy val commonNonBootstrappedSettings = commonSettings ++ Seq( version := dottyNonBootstrappedVersion, scalaVersion := scalacVersion ) @@ -372,13 +366,14 @@ object Build { val majorVersion = baseVersion.take(baseVersion.lastIndexOf('.')) IO.write(file("./docs/_site/versions/latest-nightly-base"), majorVersion) - val dottyLib = (packageAll in `dotty-compiler`).value("dotty-library") - val dottyInterfaces = (packageAll in `dotty-compiler`).value("dotty-interfaces") + val jars = (packageAll in `dotty-compiler`).value + val dottyLib = jars("dotty-library") + val dottyInterfaces =jars("dotty-interfaces") val otherDeps = (dependencyClasspath in Compile).value.map(_.data).mkString(":") val sources = (unmanagedSources in (Compile, compile)).value ++ (unmanagedSources in (`dotty-compiler`, Compile)).value - val args: Seq[String] = Seq( + val args = Seq( "-siteroot", "docs", "-project", "Dotty", "-project-version", dottyVersion, @@ -392,11 +387,13 @@ object Build { dottydoc := Def.inputTaskDyn { val args: Seq[String] = spaceDelimited("").parsed - val dottyLib = (packageAll in `dotty-compiler`).value("dotty-library") - val dottyInterfaces = (packageAll in `dotty-compiler`).value("dotty-interfaces") + val jars = (packageAll in `dotty-compiler`).value + val dottyLib = jars("dotty-library") + val dottyInterfaces =jars("dotty-interfaces") val otherDeps = (dependencyClasspath in Compile).value.map(_.data).mkString(":") - val cp: Seq[String] = Seq("-classpath", s"$dottyLib:$dottyInterfaces:$otherDeps") - (runMain in Compile).toTask(s""" dotty.tools.dottydoc.Main ${cp.mkString(" ")} """ + args.mkString(" ")) + val cp = s"$dottyLib:$dottyInterfaces:$otherDeps" + + (runMain in Compile).toTask(s" dotty.tools.dottydoc.Main -classpath $cp " + args.mkString(" ")) }.evaluated, libraryDependencies ++= { @@ -529,7 +526,7 @@ object Build { // packageAll should always be run before tests javaOptions ++= { val attList = (dependencyClasspath in Runtime).value - val pA = packageAll.value + val jars = packageAll.value // put needed dependencies on classpath: val path = for { @@ -549,11 +546,10 @@ object Build { } yield "-Xbootclasspath/p:" + path val ci_build = // propagate if this is a ci build - if (sys.props.isDefinedAt(JENKINS_BUILD)) - List(s"-D$JENKINS_BUILD=${sys.props(JENKINS_BUILD)}") ::: jenkinsMemLimit - else if (sys.props.isDefinedAt(DRONE_MEM)) - List("-Xmx" + sys.props(DRONE_MEM)) - else List() + sys.props.get(DRONE_MEM) match { + case Some(prop) => List("-Xmx" + prop) + case _ => List() + } val tuning = if (sys.props.isDefinedAt("Oshort")) @@ -561,13 +557,13 @@ object Build { List("-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1") else List() - val jars = List( - "-Ddotty.tests.classes.interfaces=" + pA("dotty-interfaces"), - "-Ddotty.tests.classes.library=" + pA("dotty-library"), - "-Ddotty.tests.classes.compiler=" + pA("dotty-compiler") + val jarOpts = List( + "-Ddotty.tests.classes.interfaces=" + jars("dotty-interfaces"), + "-Ddotty.tests.classes.library=" + jars("dotty-library"), + "-Ddotty.tests.classes.compiler=" + jars("dotty-compiler") ) - jars ::: tuning ::: agentOptions ::: ci_build ::: path.toList + jarOpts ::: tuning ::: agentOptions ::: ci_build ::: path.toList }, testCompilation := Def.inputTaskDyn { @@ -579,11 +575,10 @@ object Build { (testOnly in Test).toTask(cmd) }.evaluated, - // Override run to be able to run compiled classfiles dotr := { val args: List[String] = spaceDelimited("").parsed.toList val attList = (dependencyClasspath in Runtime).value - val _ = packageAll.value + val jars = packageAll.value def findLib(name: String) = attList .map(_.data.getAbsolutePath) @@ -591,7 +586,7 @@ object Build { .toList.mkString(":") val scalaLib = findLib("scala-library") - val dottyLib = packageAll.value("dotty-library") + val dottyLib = jars("dotty-library") def run(args: List[String]): Unit = { val fullArgs = insertClasspathInArgs(args, s".:$dottyLib:$scalaLib") @@ -605,8 +600,8 @@ object Build { } else if (args.contains("-with-compiler")) { val args1 = args.filter(_ != "-with-compiler") val asm = findLib("scala-asm") - val dottyCompiler = packageAll.value("dotty-compiler") - val dottyInterfaces = packageAll.value("dotty-interfaces") + val dottyCompiler = jars("dotty-compiler") + val dottyInterfaces = jars("dotty-interfaces") run(insertClasspathInArgs(args1, s"$dottyCompiler:$dottyInterfaces:$asm")) } else run(args) }, @@ -650,8 +645,9 @@ object Build { ) def runCompilerMain(repl: Boolean = false) = Def.inputTaskDyn { - val dottyLib = packageAll.value("dotty-library") - lazy val dottyCompiler = packageAll.value("dotty-compiler") + val jars = packageAll.value + val dottyLib = jars("dotty-library") + val dottyCompiler = jars("dotty-compiler") val args0: List[String] = spaceDelimited("").parsed.toList val decompile = args0.contains("-decompile") val debugFromTasty = args0.contains("-Ythrough-tasty") @@ -805,48 +801,6 @@ object Build { }.dependsOn(compile in (`vscode-dotty`, Compile)).evaluated ).disablePlugins(ScriptedPlugin) - /** A sandbox to play with the Scala.js back-end of dotty. - * - * This sandbox is compiled with dotty with support for Scala.js. It can be - * used like any regular Scala.js project. In particular, `fastOptJS` will - * produce a .js file, and `run` will run the JavaScript code with a JS VM. - * - * Simply running `dotty/run -scalajs` without this sandbox is not very - * useful, as that would not provide the linker and JS runners. - */ - lazy val sjsSandbox = project.in(file("sandbox/scalajs")). - enablePlugins(ScalaJSPlugin). - settings(commonNonBootstrappedSettings). - settings( - /* Remove the Scala.js compiler plugin for scalac, and enable the - * Scala.js back-end of dotty instead. - */ - libraryDependencies ~= { deps => - deps.filterNot(_.name.startsWith("scalajs-compiler")) - }, - scalacOptions += "-scalajs", - - // The main class cannot be found automatically due to the empty inc.Analysis - mainClass in Compile := Some("hello.world"), - - // While developing the Scala.js back-end, it is very useful to see the trees dotc gives us - scalacOptions += "-Xprint:labelDef", - - /* Debug-friendly Scala.js optimizer options. - * In particular, typecheck the Scala.js IR found on the classpath. - */ - scalaJSOptimizerOptions ~= { - _.withCheckScalaJSIR(true).withParallel(false) - } - ). - settings(compileWithDottySettings). - settings(inConfig(Compile)(Seq( - /* Make sure jsDependencyManifest runs after compile, otherwise compile - * might remove the entire directory afterwards. - */ - jsDependencyManifest := jsDependencyManifest.dependsOn(compile).value - ))) - lazy val `dotty-bench` = project.in(file("bench")).asDottyBench(NonBootstrapped) lazy val `dotty-bench-bootstrapped` = project.in(file("bench")).asDottyBench(Bootstrapped).disablePlugins(ScriptedPlugin) lazy val `dotty-bench-optimised` = project.in(file("bench")).asDottyBench(BootstrappedOptimised).disablePlugins(ScriptedPlugin) @@ -883,6 +837,11 @@ object Build { lazy val `sbt-dotty` = project.in(file("sbt-dotty")). settings(commonSettings). settings( + version := { + val base = "0.2.0" + if (isRelease) base else base + "-SNAPSHOT" + }, + // Keep in sync with inject-sbt-dotty.sbt libraryDependencies ++= Seq( Dependencies.`jackson-databind`, @@ -891,7 +850,6 @@ object Build { unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", sbtPlugin := true, - version := "0.2.0", sbtTestDirectory := baseDirectory.value / "sbt-test", scriptedLaunchOpts ++= Seq( "-Dplugin.version=" + version.value, @@ -901,15 +859,15 @@ object Build { // By default scripted tests use $HOME/.ivy2 for the ivy cache. We need to override this value for the CI. scriptedLaunchOpts ++= ivyPaths.value.ivyHome.map("-Dsbt.ivy.home=" + _.getAbsolutePath).toList, scriptedBufferLog := true, - scripted := scripted.dependsOn(Def.task { - val x0 = (publishLocal in `dotty-sbt-bridge-bootstrapped`).value - val x1 = (publishLocal in `dotty-interfaces`).value - val x2 = (publishLocal in `dotty-compiler-bootstrapped`).value - val x3 = (publishLocal in `dotty-library-bootstrapped`).value - val x4 = (publishLocal in `scala-library`).value - val x5 = (publishLocal in `scala-reflect`).value - val x6 = (publishLocal in `dotty-bootstrapped`).value // Needed because sbt currently hardcodes the dotty artifact - }).evaluated + scripted := scripted.dependsOn( + publishLocal in `dotty-sbt-bridge-bootstrapped`, + publishLocal in `dotty-interfaces`, + publishLocal in `dotty-compiler-bootstrapped`, + publishLocal in `dotty-library-bootstrapped`, + publishLocal in `scala-library`, + publishLocal in `scala-reflect`, + publishLocal in `dotty-bootstrapped` // Needed because sbt currently hardcodes the dotty artifact + ).evaluated ) lazy val `vscode-dotty` = project.in(file("vscode-dotty")). @@ -1150,6 +1108,48 @@ object Build { lazy val `dist-bootstrapped` = project.asDist(Bootstrapped).disablePlugins(ScriptedPlugin) lazy val `dist-optimised` = project.asDist(BootstrappedOptimised).disablePlugins(ScriptedPlugin) + // /** A sandbox to play with the Scala.js back-end of dotty. + // * + // * This sandbox is compiled with dotty with support for Scala.js. It can be + // * used like any regular Scala.js project. In particular, `fastOptJS` will + // * produce a .js file, and `run` will run the JavaScript code with a JS VM. + // * + // * Simply running `dotty/run -scalajs` without this sandbox is not very + // * useful, as that would not provide the linker and JS runners. + // */ + // lazy val sjsSandbox = project.in(file("sandbox/scalajs")). + // enablePlugins(ScalaJSPlugin). + // settings(commonNonBootstrappedSettings). + // settings( + // /* Remove the Scala.js compiler plugin for scalac, and enable the + // * Scala.js back-end of dotty instead. + // */ + // libraryDependencies ~= { deps => + // deps.filterNot(_.name.startsWith("scalajs-compiler")) + // }, + // scalacOptions += "-scalajs", + + // // The main class cannot be found automatically due to the empty inc.Analysis + // mainClass in Compile := Some("hello.world"), + + // // While developing the Scala.js back-end, it is very useful to see the trees dotc gives us + // scalacOptions += "-Xprint:labelDef", + + // /* Debug-friendly Scala.js optimizer options. + // * In particular, typecheck the Scala.js IR found on the classpath. + // */ + // scalaJSOptimizerOptions ~= { + // _.withCheckScalaJSIR(true).withParallel(false) + // } + // ). + // settings(compileWithDottySettings). + // settings(inConfig(Compile)(Seq( + // /* Make sure jsDependencyManifest runs after compile, otherwise compile + // * might remove the entire directory afterwards. + // */ + // jsDependencyManifest := jsDependencyManifest.dependsOn(compile).value + // ))) + implicit class ProjectDefinitions(val project: Project) extends AnyVal { // FIXME: we do not aggregate `bin` because its tests delete jars, thus breaking other tests diff --git a/project/plugins.sbt b/project/plugins.sbt index b7cee145605a..8e9587ae889d 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,9 +5,7 @@ // Scala IDE project file generator addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.21") - -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6") +// addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.21") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.1") diff --git a/sbt-dotty/sbt-test/source-dependencies/binary/pending b/sbt-dotty/sbt-test/source-dependencies/binary/test similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/binary/pending rename to sbt-dotty/sbt-test/source-dependencies/binary/test diff --git a/sbt-dotty/sbt-test/source-dependencies/resident-package-object/build.sbt b/sbt-dotty/sbt-test/source-dependencies/resident-package-object/build.sbt new file mode 100644 index 000000000000..894036b97cc1 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/resident-package-object/build.sbt @@ -0,0 +1,3 @@ +incOptions := incOptions.value + .withApiDebug(true) + .withRelationsDebug(true) From 3a60f32d208a0195044025ccdb37fdac25c225b1 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Mon, 19 Feb 2018 17:23:33 +0100 Subject: [PATCH 054/101] Use mangledString instead of toString Should we do that? mangledString is much more expensive --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 32 +++++++++---------- .../tools/dotc/sbt/ExtractDependencies.scala | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index af34402728fb..3259f66b8909 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -207,7 +207,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val selfType = apiType(sym.givenSelfType) - val name = ExtractDependencies.classNameAsString(sym) + val name = sym.fullName.stripModuleClassSuffix.mangledString val tparams = sym.typeParams.map(apiTypeParameter).toArray @@ -316,7 +316,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder if (aIsClass == bIsClass) { if (aIsClass) { if (a.is(Module) == b.is(Module)) - a.fullName.toString.compareTo(b.fullName.toString) + a.fullName.mangledString.compareTo(b.fullName.mangledString) else if (a.is(Module)) -1 else @@ -340,10 +340,10 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } else if (sym.isType) { apiTypeMember(sym.asType) } else if (sym.is(Mutable, butNot = Accessor)) { - api.Var.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), + api.Var.of(sym.name.mangledString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, apiType(sym.info)) } else if (sym.isStable) { - api.Val.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), + api.Val.of(sym.name.mangledString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, apiType(sym.info)) } else { apiDef(sym.asTerm) @@ -370,7 +370,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } else (0 until pnames.length).map(Function.const(false)) val params = (pnames, ptypes, defaults).zipped.map((pname, ptype, isDefault) => - api.MethodParameter.of(pname.toString, apiType(ptype), + api.MethodParameter.of(pname.mangledString, apiType(ptype), isDefault, api.ParameterModifier.Plain)) api.ParameterList.of(params.toArray, mt.isImplicitMethod) :: paramLists(restpe, params.length) case _ => @@ -380,20 +380,20 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val tparams = sym.info match { case pt: TypeLambda => (pt.paramNames, pt.paramInfos).zipped.map((pname, pbounds) => - apiTypeParameter(pname.toString, 0, pbounds.lo, pbounds.hi)) + apiTypeParameter(pname.mangledString, 0, pbounds.lo, pbounds.hi)) case _ => Nil } val vparamss = paramLists(sym.info) val retTp = sym.info.finalResultType.widenExpr - api.Def.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), + api.Def.of(sym.name.mangledString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, tparams.toArray, vparamss.toArray, apiType(retTp)) } def apiTypeMember(sym: TypeSymbol): api.TypeMember = { val typeParams = Array[api.TypeParameter]() - val name = sym.name.toString + val name = sym.name.mangledString val access = apiAccess(sym) val modifiers = apiModifiers(sym) val as = apiAnnotations(sym) @@ -439,7 +439,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder sym.owner.thisType else tp.prefix - api.Projection.of(apiType(prefix), sym.name.toString) + api.Projection.of(apiType(prefix), sym.name.mangledString) case AppliedType(tycon, args) => def processArg(arg: Type): api.Type = arg match { case arg @ TypeBounds(lo, hi) => // Handle wildcard parameters @@ -463,7 +463,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val apiRes = apiType(tl.resType) api.Polymorphic.of(apiRes, apiTparams.toArray) case rt: RefinedType => - val name = rt.refinedName.toString + val name = rt.refinedName.mangledString val parent = apiType(rt.parent) def typeRefinement(name: String, tp: TypeBounds): api.TypeMember = tp match { @@ -536,7 +536,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder case tp: ParamRef => // TODO: Distinguishing parameters based on their names alone is not enough, // the binder is also needed (at least for type lambdas). - api.ParameterRef.of(tp.paramName.toString) + api.ParameterRef.of(tp.paramName.mangledString) case tp: LazyRef => apiType(tp.ref) case tp: TypeVar => @@ -557,12 +557,12 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder def apiThis(sym: Symbol): api.Singleton = { val pathComponents = sym.ownersIterator.takeWhile(!_.isEffectiveRoot) - .map(s => api.Id.of(s.name.toString)) + .map(s => api.Id.of(s.name.mangledString)) api.Singleton.of(api.Path.of(pathComponents.toArray.reverse ++ Array(Constants.thisPath))) } def apiTypeParameter(tparam: ParamInfo): api.TypeParameter = - apiTypeParameter(tparam.paramName.toString, tparam.paramVariance, + apiTypeParameter(tparam.paramName.mangledString, tparam.paramVariance, tparam.paramInfo.bounds.lo, tparam.paramInfo.bounds.hi) def apiTypeParameter(name: String, variance: Int, lo: Type, hi: Type): api.TypeParameter = @@ -590,7 +590,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder if (sym.privateWithin eq NoSymbol) Constants.unqualified else - api.IdQualifier.of(sym.privateWithin.fullName.toString) + api.IdQualifier.of(sym.privateWithin.fullName.mangledString) if (sym.is(Protected)) api.Protected.of(qualifier) else @@ -617,7 +617,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // To do this properly we would need a way to hash trees and types in // dotty itself. val printTypesCtx = ctx.fresh.setSetting(ctx.settings.XprintTypes, true) - annots += marker(Inliner.bodyToInline(s).show(printTypesCtx).toString) + annots += marker(Inliner.bodyToInline(s).show(printTypesCtx)) } // In the Scala2 ExtractAPI phase we only extract annotations that extend @@ -641,6 +641,6 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // junit tests are annotated @org.junit.Test). api.Annotation.of( apiType(annot.tree.tpe), // Used by sbt to find tests to run - Array(api.AnnotationArgument.of("FULLTREE", annot.tree.show.toString))) + Array(api.AnnotationArgument.of("FULLTREE", annot.tree.show))) } } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index d223a99755f6..c29f419af38e 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -87,9 +87,9 @@ class ExtractDependencies extends Phase { if (ctx.sbtCallback != null) { extractDeps.usedNames.foreach{ case (rawClassName, usedNames) => - val className = rawClassName.toString + val className = rawClassName usedNames.defaultNames.foreach { rawUsedName => - val useName = rawUsedName.toString + val useName = rawUsedName.stripModuleClassSuffix.mangledString val useScopes = usedNames.scopedNames.get(rawUsedName) match { case None => EnumSet.of(UseScope.Default) From a2d86e85d31cbce4bb54720c5c2eca2e0a6ef391 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 1 Mar 2018 16:16:05 +0100 Subject: [PATCH 055/101] Use Dotty naming scheme and toString --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 30 +++++++++---------- .../tools/dotc/sbt/ExtractDependencies.scala | 6 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 3259f66b8909..1d45bab6c2dc 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -207,7 +207,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val selfType = apiType(sym.givenSelfType) - val name = sym.fullName.stripModuleClassSuffix.mangledString + val name = sym.fullName.toString val tparams = sym.typeParams.map(apiTypeParameter).toArray @@ -241,7 +241,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val javaPlatform = ctx.platform.asInstanceOf[JavaPlatform] if (sym.isStatic && defType == DefinitionType.Module && javaPlatform.hasJavaMainMethod(sym)) { - _mainClasses += name + _mainClasses += sym.fullName.stripModuleClassSuffix.toString // required for sbt to find the static main method } api.ClassLikeDef.of(name, acc, modifiers, anns, tparams, defType) @@ -316,7 +316,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder if (aIsClass == bIsClass) { if (aIsClass) { if (a.is(Module) == b.is(Module)) - a.fullName.mangledString.compareTo(b.fullName.mangledString) + a.fullName.toString.compareTo(b.fullName.toString) else if (a.is(Module)) -1 else @@ -340,10 +340,10 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } else if (sym.isType) { apiTypeMember(sym.asType) } else if (sym.is(Mutable, butNot = Accessor)) { - api.Var.of(sym.name.mangledString, apiAccess(sym), apiModifiers(sym), + api.Var.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, apiType(sym.info)) } else if (sym.isStable) { - api.Val.of(sym.name.mangledString, apiAccess(sym), apiModifiers(sym), + api.Val.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, apiType(sym.info)) } else { apiDef(sym.asTerm) @@ -370,7 +370,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } else (0 until pnames.length).map(Function.const(false)) val params = (pnames, ptypes, defaults).zipped.map((pname, ptype, isDefault) => - api.MethodParameter.of(pname.mangledString, apiType(ptype), + api.MethodParameter.of(pname.toString, apiType(ptype), isDefault, api.ParameterModifier.Plain)) api.ParameterList.of(params.toArray, mt.isImplicitMethod) :: paramLists(restpe, params.length) case _ => @@ -380,20 +380,20 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val tparams = sym.info match { case pt: TypeLambda => (pt.paramNames, pt.paramInfos).zipped.map((pname, pbounds) => - apiTypeParameter(pname.mangledString, 0, pbounds.lo, pbounds.hi)) + apiTypeParameter(pname.toString, 0, pbounds.lo, pbounds.hi)) case _ => Nil } val vparamss = paramLists(sym.info) val retTp = sym.info.finalResultType.widenExpr - api.Def.of(sym.name.mangledString, apiAccess(sym), apiModifiers(sym), + api.Def.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, tparams.toArray, vparamss.toArray, apiType(retTp)) } def apiTypeMember(sym: TypeSymbol): api.TypeMember = { val typeParams = Array[api.TypeParameter]() - val name = sym.name.mangledString + val name = sym.name.toString val access = apiAccess(sym) val modifiers = apiModifiers(sym) val as = apiAnnotations(sym) @@ -439,7 +439,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder sym.owner.thisType else tp.prefix - api.Projection.of(apiType(prefix), sym.name.mangledString) + api.Projection.of(apiType(prefix), sym.name.toString) case AppliedType(tycon, args) => def processArg(arg: Type): api.Type = arg match { case arg @ TypeBounds(lo, hi) => // Handle wildcard parameters @@ -463,7 +463,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val apiRes = apiType(tl.resType) api.Polymorphic.of(apiRes, apiTparams.toArray) case rt: RefinedType => - val name = rt.refinedName.mangledString + val name = rt.refinedName.toString val parent = apiType(rt.parent) def typeRefinement(name: String, tp: TypeBounds): api.TypeMember = tp match { @@ -536,7 +536,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder case tp: ParamRef => // TODO: Distinguishing parameters based on their names alone is not enough, // the binder is also needed (at least for type lambdas). - api.ParameterRef.of(tp.paramName.mangledString) + api.ParameterRef.of(tp.paramName.toString) case tp: LazyRef => apiType(tp.ref) case tp: TypeVar => @@ -557,12 +557,12 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder def apiThis(sym: Symbol): api.Singleton = { val pathComponents = sym.ownersIterator.takeWhile(!_.isEffectiveRoot) - .map(s => api.Id.of(s.name.mangledString)) + .map(s => api.Id.of(s.name.toString)) api.Singleton.of(api.Path.of(pathComponents.toArray.reverse ++ Array(Constants.thisPath))) } def apiTypeParameter(tparam: ParamInfo): api.TypeParameter = - apiTypeParameter(tparam.paramName.mangledString, tparam.paramVariance, + apiTypeParameter(tparam.paramName.toString, tparam.paramVariance, tparam.paramInfo.bounds.lo, tparam.paramInfo.bounds.hi) def apiTypeParameter(name: String, variance: Int, lo: Type, hi: Type): api.TypeParameter = @@ -590,7 +590,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder if (sym.privateWithin eq NoSymbol) Constants.unqualified else - api.IdQualifier.of(sym.privateWithin.fullName.mangledString) + api.IdQualifier.of(sym.privateWithin.fullName.toString) if (sym.is(Protected)) api.Protected.of(qualifier) else diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index c29f419af38e..06efc04d7530 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -89,7 +89,7 @@ class ExtractDependencies extends Phase { case (rawClassName, usedNames) => val className = rawClassName usedNames.defaultNames.foreach { rawUsedName => - val useName = rawUsedName.stripModuleClassSuffix.mangledString + val useName = rawUsedName.toString val useScopes = usedNames.scopedNames.get(rawUsedName) match { case None => EnumSet.of(UseScope.Default) @@ -179,7 +179,7 @@ class ExtractDependencies extends Phase { object ExtractDependencies { def classNameAsString(sym: Symbol)(implicit ctx: Context): String = - sym.fullName.stripModuleClassSuffix.mangledString // fullName in scalac strips module class suffix + sym.fullName.toString def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = sym.ownersIterator.exists(_.isTerm) @@ -294,7 +294,7 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic private class PatMatDependencyTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) { override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val encName = nonLocalEnclosingClass(ctx.owner).fullName.stripModuleClassSuffix.mangledString + val encName = nonLocalEnclosingClass(ctx.owner).fullName.toString val nameUsed = _usedNames.getOrElseUpdate(encName, new NameUsedInClass) nameUsed.defaultNames += symbol.name From 4a74fb75b7f436049251a823b9514ce04ed9dd6e Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 1 Mar 2018 16:42:22 +0100 Subject: [PATCH 056/101] Strip module suffix for module class Zinc relies on class and its companion class having the same name: this creates an implicit dependency between the two. --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 5 +++-- compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 1d45bab6c2dc..e4f4e109debd 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -207,7 +207,8 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val selfType = apiType(sym.givenSelfType) - val name = sym.fullName.toString + val name = sym.fullName.stripModuleClassSuffix.toString + // We strip module class suffix. Zinc relies on a class and its companion having the same name val tparams = sym.typeParams.map(apiTypeParameter).toArray @@ -241,7 +242,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val javaPlatform = ctx.platform.asInstanceOf[JavaPlatform] if (sym.isStatic && defType == DefinitionType.Module && javaPlatform.hasJavaMainMethod(sym)) { - _mainClasses += sym.fullName.stripModuleClassSuffix.toString // required for sbt to find the static main method + _mainClasses += name } api.ClassLikeDef.of(name, acc, modifiers, anns, tparams, defType) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 06efc04d7530..0009d60c349c 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -179,7 +179,7 @@ class ExtractDependencies extends Phase { object ExtractDependencies { def classNameAsString(sym: Symbol)(implicit ctx: Context): String = - sym.fullName.toString + sym.fullName.stripModuleClassSuffix.toString def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = sym.ownersIterator.exists(_.isTerm) @@ -269,7 +269,7 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic _topLevelDependencies += ClassDependency(currentClass, tlClass) } } - addUsedName(nonLocalEnclosingClass(ctx.owner), sym.name) + addUsedName(nonLocalEnclosingClass(ctx.owner), sym.name.stripModuleClassSuffix) } private def nonLocalEnclosingClass(sym: Symbol)(implicit ctx: Context): Symbol = @@ -294,7 +294,7 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic private class PatMatDependencyTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) { override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val encName = nonLocalEnclosingClass(ctx.owner).fullName.toString + val encName = nonLocalEnclosingClass(ctx.owner).fullName.stripModuleClassSuffix.toString val nameUsed = _usedNames.getOrElseUpdate(encName, new NameUsedInClass) nameUsed.defaultNames += symbol.name From 88fb4ea91b596a50e14c50c6db7c243c38e4a8ca Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Mon, 5 Mar 2018 16:46:21 +0100 Subject: [PATCH 057/101] Fix separate compilation --- .../dotty/tools/backend/jvm/GenBCode.scala | 7 +++--- .../tools/dotc/sbt/ExtractDependencies.scala | 22 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index 8a1131cea9ec..0f2f1e076207 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -270,16 +270,15 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter for ((cls, clsFile) <- classNodes.zip(classFiles)) { if (cls != null) { + val className = cls.name.replace('/', '.') if (ctx.compilerCallback != null) - ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(clsFile), fullClassName) + ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(clsFile), className) if (ctx.sbtCallback != null) { - // ctx.sbtCallback.generatedClass(sourceFile.jfile.orElse(null), clsFile.file, fullClassName) - // TODO: Check if (isLocal) ctx.sbtCallback.generatedLocalClass(sourceFile.jfile.orElse(null), clsFile.file) else { ctx.sbtCallback.generatedNonLocalClass(sourceFile.jfile.orElse(null), clsFile.file, - cls.name, fullClassName) + className, fullClassName) } } } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 0009d60c349c..d2e0fd0660ae 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -139,23 +139,25 @@ class ExtractDependencies extends Phase { ctx.sbtCallback.binaryDependency(file, binaryClassName, fromClassName, sourceFile, context) def processExternalDependency(depFile: AbstractFile) = { - def binaryClassName(classSegments: List[String]) = - classSegments.mkString(".").stripSuffix(".class") + + val binaryClassName = ctx.atPhase(ctx.flattenPhase) { implicit ctx => + dep.to.fullName.toString + } depFile match { case ze: ZipArchive#Entry => // The dependency comes from a JAR for (zip <- ze.underlyingSource; zipFile <- Option(zip.file)) { - val classSegments = io.File(ze.path).segments - binaryDependency(zipFile, binaryClassName(classSegments)) + binaryDependency(zipFile, binaryClassName) } case pf: PlainFile => // The dependency comes from a class file - val packages = dep.to.ownersIterator - .filter(x => x.is(PackageClass) && !x.isEffectiveRoot).length - // We can recover the fully qualified name of a classfile from - // its path - val classSegments = pf.givenPath.segments.takeRight(packages + 1) - binaryDependency(pf.file, binaryClassName(classSegments)) + val classFile = + if (dep.to.is(ModuleClass, butNot = Scala2x)) + new File(pf.path.stripSuffix(".class") + "$.class") + // Module Class loaded from TASTY are loaded from their companion class file. + // We recover the name of the module class file. + else pf.file + binaryDependency(classFile, binaryClassName) case _ => ctx.warning(s"sbt-deps: Ignoring dependency $depFile of class ${depFile.getClass}}") From fd5aa5339cb0b1f5b443de9678fb8671c026178b Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Mon, 5 Mar 2018 18:43:01 +0100 Subject: [PATCH 058/101] Fix binary class name for Java Symbol --- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index d2e0fd0660ae..27a5aaa0e860 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -141,7 +141,8 @@ class ExtractDependencies extends Phase { def processExternalDependency(depFile: AbstractFile) = { val binaryClassName = ctx.atPhase(ctx.flattenPhase) { implicit ctx => - dep.to.fullName.toString + if (dep.to.is(JavaDefined)) dep.to.fullName.stripModuleClassSuffix.toString + else dep.to.fullName.toString } depFile match { @@ -151,13 +152,7 @@ class ExtractDependencies extends Phase { } case pf: PlainFile => // The dependency comes from a class file - val classFile = - if (dep.to.is(ModuleClass, butNot = Scala2x)) - new File(pf.path.stripSuffix(".class") + "$.class") - // Module Class loaded from TASTY are loaded from their companion class file. - // We recover the name of the module class file. - else pf.file - binaryDependency(classFile, binaryClassName) + binaryDependency(pf.file, binaryClassName) case _ => ctx.warning(s"sbt-deps: Ignoring dependency $depFile of class ${depFile.getClass}}") From 9994ebfd004be7a34d312dccf8d2b5fd7bb402eb Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Mon, 5 Mar 2018 19:03:52 +0100 Subject: [PATCH 059/101] Revert to old scheme for binary class name --- .../tools/dotc/sbt/ExtractDependencies.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 27a5aaa0e860..648d5c29117a 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -139,20 +139,23 @@ class ExtractDependencies extends Phase { ctx.sbtCallback.binaryDependency(file, binaryClassName, fromClassName, sourceFile, context) def processExternalDependency(depFile: AbstractFile) = { - - val binaryClassName = ctx.atPhase(ctx.flattenPhase) { implicit ctx => - if (dep.to.is(JavaDefined)) dep.to.fullName.stripModuleClassSuffix.toString - else dep.to.fullName.toString - } + def binaryClassName(classSegments: List[String]) = + classSegments.mkString(".").stripSuffix(".class") depFile match { case ze: ZipArchive#Entry => // The dependency comes from a JAR for (zip <- ze.underlyingSource; zipFile <- Option(zip.file)) { - binaryDependency(zipFile, binaryClassName) + val classSegments = io.File(ze.path).segments + binaryDependency(zipFile, binaryClassName(classSegments)) } case pf: PlainFile => // The dependency comes from a class file - binaryDependency(pf.file, binaryClassName) + val packages = dep.to.ownersIterator + .count(x => x.is(PackageClass) && !x.isEffectiveRoot) + // We can recover the fully qualified name of a classfile from + // its path + val classSegments = pf.givenPath.segments.takeRight(packages + 1) + binaryDependency(pf.file, binaryClassName(classSegments)) case _ => ctx.warning(s"sbt-deps: Ignoring dependency $depFile of class ${depFile.getClass}}") From cf20829ce19e01915c031233e3c698c0fe7b72f5 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Mon, 5 Mar 2018 19:07:36 +0100 Subject: [PATCH 060/101] Small build cleanup --- project/Build.scala | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 4208398f4608..dcd082907933 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -61,9 +61,6 @@ object Build { } val dottyNonBootstrappedVersion = dottyVersion + "-nonbootstrapped" - val DRONE_MEM = "dotty.drone.mem" - - val agentOptions = List( // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" // "-agentpath:/home/dark/opt/yjp-2013-build-13072/bin/linux-x86-64/libyjpagent.so" @@ -133,19 +130,13 @@ object Build { // Settings shared globally (scoped in Global). Used in build.sbt lazy val globalSettings = Def.settings( - // Override `runCode` from sbt-dotty to use the language-server and - // vscode extension from the source repository of dotty instead of a - // published version. - runCode := (run in `dotty-language-server`).toTask("").value, - onLoad := (onLoad in Global).value andThen { state => def exists(submodule: String) = { val path = Paths.get(submodule) Files.exists(path) && { val fileStream = Files.list(path) - val nonEmpty = fileStream.iterator().hasNext() - fileStream.close() - nonEmpty + try fileStream.iterator().hasNext() + finally fileStream.close() } } @@ -546,7 +537,7 @@ object Build { } yield "-Xbootclasspath/p:" + path val ci_build = // propagate if this is a ci build - sys.props.get(DRONE_MEM) match { + sys.props.get("dotty.drone.mem") match { case Some(prop) => List("-Xmx" + prop) case _ => List() } From 31a93a129f01e8b098d6cee64abfa8f20befc8a1 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 6 Mar 2018 19:11:07 +0100 Subject: [PATCH 061/101] Merge two caches --- .../tools/dotc/sbt/ExtractDependencies.scala | 41 +++++++------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 648d5c29117a..3a8b40fe4a09 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -70,17 +70,14 @@ class ExtractDependencies extends Phase { if (dumpInc) { val names = extractDeps.usedNames.map(_.toString).toArray[Object] - val deps = extractDeps.topLevelDependencies.map(_.toString).toArray[Object] - val inhDeps = extractDeps.topLevelInheritanceDependencies.map(_.toString).toArray[Object] + val deps = extractDeps.dependencies.map(_.toString).toArray[Object] Arrays.sort(names) Arrays.sort(deps) - Arrays.sort(inhDeps) val pw = io.File(sourceFile.jpath).changeExtension("inc").toFile.printWriter() try { pw.println(s"// usedNames: ${names.mkString(",")}") - pw.println(s"// topLevelDependencies: ${deps.mkString(",")}") - pw.println(s"// topLevelInheritanceDependencies: ${inhDeps.mkString(",")}") + pw.println(s"// Dependencies: ${deps.mkString(",")}") } finally pw.close() } @@ -102,9 +99,7 @@ class ExtractDependencies extends Phase { } } - // FIXME: https://github.com/sbt/zinc/commit/05482d131346d645375263e1420d2cd19b2ea6ef - extractDeps.topLevelDependencies.foreach(dep => recordDependency(dep, DependencyByMemberRef, allowLocal = true)) - extractDeps.topLevelInheritanceDependencies.foreach(dep => recordDependency(dep, DependencyByInheritance, allowLocal = true)) + extractDeps.dependencies.foreach(recordDependency) } } } @@ -131,12 +126,12 @@ class ExtractDependencies extends Phase { * that is coming from either source code (not necessarily compiled in this compilation * run) or from class file and calls respective callback method. */ - def recordDependency(dep: ClassDependency, context: DependencyContext, allowLocal: Boolean)(implicit ctx: Context): Unit = { + def recordDependency(dep: ClassDependency)(implicit ctx: Context): Unit = { val fromClassName = classNameAsString(dep.from) val sourceFile = ctx.compilationUnit.source.file.file def binaryDependency(file: File, binaryClassName: String) = - ctx.sbtCallback.binaryDependency(file, binaryClassName, fromClassName, sourceFile, context) + ctx.sbtCallback.binaryDependency(file, binaryClassName, fromClassName, sourceFile, dep.context) def processExternalDependency(depFile: AbstractFile) = { def binaryClassName(classSegments: List[String]) = @@ -164,6 +159,8 @@ class ExtractDependencies extends Phase { val depFile = dep.to.associatedFile if (depFile != null) { + // Cannot ignore inheritance relationship coming from the same source (see sbt/zinc#417) + def allowLocal = dep.context == DependencyByInheritance || dep.context == LocalDependencyByInheritance if (depFile.extension == "class") { // Dependency is external -- source is undefined processExternalDependency(depFile) @@ -171,7 +168,7 @@ class ExtractDependencies extends Phase { // We cannot ignore dependencies coming from the same source file because // the dependency info needs to propagate. See source-dependencies/trait-trait-211. val toClassName = classNameAsString(dep.to) - ctx.sbtCallback.classDependency(toClassName, fromClassName, context) + ctx.sbtCallback.classDependency(toClassName, fromClassName, dep.context) } } } @@ -185,7 +182,7 @@ object ExtractDependencies { sym.ownersIterator.exists(_.isTerm) } -private case class ClassDependency(from: Symbol, to: Symbol) +private case class ClassDependency(from: Symbol, to: Symbol, context: DependencyContext) private final class NameUsedInClass { // Default names and other scopes are separated for performance reasons @@ -229,24 +226,16 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic import ExtractDependencies._ private[this] val _usedNames = new mutable.HashMap[String, NameUsedInClass] - private[this] val _topLevelDependencies = new mutable.HashSet[ClassDependency] - private[this] val _topLevelInheritanceDependencies = new mutable.HashSet[ClassDependency] + private[this] val _dependencies = new mutable.HashSet[ClassDependency] /** The names used in this class, this does not include names which are only * defined and not referenced. */ def usedNames: collection.Map[String, NameUsedInClass] = _usedNames - /** The set of top-level classes that the compilation unit depends on - * because it refers to these classes or something defined in them. - * This is always a superset of `topLevelInheritanceDependencies` by definition. + /** The set of class dependencies from this compilation unit. */ - def topLevelDependencies: Set[ClassDependency] = _topLevelDependencies - - /** The set of top-level classes that the compilation unit extends or that - * contain a non-top-level class that the compilaion unit extends. - */ - def topLevelInheritanceDependencies: Set[ClassDependency] = _topLevelInheritanceDependencies + def dependencies: Set[ClassDependency] = _dependencies private def addUsedName(enclosingSym: Symbol, name: Name) = { val enclosingName = @@ -263,10 +252,10 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic val tlClass = sym.topLevelClass if (tlClass.ne(NoSymbol)) { if (currentClass == defn.RootClass) { - _topLevelDependencies += ClassDependency(responsibleForImports, tlClass) + _dependencies += ClassDependency(responsibleForImports, tlClass, DependencyByMemberRef) } else { // Some synthetic type aliases like AnyRef do not belong to any class - _topLevelDependencies += ClassDependency(currentClass, tlClass) + _dependencies += ClassDependency(currentClass, tlClass, DependencyByMemberRef) } } addUsedName(nonLocalEnclosingClass(ctx.owner), sym.name.stripModuleClassSuffix) @@ -289,7 +278,7 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic sym.isAnonymousClass private def addInheritanceDependency(parent: Symbol)(implicit ctx: Context): Unit = - _topLevelInheritanceDependencies += ClassDependency(currentClass, parent.topLevelClass) + _dependencies += ClassDependency(currentClass, parent.topLevelClass, DependencyByInheritance) private class PatMatDependencyTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) { override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { From 96aa56251e38881e5bfe7ed87a283e4e756d7574 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 6 Mar 2018 19:30:38 +0100 Subject: [PATCH 062/101] Simplify UsedName --- .../tools/dotc/sbt/ExtractDependencies.scala | 76 ++++++++----------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 3a8b40fe4a09..bcd691690ea4 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -69,7 +69,7 @@ class ExtractDependencies extends Phase { extractDeps.traverse(unit.tpdTree) if (dumpInc) { - val names = extractDeps.usedNames.map(_.toString).toArray[Object] + val names = extractDeps.usedNames.map { case (clazz, names) => s"$clazz: $names" }.toArray[Object] val deps = extractDeps.dependencies.map(_.toString).toArray[Object] Arrays.sort(names) Arrays.sort(deps) @@ -82,20 +82,12 @@ class ExtractDependencies extends Phase { } if (ctx.sbtCallback != null) { - extractDeps.usedNames.foreach{ - case (rawClassName, usedNames) => - val className = rawClassName - usedNames.defaultNames.foreach { rawUsedName => - val useName = rawUsedName.toString - val useScopes = - usedNames.scopedNames.get(rawUsedName) match { - case None => EnumSet.of(UseScope.Default) - case Some(existingScopes) => - existingScopes.add(UseScope.Default) - existingScopes - } - - ctx.sbtCallback.usedName(className, useName, useScopes) + extractDeps.usedNames.foreach { + case (clazz, usedNames) => + val className = clazz + usedNames.names.foreach { + case (usedName, scopes) => + ctx.sbtCallback.usedName(className, usedName.toString, scopes) } } @@ -184,29 +176,25 @@ object ExtractDependencies { private case class ClassDependency(from: Symbol, to: Symbol, context: DependencyContext) -private final class NameUsedInClass { - // Default names and other scopes are separated for performance reasons - val defaultNames: mutable.Set[Name] = new mutable.HashSet[Name] - val scopedNames: mutable.Map[Name, EnumSet[UseScope]] = new mutable.HashMap[Name, EnumSet[UseScope]].withDefault(_ => EnumSet.noneOf(classOf[UseScope])) +private final class UsedNamesInClass { + private val _names = new mutable.HashMap[Name, EnumSet[UseScope]] + def names: collection.Map[Name, EnumSet[UseScope]] = _names + + def update(name: Name, scope: UseScope): Unit = { + val scopes = _names.getOrElseUpdate(name, EnumSet.noneOf(classOf[UseScope])) + scopes.add(scope) + } - // We have to leave with commas on ends override def toString(): String = { - val builder = new StringBuilder(": ") - defaultNames.foreach { name => - builder.append(name.toString.trim) - val otherScopes = scopedNames.get(name) - scopedNames.get(name) match { - case None => - case Some(otherScopes) => - // Pickling tests fail when this is turned in an anonymous class - class Consumer extends java.util.function.Consumer[UseScope]() { - override def accept(scope: UseScope): Unit = - builder.append(scope.name()).append(", ") - } - builder.append(" in [") - otherScopes.forEach(new Consumer) - builder.append("]") - } + val builder = new StringBuilder + names.foreach { case (name, scopes) => + builder.append(name.mangledString) + builder.append(" in [") + scopes.forEach(new java.util.function.Consumer[UseScope]() { // TODO: Adapt to SAM type when #2732 is fixed + override def accept(scope: UseScope): Unit = + builder.append(scope.toString) + }) + builder.append("]") builder.append(", ") } builder.toString() @@ -225,13 +213,13 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic import tpd._ import ExtractDependencies._ - private[this] val _usedNames = new mutable.HashMap[String, NameUsedInClass] + private[this] val _usedNames = new mutable.HashMap[String, UsedNamesInClass] private[this] val _dependencies = new mutable.HashSet[ClassDependency] /** The names used in this class, this does not include names which are only * defined and not referenced. */ - def usedNames: collection.Map[String, NameUsedInClass] = _usedNames + def usedNames: collection.Map[String, UsedNamesInClass] = _usedNames /** The set of class dependencies from this compilation unit. */ @@ -241,10 +229,8 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic val enclosingName = if (enclosingSym == defn.RootClass) classNameAsString(responsibleForImports) else classNameAsString(enclosingSym) - val nameUsed = _usedNames.getOrElseUpdate(enclosingName, new NameUsedInClass) - nameUsed.defaultNames += name - // TODO: Set correct scope - nameUsed.scopedNames(name).add(UseScope.Default) + val nameUsed = _usedNames.getOrElseUpdate(enclosingName, new UsedNamesInClass) + nameUsed.update(name, UseScope.Default) } private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = @@ -284,10 +270,10 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { if (!ignoreDependency(symbol) && symbol.is(Sealed)) { val encName = nonLocalEnclosingClass(ctx.owner).fullName.stripModuleClassSuffix.toString - val nameUsed = _usedNames.getOrElseUpdate(encName, new NameUsedInClass) + val nameUsed = _usedNames.getOrElseUpdate(encName, new UsedNamesInClass) - nameUsed.defaultNames += symbol.name - nameUsed.scopedNames(symbol.name).add(UseScope.PatMatTarget) + nameUsed.update(symbol.name, UseScope.Default) + nameUsed.update(symbol.name, UseScope.PatMatTarget) } } } From bd2a66587e8fa9bb8a7b00145003ba995f9082fb Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 6 Mar 2018 22:00:42 +0100 Subject: [PATCH 063/101] Resolve dependency source --- .../tools/dotc/sbt/ExtractDependencies.scala | 105 +++++++++--------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index bcd691690ea4..c113428dc1ef 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -55,17 +55,7 @@ class ExtractDependencies extends Phase { val dumpInc = ctx.settings.YdumpSbtInc.value val forceRun = dumpInc || ctx.settings.YforceSbtPhases.value if ((ctx.sbtCallback != null || forceRun) && !unit.isJava) { - val sourceFile = unit.source.file - val responsibleOfImports = firstClassOrModule(unit.tpdTree) match { - case None => - ctx.warning("""|No class, trait or object is defined in the compilation unit. - |The incremental compiler cannot record the dependency information in such case. - |Some errors like unused import referring to a non-existent class might not be reported. - |""".stripMargin, unit.tpdTree.pos) - defn.RootClass - case Some(sym) => sym - } - val extractDeps = new ExtractDependenciesCollector(responsibleOfImports) + val extractDeps = new ExtractDependenciesCollector extractDeps.traverse(unit.tpdTree) if (dumpInc) { @@ -74,6 +64,7 @@ class ExtractDependencies extends Phase { Arrays.sort(names) Arrays.sort(deps) + val sourceFile = unit.source.file val pw = io.File(sourceFile.jpath).changeExtension("inc").toFile.printWriter() try { pw.println(s"// usedNames: ${names.mkString(",")}") @@ -96,23 +87,6 @@ class ExtractDependencies extends Phase { } } - private def firstClassOrModule(tree: tpd.Tree)(implicit ctx: Context): Option[Symbol] = { - import tpd._ - val acc = new TreeAccumulator[Option[Symbol]] { - def apply(x: Option[Symbol], t: Tree)(implicit ctx: Context) = - if (x.isDefined) x - else t match { - case moduleDef: Thicket => - Some(moduleDef.symbol) - case typeDef: TypeDef => - Some(typeDef.symbol) - case other => - foldOver(x, other) - } - } - acc(None, tree) - } - /* * Handles dependency on given symbol by trying to figure out if represents a term * that is coming from either source code (not necessarily compiled in this compilation @@ -209,7 +183,7 @@ private final class UsedNamesInClass { * specially, see the subsection "Dependencies introduced by member reference and * inheritance" in the "Name hashing algorithm" section. */ -private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implicit val ctx: Context) extends tpd.TreeTraverser { thisTreeTraverser => +private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeTraverser => import tpd._ import ExtractDependencies._ @@ -225,7 +199,50 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic */ def dependencies: Set[ClassDependency] = _dependencies - private def addUsedName(enclosingSym: Symbol, name: Name) = { + /** Top level import dependencies are registered as coming from a first top level + * class/trait/object declared in the compilation unit. If none exists, issue warning. + */ + private[this] var _responsibleForImports: Symbol = _ + private def responsibleForImports(implicit ctx: Context) = { + def firstClassOrModule(tree: Tree) = { + val acc = new TreeAccumulator[Symbol] { + def apply(x: Symbol, t: Tree)(implicit ctx: Context) = + t match { + case typeDef: TypeDef => + typeDef.symbol + case other => + foldOver(x, other) + } + } + acc(NoSymbol, tree) + } + + if (_responsibleForImports == null) { + val tree = ctx.compilationUnit.tpdTree + _responsibleForImports = firstClassOrModule(tree) + if (_responsibleForImports == NoSymbol) + ctx.warning("""|No class, trait or object is defined in the compilation unit. + |The incremental compiler cannot record the dependency information in such case. + |Some errors like unused import referring to a non-existent class might not be reported. + |""".stripMargin, tree.pos) + } + _responsibleForImports + } + + /** + * Resolves dependency source (that is, the closest non-local enclosing + * class from a given `currentOwner` set by the `Traverser`). + * + * TODO: cache and/or optimise? + */ + private def resolveDependencySource(implicit ctx: Context): Symbol = { + def isNonLocalClass(sym: Symbol) = sym.isClass && !isLocal(sym) + //val source = ctx.owner.ownersIterator.find(isNonLocalClass).get // Zinc + val source = currentClass + if (source.isEffectiveRoot) responsibleForImports else source + } + + private def addUsedName(enclosingSym: Symbol, name: Name)(implicit ctx: Context) = { val enclosingName = if (enclosingSym == defn.RootClass) classNameAsString(responsibleForImports) else classNameAsString(enclosingSym) @@ -236,40 +253,26 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { val tlClass = sym.topLevelClass + val from = resolveDependencySource if (tlClass.ne(NoSymbol)) { - if (currentClass == defn.RootClass) { - _dependencies += ClassDependency(responsibleForImports, tlClass, DependencyByMemberRef) - } else { - // Some synthetic type aliases like AnyRef do not belong to any class - _dependencies += ClassDependency(currentClass, tlClass, DependencyByMemberRef) - } + _dependencies += ClassDependency(from, tlClass, DependencyByMemberRef) } - addUsedName(nonLocalEnclosingClass(ctx.owner), sym.name.stripModuleClassSuffix) - } - - private def nonLocalEnclosingClass(sym: Symbol)(implicit ctx: Context): Symbol = - sym.enclosingClass match { - case NoSymbol => NoSymbol - case csym => - if (isLocal(csym)) - nonLocalEnclosingClass(csym.owner) - else - csym + addUsedName(from, sym.name.stripModuleClassSuffix) } - private def ignoreDependency(sym: Symbol) = + private def ignoreDependency(sym: Symbol)(implicit ctx: Context) = sym.eq(NoSymbol) || sym.isEffectiveRoot || sym.isAnonymousFunction || sym.isAnonymousClass private def addInheritanceDependency(parent: Symbol)(implicit ctx: Context): Unit = - _dependencies += ClassDependency(currentClass, parent.topLevelClass, DependencyByInheritance) + _dependencies += ClassDependency(resolveDependencySource, parent.topLevelClass, DependencyByInheritance) private class PatMatDependencyTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) { override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val encName = nonLocalEnclosingClass(ctx.owner).fullName.stripModuleClassSuffix.toString + val encName = classNameAsString(resolveDependencySource) val nameUsed = _usedNames.getOrElseUpdate(encName, new UsedNamesInClass) nameUsed.update(symbol.name, UseScope.Default) @@ -299,7 +302,7 @@ private class ExtractDependenciesCollector(responsibleForImports: Symbol)(implic case Thicket(Ident(name) :: Ident(rename) :: Nil) => addImported(name) if (rename ne nme.WILDCARD) { - addUsedName(nonLocalEnclosingClass(ctx.owner), rename) + addUsedName(resolveDependencySource, rename) } case _ => } From 6b9aa1f55f0f4ac7bfebefe71ac0056b7c085444 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 14:31:21 +0100 Subject: [PATCH 064/101] Rework type traverser --- .../tools/dotc/sbt/ExtractDependencies.scala | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index c113428dc1ef..bd3105f31127 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -242,12 +242,12 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT if (source.isEffectiveRoot) responsibleForImports else source } - private def addUsedName(enclosingSym: Symbol, name: Name)(implicit ctx: Context) = { + private def addUsedName(enclosingSym: Symbol, name: Name, scope: UseScope)(implicit ctx: Context) = { val enclosingName = if (enclosingSym == defn.RootClass) classNameAsString(responsibleForImports) else classNameAsString(enclosingSym) val nameUsed = _usedNames.getOrElseUpdate(enclosingName, new UsedNamesInClass) - nameUsed.update(name, UseScope.Default) + nameUsed.update(name, scope) } private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = @@ -257,7 +257,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT if (tlClass.ne(NoSymbol)) { _dependencies += ClassDependency(from, tlClass, DependencyByMemberRef) } - addUsedName(from, sym.name.stripModuleClassSuffix) + addUsedName(from, sym.name.stripModuleClassSuffix, UseScope.Default) } private def ignoreDependency(sym: Symbol)(implicit ctx: Context) = @@ -269,26 +269,14 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def addInheritanceDependency(parent: Symbol)(implicit ctx: Context): Unit = _dependencies += ClassDependency(resolveDependencySource, parent.topLevelClass, DependencyByInheritance) - private class PatMatDependencyTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) { - override protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = { - if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val encName = classNameAsString(resolveDependencySource) - val nameUsed = _usedNames.getOrElseUpdate(encName, new UsedNamesInClass) - - nameUsed.update(symbol.name, UseScope.Default) - nameUsed.update(symbol.name, UseScope.PatMatTarget) - } - } - } - /** Traverse the tree of a source file and record the dependencies which * can be retrieved using `topLevelDependencies`, `topLevelInheritanceDependencies`, * and `usedNames` */ override def traverse(tree: Tree)(implicit ctx: Context): Unit = { tree match { - case v @ ValDef(_, tpt, _) if v.symbol.is(Case) && v.symbol.is(Synthetic) => - new PatMatDependencyTraverser(ctx).traverse(tpt.tpe) + case Match(selector, _) => + addPatMatDependency(selector.tpe) case Import(expr, selectors) => def lookupImported(name: Name) = expr.tpe.member(name).symbol def addImported(name: Name) = { @@ -302,7 +290,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT case Thicket(Ident(name) :: Ident(rename) :: Nil) => addImported(name) if (rename ne nme.WILDCARD) { - addUsedName(resolveDependencySource, rename) + addUsedName(resolveDependencySource, rename, UseScope.Default) } case _ => } @@ -311,10 +299,10 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT // record it as a dependency traverse(call) case t: TypeTree => - new usedTypeTraverser(ctx).traverse(t.tpe) + addTypeDependency(t.tpe) case ref: RefTree => addDependency(ref.symbol) - new usedTypeTraverser(ctx).traverse(ref.tpe) + addTypeDependency(ref.tpe) case t @ Template(_, parents, _, _) => t.parents.foreach(p => addInheritanceDependency(p.tpe.classSymbol)) case _ => @@ -355,7 +343,9 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT * The tests in sbt `types-in-used-names-a`, `types-in-used-names-b`, * `as-seen-from-a` and `as-seen-from-b` rely on this. */ - private class ExtractTypesCollector(ctx0: Context) extends TypeTraverser()(ctx0) { + private abstract class TypeDependencyTraverser(implicit ctx: Context) extends TypeTraverser()(ctx) { + protected def addDependency(symbol: Symbol): Unit + val seen = new mutable.HashSet[Type] def traverse(tp: Type): Unit = if (!seen.contains(tp)) { seen += tp @@ -378,10 +368,25 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT traverseChildren(tp) } } + } - protected def addDependency(symbol: Symbol)(implicit ctx: Context): Unit = - thisTreeTraverser.addDependency(symbol) + def addTypeDependency(tpe: Type)(implicit ctx: Context) = { + val traverser = new TypeDependencyTraverser { + def addDependency(symbol: Symbol) = thisTreeTraverser.addDependency(symbol) + } + traverser.traverse(tpe) } - private class usedTypeTraverser(ctx0: Context) extends ExtractTypesCollector(ctx0) + def addPatMatDependency(tpe: Type)(implicit ctx: Context) = { + val traverser = new TypeDependencyTraverser { + def addDependency(symbol: Symbol) = + if (!ignoreDependency(symbol) && symbol.is(Sealed)) { + val enclosingSym = resolveDependencySource + val usedName = symbol.name.stripModuleClassSuffix + addUsedName(enclosingSym, usedName, UseScope.Default) + addUsedName(enclosingSym, usedName, UseScope.PatMatTarget) + } + } + traverser.traverse(tpe) + } } From 01d35ff4cf4f809d6a6da0946a9896a3f77c6219 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 14:45:17 +0100 Subject: [PATCH 065/101] Rework inheritance dependencies --- .../tools/dotc/sbt/ExtractDependencies.scala | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index bd3105f31127..eafee161d104 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -266,8 +266,16 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT sym.isAnonymousFunction || sym.isAnonymousClass - private def addInheritanceDependency(parent: Symbol)(implicit ctx: Context): Unit = - _dependencies += ClassDependency(resolveDependencySource, parent.topLevelClass, DependencyByInheritance) + private def addInheritanceDependency(tree: Template)(implicit ctx: Context): Unit = + if (tree.parents.nonEmpty) { + val depContext = + if (isLocal(tree.symbol.owner)) LocalDependencyByInheritance + else DependencyByInheritance + val from = resolveDependencySource + tree.parents.foreach { parent => + _dependencies += ClassDependency(from, parent.tpe.classSymbol.topLevelClass, depContext) + } + } /** Traverse the tree of a source file and record the dependencies which * can be retrieved using `topLevelDependencies`, `topLevelInheritanceDependencies`, @@ -303,8 +311,8 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT case ref: RefTree => addDependency(ref.symbol) addTypeDependency(ref.tpe) - case t @ Template(_, parents, _, _) => - t.parents.foreach(p => addInheritanceDependency(p.tpe.classSymbol)) + case t: Template => + addInheritanceDependency(t) case _ => } traverseChildren(tree) From 2db004794aeafb7dbaf8dd9975a205f19efec0a5 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 14:58:48 +0100 Subject: [PATCH 066/101] Use Symbol instead of String for usedNames cache's key --- .../tools/dotc/sbt/ExtractDependencies.scala | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index eafee161d104..17efa4169d70 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -75,7 +75,7 @@ class ExtractDependencies extends Phase { if (ctx.sbtCallback != null) { extractDeps.usedNames.foreach { case (clazz, usedNames) => - val className = clazz + val className = classNameAsString(clazz) usedNames.names.foreach { case (usedName, scopes) => ctx.sbtCallback.usedName(className, usedName.toString, scopes) @@ -187,13 +187,13 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT import tpd._ import ExtractDependencies._ - private[this] val _usedNames = new mutable.HashMap[String, UsedNamesInClass] + private[this] val _usedNames = new mutable.HashMap[Symbol, UsedNamesInClass] private[this] val _dependencies = new mutable.HashSet[ClassDependency] /** The names used in this class, this does not include names which are only * defined and not referenced. */ - def usedNames: collection.Map[String, UsedNamesInClass] = _usedNames + def usedNames: collection.Map[Symbol, UsedNamesInClass] = _usedNames /** The set of class dependencies from this compilation unit. */ @@ -242,12 +242,17 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT if (source.isEffectiveRoot) responsibleForImports else source } - private def addUsedName(enclosingSym: Symbol, name: Name, scope: UseScope)(implicit ctx: Context) = { - val enclosingName = - if (enclosingSym == defn.RootClass) classNameAsString(responsibleForImports) - else classNameAsString(enclosingSym) - val nameUsed = _usedNames.getOrElseUpdate(enclosingName, new UsedNamesInClass) - nameUsed.update(name, scope) + private def addUsedName(fromClass: Symbol, name: Name, scope: UseScope): Unit = { + val usedName = _usedNames.getOrElseUpdate(fromClass, new UsedNamesInClass) + usedName.update(name, scope) + } + + private def addUsedName(name: Name, scope: UseScope)(implicit ctx: Context): Unit = { + val fromClass = resolveDependencySource + if (fromClass ne NoSymbol) { + assert(fromClass.isClass) + addUsedName(fromClass, name, scope) + } } private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = @@ -298,7 +303,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT case Thicket(Ident(name) :: Ident(rename) :: Nil) => addImported(name) if (rename ne nme.WILDCARD) { - addUsedName(resolveDependencySource, rename, UseScope.Default) + addUsedName(rename, UseScope.Default) } case _ => } @@ -389,10 +394,9 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT val traverser = new TypeDependencyTraverser { def addDependency(symbol: Symbol) = if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val enclosingSym = resolveDependencySource val usedName = symbol.name.stripModuleClassSuffix - addUsedName(enclosingSym, usedName, UseScope.Default) - addUsedName(enclosingSym, usedName, UseScope.PatMatTarget) + addUsedName(usedName, UseScope.Default) + addUsedName(usedName, UseScope.PatMatTarget) } } traverser.traverse(tpe) From 26241d0f4190c5d7c1bf1e61d14da87ef4b6be4c Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 17:18:52 +0100 Subject: [PATCH 067/101] Cleanup --- .../tools/dotc/sbt/ExtractDependencies.scala | 81 +++++++++++-------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 17efa4169d70..8d24e2e8b3a4 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -54,26 +54,33 @@ class ExtractDependencies extends Phase { val unit = ctx.compilationUnit val dumpInc = ctx.settings.YdumpSbtInc.value val forceRun = dumpInc || ctx.settings.YforceSbtPhases.value - if ((ctx.sbtCallback != null || forceRun) && !unit.isJava) { - val extractDeps = new ExtractDependenciesCollector - extractDeps.traverse(unit.tpdTree) + val shouldRun = !unit.isJava && (ctx.sbtCallback != null || forceRun) + + if (shouldRun) { + val collector = new ExtractDependenciesCollector + collector.traverse(unit.tpdTree) if (dumpInc) { - val names = extractDeps.usedNames.map { case (clazz, names) => s"$clazz: $names" }.toArray[Object] - val deps = extractDeps.dependencies.map(_.toString).toArray[Object] - Arrays.sort(names) + val deps = collector.dependencies.map(_.toString).toArray[Object] + val names = collector.usedNames.map { case (clazz, names) => s"$clazz: $names" }.toArray[Object] Arrays.sort(deps) + Arrays.sort(names) - val sourceFile = unit.source.file - val pw = io.File(sourceFile.jpath).changeExtension("inc").toFile.printWriter() + val pw = io.File(unit.source.file.jpath).changeExtension("inc").toFile.printWriter() + // val pw = Console.out try { - pw.println(s"// usedNames: ${names.mkString(",")}") - pw.println(s"// Dependencies: ${deps.mkString(",")}") + pw.println("Used Names:") + pw.println("===========") + names.foreach(pw.println) + pw.println() + pw.println("Dependencies:") + pw.println("=============") + deps.foreach(pw.println) } finally pw.close() } if (ctx.sbtCallback != null) { - extractDeps.usedNames.foreach { + collector.usedNames.foreach { case (clazz, usedNames) => val className = classNameAsString(clazz) usedNames.names.foreach { @@ -82,7 +89,7 @@ class ExtractDependencies extends Phase { } } - extractDeps.dependencies.foreach(recordDependency) + collector.dependencies.foreach(recordDependency) } } } @@ -146,6 +153,10 @@ object ExtractDependencies { def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = sym.ownersIterator.exists(_.isTerm) + + /** Return the enclosing class or the module class if it's a module. */ + def enclOrModuleClass(dep: Symbol)(implicit ctx: Context): Symbol = + if (dep.is(ModuleVal)) dep.moduleClass else dep.enclosingClass } private case class ClassDependency(from: Symbol, to: Symbol, context: DependencyContext) @@ -255,22 +266,22 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT } } - private def addDependency(sym: Symbol)(implicit ctx: Context): Unit = + private def addMemberRefDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { - val tlClass = sym.topLevelClass - val from = resolveDependencySource - if (tlClass.ne(NoSymbol)) { - _dependencies += ClassDependency(from, tlClass, DependencyByMemberRef) + val depClass = sym.topLevelClass // FIXME should be enclOrModuleClass(sym) in Zinc > 1.0 + // assert(depClass.isClass, s"$depClass, $sym, ${sym.isClass}") + + if (depClass ne NoSymbol) { + assert(depClass.isClass) + val fromClass = resolveDependencySource + if (fromClass ne NoSymbol) { + assert(fromClass.isClass) + _dependencies += ClassDependency(fromClass, depClass, DependencyByMemberRef) + addUsedName(fromClass, sym.name.stripModuleClassSuffix, UseScope.Default) + } } - addUsedName(from, sym.name.stripModuleClassSuffix, UseScope.Default) } - private def ignoreDependency(sym: Symbol)(implicit ctx: Context) = - sym.eq(NoSymbol) || - sym.isEffectiveRoot || - sym.isAnonymousFunction || - sym.isAnonymousClass - private def addInheritanceDependency(tree: Template)(implicit ctx: Context): Unit = if (tree.parents.nonEmpty) { val depContext = @@ -278,13 +289,18 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT else DependencyByInheritance val from = resolveDependencySource tree.parents.foreach { parent => - _dependencies += ClassDependency(from, parent.tpe.classSymbol.topLevelClass, depContext) + _dependencies += ClassDependency(from, parent.tpe.classSymbol, depContext) } } - /** Traverse the tree of a source file and record the dependencies which - * can be retrieved using `topLevelDependencies`, `topLevelInheritanceDependencies`, - * and `usedNames` + private def ignoreDependency(sym: Symbol)(implicit ctx: Context) = + sym.eq(NoSymbol) || + sym.isEffectiveRoot || + sym.isAnonymousFunction || + sym.isAnonymousClass + + /** Traverse the tree of a source file and record the dependencies and used names which + * can be retrieved using `dependencies` and`usedNames`. */ override def traverse(tree: Tree)(implicit ctx: Context): Unit = { tree match { @@ -294,8 +310,8 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT def lookupImported(name: Name) = expr.tpe.member(name).symbol def addImported(name: Name) = { // importing a name means importing both a term and a type (if they exist) - addDependency(lookupImported(name.toTermName)) - addDependency(lookupImported(name.toTypeName)) + addMemberRefDependency(lookupImported(name.toTermName)) + addMemberRefDependency(lookupImported(name.toTypeName)) } selectors foreach { case Ident(name) => @@ -314,7 +330,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT case t: TypeTree => addTypeDependency(t.tpe) case ref: RefTree => - addDependency(ref.symbol) + addMemberRefDependency(ref.symbol) addTypeDependency(ref.tpe) case t: Template => addInheritanceDependency(t) @@ -385,7 +401,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT def addTypeDependency(tpe: Type)(implicit ctx: Context) = { val traverser = new TypeDependencyTraverser { - def addDependency(symbol: Symbol) = thisTreeTraverser.addDependency(symbol) + def addDependency(symbol: Symbol) = addMemberRefDependency(symbol) } traverser.traverse(tpe) } @@ -395,7 +411,6 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT def addDependency(symbol: Symbol) = if (!ignoreDependency(symbol) && symbol.is(Sealed)) { val usedName = symbol.name.stripModuleClassSuffix - addUsedName(usedName, UseScope.Default) addUsedName(usedName, UseScope.PatMatTarget) } } From d56e34f58e5a9b2874d019d1c44c08636ac64e37 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 17:20:48 +0100 Subject: [PATCH 068/101] Record finer grained dependencies Use enclosing class or module class instead of top level class --- compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 8d24e2e8b3a4..a037e2c2dcb8 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -268,7 +268,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def addMemberRefDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { - val depClass = sym.topLevelClass // FIXME should be enclOrModuleClass(sym) in Zinc > 1.0 + val depClass = enclOrModuleClass(sym) // assert(depClass.isClass, s"$depClass, $sym, ${sym.isClass}") if (depClass ne NoSymbol) { From 5193632d95513f2a595db05089000f11679eccd0 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 17:44:03 +0100 Subject: [PATCH 069/101] Don't record dependency on package --- compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index a037e2c2dcb8..a0cc53a9098a 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -295,9 +295,9 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def ignoreDependency(sym: Symbol)(implicit ctx: Context) = sym.eq(NoSymbol) || - sym.isEffectiveRoot || sym.isAnonymousFunction || - sym.isAnonymousClass + sym.isAnonymousClass || + sym.is(PackageClass) /** Traverse the tree of a source file and record the dependencies and used names which * can be retrieved using `dependencies` and`usedNames`. From 452356bfee2a08754787cc22ed974a2c90a45c40 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 17:58:35 +0100 Subject: [PATCH 070/101] Use non local enclosing class as dependency source --- compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index a0cc53a9098a..3f95faf15d48 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -248,9 +248,8 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT */ private def resolveDependencySource(implicit ctx: Context): Symbol = { def isNonLocalClass(sym: Symbol) = sym.isClass && !isLocal(sym) - //val source = ctx.owner.ownersIterator.find(isNonLocalClass).get // Zinc - val source = currentClass - if (source.isEffectiveRoot) responsibleForImports else source + val source = ctx.owner.ownersIterator.find(isNonLocalClass).get + if (source.is(PackageClass)) responsibleForImports else source } private def addUsedName(fromClass: Symbol, name: Name, scope: UseScope): Unit = { From cdfa4333427fa7db70dcdf76a23bd54e50d980b1 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 18:10:13 +0100 Subject: [PATCH 071/101] Optimise resolveDependencySource --- .../tools/dotc/sbt/ExtractDependencies.scala | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 3f95faf15d48..6d26e6cab09a 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -240,16 +240,32 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT _responsibleForImports } + private[this] var lastOwner: Symbol = _ + private[this] var lastDepSource: Symbol = _ + /** * Resolves dependency source (that is, the closest non-local enclosing - * class from a given `currentOwner` set by the `Traverser`). - * - * TODO: cache and/or optimise? + * class from a given `ctx.owner` */ private def resolveDependencySource(implicit ctx: Context): Symbol = { - def isNonLocalClass(sym: Symbol) = sym.isClass && !isLocal(sym) - val source = ctx.owner.ownersIterator.find(isNonLocalClass).get - if (source.is(PackageClass)) responsibleForImports else source + def resolveDepSource: Symbol = { + val owners = ctx.owner.ownersIterator + while (owners.hasNext) { + val source = owners.next() + def isLocal = !owners.exists(_.isTerm) // side-effectful: consume iterator elements + if (source.isClass && isLocal) return source + else if (source.is(PackageClass)) return responsibleForImports + } + assert(false, "unreachable") + NoSymbol + } + + if (lastOwner != ctx.owner) { + lastOwner = ctx.owner + lastDepSource = resolveDepSource + } + + lastDepSource } private def addUsedName(fromClass: Symbol, name: Name, scope: UseScope): Unit = { From 8e3bad9fb5c112b56cb9e7c95f5cafbf705f1a1b Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 7 Mar 2018 18:45:54 +0100 Subject: [PATCH 072/101] Address review comments --- .../src/dotty/tools/dotc/config/JavaPlatform.scala | 9 +-------- compiler/src/dotty/tools/dotc/config/Platform.scala | 12 ++++++++++++ compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 13 +------------ .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 1 + .../tools/dotc/transform/CollectEntryPoints.scala | 7 +++---- 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala index 03eb441852f0..08a67ab3d1f0 100644 --- a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala +++ b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala @@ -21,19 +21,12 @@ class JavaPlatform extends Platform { } // The given symbol is a method with the right name and signature to be a runnable java program. - def isJavaMainMethod(sym: SymDenotation)(implicit ctx: Context) = + def isMainMethod(sym: SymDenotation)(implicit ctx: Context) = (sym.name == nme.main) && (sym.info match { case MethodTpe(_, defn.ArrayOf(el) :: Nil, restpe) => el =:= defn.StringType && (restpe isRef defn.UnitClass) case _ => false }) - // The given class has a main method. - def hasJavaMainMethod(sym: Symbol)(implicit ctx: Context): Boolean = - (sym.info member nme.main).hasAltWith { - case x: SymDenotation => isJavaMainMethod(x) - case _ => false - } - /** Update classpath with a substituted subentry */ def updateClassPath(subst: Map[ClassPath, ClassPath]): Unit = currentClassPath.get match { case AggregateClassPath(entries) => diff --git a/compiler/src/dotty/tools/dotc/config/Platform.scala b/compiler/src/dotty/tools/dotc/config/Platform.scala index 062d9002d186..71e0d9cd107c 100644 --- a/compiler/src/dotty/tools/dotc/config/Platform.scala +++ b/compiler/src/dotty/tools/dotc/config/Platform.scala @@ -10,6 +10,8 @@ package config import io.{ClassPath, AbstractFile} import core.Contexts._, core.Symbols._ import core.SymbolLoader +import core.SymDenotations.SymDenotation +import core.StdNames.nme /** The platform dependent pieces of Global. */ @@ -35,5 +37,15 @@ abstract class Platform { /** Create a new class loader to load class file `bin` */ def newClassLoader(bin: AbstractFile)(implicit ctx: Context): SymbolLoader + + /** The given symbol is a method with the right name and signature to be a runnable program. */ + def isMainMethod(sym: SymDenotation)(implicit ctx: Context): Boolean + + /** The given class has a main method. */ + final def hasMainMethod(sym: Symbol)(implicit ctx: Context): Boolean = + sym.info.member(nme.main).hasAltWith { + case x: SymDenotation => isMainMethod(x) + case _ => false + } } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index e4f4e109debd..b114520f59d9 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -228,20 +228,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder name, acc, modifiers, anns, defType, api.SafeLazy.strict(selfType), api.SafeLazy.strict(structure), Constants.emptyStringArray, childrenOfSealedClass, topLevel, tparams) - // if (name.toString.contains("DottyPredef")) { - // println("sym: " + sym) - // println("name: " + name) - // ctx.atPhase(ctx.flattenPhase.next) { implicit ctx => - // println("flatten: " + sym.fullName.toString) - // println("flattenm: " + sym.fullName.mangledString) - // } - // println("flattenx: " + toDenot(sym.binaryName.toString) - // } - allNonLocalClassesInSrc += cl - val javaPlatform = ctx.platform.asInstanceOf[JavaPlatform] - if (sym.isStatic && defType == DefinitionType.Module && javaPlatform.hasJavaMainMethod(sym)) { + if (sym.isStatic && defType == DefinitionType.Module && ctx.platform.hasMainMethod(sym)) { _mainClasses += name } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 6d26e6cab09a..da20e3ad0967 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -161,6 +161,7 @@ object ExtractDependencies { private case class ClassDependency(from: Symbol, to: Symbol, context: DependencyContext) +/** An object that maintain the set of used names from within a class */ private final class UsedNamesInClass { private val _names = new mutable.HashMap[Name, EnumSet[UseScope]] def names: collection.Map[Name, EnumSet[UseScope]] = _names diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala index 071b41444bfc..4b3ad0eb8255 100644 --- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala @@ -70,8 +70,7 @@ class CollectEntryPoints extends MiniPhase { } def precise(implicit ctx: Context) = { val companion = sym.companionClass //sym.asClass.linkedClassOfClass - val javaPlatform = ctx.platform.asInstanceOf[JavaPlatform] - if (javaPlatform.hasJavaMainMethod(companion)) + if (ctx.platform.hasMainMethod(companion)) failNoForwarder("companion contains its own main method") else if (companion.exists && companion.info.member(nme.main).exists) // this is only because forwarders aren't smart enough yet @@ -80,7 +79,7 @@ class CollectEntryPoints extends MiniPhase { failNoForwarder("companion is a trait") // Now either succeed, or issue some additional warnings for things which look like // attempts to be java main methods. - else (possibles exists (x => javaPlatform.isJavaMainMethod(x.symbol))) || { + else (possibles exists (x => ctx.platform.isMainMethod(x.symbol))) || { possibles exists { m => m.symbol.info match { @@ -90,7 +89,7 @@ class CollectEntryPoints extends MiniPhase { if (t.resultType :: t.paramInfos exists (_.typeSymbol.isAbstractType)) fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos) else - javaPlatform.isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos) + ctx.platform.isMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos) case tp => fail(s"don't know what this is: $tp", m.symbol.pos) } From 0c471e50c006da44102ca780e7e92504df499c46 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 8 Mar 2018 11:27:38 +0100 Subject: [PATCH 073/101] Fix resolveDependencySource --- compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index da20e3ad0967..0ba982e026af 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -255,7 +255,6 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT val source = owners.next() def isLocal = !owners.exists(_.isTerm) // side-effectful: consume iterator elements if (source.isClass && isLocal) return source - else if (source.is(PackageClass)) return responsibleForImports } assert(false, "unreachable") NoSymbol @@ -263,7 +262,8 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT if (lastOwner != ctx.owner) { lastOwner = ctx.owner - lastDepSource = resolveDepSource + val source = resolveDepSource + lastDepSource = if (source.is(PackageClass)) responsibleForImports else source } lastDepSource From ac88395812b9ab447364f2031891ccb02641c42c Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 8 Mar 2018 17:28:01 +0100 Subject: [PATCH 074/101] Build cleanup --- project/Build.scala | 55 ++++++++++++++++++------------------ project/Dependencies.scala | 15 ++-------- project/build.properties | 2 +- project/inject-sbt-dotty.sbt | 2 +- 4 files changed, 32 insertions(+), 42 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index dcd082907933..549566af241a 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -249,22 +249,22 @@ object Build { // Compile using the non-bootstrapped and non-published dotty managedScalaInstance := false, scalaInstance := { - val updateResult = update.value - val (libraryJar, compilerJar) = - if (bootstrapFromPublishedJars.value) { - val jars = updateResult.select( + val updateReport = update.value + var libraryJar = packageBin.in(`dotty-library`, Compile).value + var compilerJar = packageBin.in(`dotty-compiler`, Compile).value + + if (bootstrapFromPublishedJars.value) { + val jars = updateReport.select( configuration = configurationFilter(Configurations.ScalaTool.name), module = moduleFilter(), artifact = artifactFilter(extension = "jar") ) - (jars.find(_.getName.startsWith("dotty-library_2.12")).get, - jars.find(_.getName.startsWith("dotty-compiler_2.12")).get) - } else - ((packageBin in (`dotty-library`, Compile)).value: @sbtUnchecked, - (packageBin in (`dotty-compiler`, Compile)).value: @sbtUnchecked) + libraryJar = jars.find(_.getName.startsWith("dotty-library_2.12")).get + compilerJar = jars.find(_.getName.startsWith("dotty-compiler_2.12")).get + } // All compiler dependencies except the library - val otherDependencies = (dependencyClasspath in (`dotty-compiler`, Compile)).value + val otherDependencies = dependencyClasspath.in(`dotty-compiler`, Compile).value .filterNot(_.get(artifact.key).exists(_.name == "dotty-library")) .map(_.data) @@ -362,8 +362,8 @@ object Build { val dottyInterfaces =jars("dotty-interfaces") val otherDeps = (dependencyClasspath in Compile).value.map(_.data).mkString(":") val sources = - (unmanagedSources in (Compile, compile)).value ++ - (unmanagedSources in (`dotty-compiler`, Compile)).value + unmanagedSources.in(Compile, compile).value ++ + unmanagedSources.in(`dotty-compiler`, Compile).value val args = Seq( "-siteroot", "docs", "-project", "Dotty", @@ -488,7 +488,7 @@ object Build { "org.scala-lang.modules" % "scala-asm" % "6.0.0-scala-1", // used by the backend ("org.scala-lang.modules" %% "scala-xml" % "1.0.6").withDottyCompat(scalaVersion.value), "org.scala-lang" % "scala-library" % scalacVersion % "test", - Dependencies.`compiler-interface`, + Dependencies.compilerInterface(sbtVersion.value), ), // For convenience, change the baseDirectory when running the compiler @@ -675,19 +675,19 @@ object Build { // packageAll packages all and then returns a map with the abs location packageAll := { Map( - "dotty-interfaces" -> (packageBin in (`dotty-interfaces`, Compile)).value, - "dotty-compiler" -> (packageBin in Compile).value, - "dotty-library" -> (packageBin in (`dotty-library`, Compile)).value, - "dotty-compiler-test" -> (packageBin in Test).value + "dotty-interfaces" -> packageBin.in(`dotty-interfaces`, Compile).value, + "dotty-compiler" -> packageBin.in(Compile).value, + "dotty-library" -> packageBin.in(`dotty-library`, Compile).value, + "dotty-compiler-test" -> packageBin.in(Test).value ).mapValues(_.getAbsolutePath) } ) lazy val bootstrapedDottyCompilerSettings = commonDottyCompilerSettings ++ Seq( packageAll := { - (packageAll in `dotty-compiler`).value ++ Seq( - ("dotty-compiler" -> (packageBin in Compile).value.getAbsolutePath), - ("dotty-library" -> (packageBin in (`dotty-library-bootstrapped`, Compile)).value.getAbsolutePath) + packageAll.in(`dotty-compiler`).value ++ Seq( + "dotty-compiler" -> packageBin.in(Compile).value.getAbsolutePath, + "dotty-library" -> packageBin.in(`dotty-library-bootstrapped`, Compile).value.getAbsolutePath ) } ) @@ -738,8 +738,8 @@ object Build { description := "sbt compiler bridge for Dotty", resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api libraryDependencies ++= Seq( - Dependencies.`compiler-interface`, - (Dependencies.`zinc-apiinfo` % Test).withDottyCompat(scalaVersion.value), + Dependencies.compilerInterface(sbtVersion.value), + (Dependencies.zincApiinfo(sbtVersion.value) % Test).withDottyCompat(scalaVersion.value), ("org.specs2" %% "specs2-core" % "3.9.1" % Test).withDottyCompat(scalaVersion.value), ("org.specs2" %% "specs2-junit" % "3.9.1" % Test).withDottyCompat(scalaVersion.value) ), @@ -836,7 +836,7 @@ object Build { // Keep in sync with inject-sbt-dotty.sbt libraryDependencies ++= Seq( Dependencies.`jackson-databind`, - Dependencies.`compiler-interface` + Dependencies.compilerInterface(sbtVersion.value) ), unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", @@ -871,12 +871,13 @@ object Build { includeFilter in unmanagedSources := NothingFilter | "*.ts" | "**.json", watchSources in Global ++= (unmanagedSources in Compile).value, compile in Compile := { - val coursier = baseDirectory.value / "out/coursier" - val packageJson = baseDirectory.value / "package.json" + val workingDir = baseDirectory.value + val coursier = workingDir / "out/coursier" + val packageJson = workingDir / "package.json" if (!coursier.exists || packageJson.lastModified > coursier.lastModified) - runProcess(Seq("npm", "run", "update-all"), wait = true, directory = baseDirectory.value: @sbtUnchecked) + runProcess(Seq("npm", "run", "update-all"), wait = true, directory = workingDir) val tsc = baseDirectory.value / "node_modules" / ".bin" / "tsc" - runProcess(Seq(tsc.getAbsolutePath, "--pretty", "--project", baseDirectory.value.getAbsolutePath), wait = true) + runProcess(Seq(tsc.getAbsolutePath, "--pretty", "--project", workingDir.getAbsolutePath), wait = true) // Currently, vscode-dotty depends on daltonjorge.scala for syntax highlighting, // this is not automatically installed when starting the extension in development mode diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 2d63ab9cd915..f2b503cdbb99 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -13,17 +13,6 @@ object Dependencies { val `jackson-dataformat-yaml` = "com.fasterxml.jackson.dataformat" % "jackson-dataformat-yaml" % jacksonVersion - private def readPropertyFile(file: String): Properties = { - val prop = new Properties() - val input = new FileInputStream(file) - try { - prop.load(input) - prop - } - finally input.close - } - - private val sbtVersion = readPropertyFile("project/build.properties").getProperty("sbt.version") - val `compiler-interface` = "org.scala-sbt" % "compiler-interface" % sbtVersion - val `zinc-apiinfo` = "org.scala-sbt" %% "zinc-apiinfo" % sbtVersion + def compilerInterface(sbtVersion: String) = "org.scala-sbt" % "compiler-interface" % sbtVersion + def zincApiinfo(sbtVersion: String) = "org.scala-sbt" %% "zinc-apiinfo" % sbtVersion } \ No newline at end of file diff --git a/project/build.properties b/project/build.properties index 8b697bbb94f3..31334bbd3df2 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.1.0 +sbt.version=1.1.1 diff --git a/project/inject-sbt-dotty.sbt b/project/inject-sbt-dotty.sbt index d2962d3d901e..a73be671d462 100644 --- a/project/inject-sbt-dotty.sbt +++ b/project/inject-sbt-dotty.sbt @@ -7,7 +7,7 @@ unmanagedSourceDirectories in Compile += baseDirectory.value / "../sbt-dotty/src // Keep in sync with `sbt-dotty` config in Build.scala libraryDependencies ++= Seq( Dependencies.`jackson-databind`, - Dependencies.`compiler-interface` + Dependencies.compilerInterface(sbtVersion.value) ) unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config" From 4b862f8c5c59e747b01478fc21c230d81c79b75d Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 8 Mar 2018 18:09:46 +0100 Subject: [PATCH 075/101] Add new tests from Zinc --- .../anon-class-java-depends-on-scala/JJ.java | 11 +++++ .../build.sbt | 1 + .../changes/S1.scala | 3 ++ .../changes/S2.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../anon-class-java-depends-on-scala/test | 4 ++ .../anon-java-scala-class/A.java | 3 ++ .../anon-java-scala-class/B.java | 3 ++ .../anon-java-scala-class/C.scala | 5 ++ .../anon-java-scala-class/D.scala | 5 ++ .../anon-java-scala-class/changes/A2.java | 6 +++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../anon-java-scala-class/project/plugins.sbt | 1 + .../anon-java-scala-class/test | 16 +++++++ .../changed/Sealed1.scala | 9 ++++ .../changed/Sealed2.scala | 9 ++++ .../incOptions.properties | 1 + .../changedTypeOfChildOfSealed/pending | 10 ++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../src/main/scala/foo/Sealed.scala | 9 ++++ .../src/main/scala/foo/Usage.scala | 8 ++++ .../source-dependencies/check-classes/A.scala | 1 + .../project/DottyInjectedPlugin.scala | 12 +++++ .../check-classes/project/plugins.sbt | 1 + .../source-dependencies/check-classes/test | 2 + .../check-dependencies/A.scala | 1 + .../check-dependencies/B.scala | 1 + .../check-dependencies/C.scala | 1 + .../project/DottyInjectedPlugin.scala | 12 +++++ .../check-dependencies/project/plugins.sbt | 1 + .../check-dependencies/test | 3 ++ .../check-products/A.scala | 1 + .../project/DottyInjectedPlugin.scala | 12 +++++ .../check-products/project/plugins.sbt | 1 + .../source-dependencies/check-products/test | 2 + .../check-recompilations/A.scala | 3 ++ .../check-recompilations/B.scala | 3 ++ .../check-recompilations/C.scala | 3 ++ .../check-recompilations/D.scala | 3 ++ .../check-recompilations/changes/A.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../check-recompilations/project/plugins.sbt | 1 + .../check-recompilations/test | 10 ++++ .../class-based-inheritance/changes/A1.scala | 5 ++ .../class-based-inheritance/changes/A2.scala | 8 ++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../src/main/scala/A.scala | 5 ++ .../src/main/scala/B.scala | 1 + .../src/main/scala/C.scala | 1 + .../class-based-inheritance/test | 21 ++++++++ .../class-based-memberRef/changes/A1.scala | 7 +++ .../incOptions.properties | 1 + .../project/DottyInjectedPlugin.scala | 12 +++++ .../class-based-memberRef/project/plugins.sbt | 1 + .../src/main/scala/A.scala | 7 +++ .../src/main/scala/B.scala | 6 +++ .../class-based-memberRef/test | 11 +++++ .../constructors-unrelated/A.scala | 2 + .../constructors-unrelated/B.scala | 1 + .../constructors-unrelated/changes/A2.scala | 2 + .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../constructors-unrelated/test | 6 +++ .../continuations/Foo.scala | 3 ++ .../continuations/Use.scala | 6 +++ .../continuations/build.sbt | 7 +++ .../continuations/changes/Def1.scala | 5 ++ .../continuations/changes/Def2.scala | 5 ++ .../source-dependencies/continuations/pending | 13 +++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../continuations/project/plugins.sbt | 1 + .../source-dependencies/cross-source/pending | 16 +++++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../cross-source/project/plugins.sbt | 1 + .../cross-source/src/main/scala-2.10/B.scala | 3 ++ .../cross-source/src/main/scala-2.9.3/B.scala | 3 ++ .../cross-source/src/main/scala/A.scala | 3 ++ .../empty-modified-names/T.scala | 3 ++ .../empty-modified-names/changes/T.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../empty-modified-names/project/plugins.sbt | 1 + .../empty-modified-names/test | 3 ++ .../changed/FactoryProvider.scala | 6 +++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../src/main/scala/foo/FactoryProvider.scala | 6 +++ .../src/main/scala/foo/Lib.scala | 36 ++++++++++++++ .../src/main/scala/foo/Usage.scala | 7 +++ .../expanded-type-projection/test | 5 ++ .../changes/A1.scala | 3 ++ .../changes/A2.scala | 5 ++ .../changes/B.scala | 2 + .../changes/C.scala | 3 ++ .../changes/M.scala | 6 +++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../implicit-search-higher-kinded/test | 14 ++++++ .../inner-class-java-depends-on-scala/JJ.java | 12 +++++ .../build.sbt | 1 + .../changes/S1.scala | 3 ++ .../changes/S2.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../inner-class-java-depends-on-scala/test | 4 ++ .../java-anonymous/Outer.java | 9 ++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../java-anonymous/project/plugins.sbt | 1 + .../source-dependencies/java-anonymous/test | 2 + .../java-enum/changes/SomeEnum.java | 18 +++++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../java-enum/project/plugins.sbt | 1 + .../source-dependencies/java-enum/test | 2 + .../source-dependencies/java-inner/A.java | 5 ++ .../source-dependencies/java-inner/C.java | 5 ++ .../source-dependencies/java-inner/D.java | 2 + .../project/DottyInjectedPlugin.scala | 12 +++++ .../java-inner/project/plugins.sbt | 1 + .../source-dependencies/java-inner/test | 6 +++ .../java-lambda-typeparams/Example.java | 26 ++++++++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../java-lambda-typeparams/test | 1 + .../JFunction2$mcJDD$sp.java | 5 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../java-name-with-dollars/test | 2 + .../local-class-inheritance-from-java/A.java | 3 ++ .../local-class-inheritance-from-java/B.java | 3 ++ .../local-class-inheritance-from-java/C.scala | 5 ++ .../local-class-inheritance-from-java/D.scala | 5 ++ .../changes/A2.java | 6 +++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../local-class-inheritance-from-java/test | 16 +++++++ .../local-class-inheritance/A.scala | 1 + .../local-class-inheritance/B.scala | 1 + .../local-class-inheritance/C.scala | 5 ++ .../local-class-inheritance/D.scala | 5 ++ .../local-class-inheritance/changes/A2.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../local-class-inheritance/test | 17 +++++++ .../malformed-class-name-with-dollar/B.java | 5 ++ .../changes/A.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../malformed-class-name-with-dollar/test | 3 ++ .../malformed-class-name/Boo.scala | 48 +++++++++++++++++++ .../malformed-class-name/changes/BooUser.java | 32 +++++++++++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../malformed-class-name/project/plugins.sbt | 1 + .../malformed-class-name/test | 3 ++ .../naha-synthetic/A.scala | 1 + .../naha-synthetic/B.scala | 1 + .../naha-synthetic/build.sbt | 5 ++ .../naha-synthetic/changes/A.scala | 1 + .../project/DottyInjectedPlugin.scala | 12 +++++ .../naha-synthetic/project/plugins.sbt | 1 + .../source-dependencies/naha-synthetic/test | 5 ++ .../nested-type-params/A.scala | 1 + .../nested-type-params/B.scala | 1 + .../nested-type-params/Bar.scala | 1 + .../nested-type-params/Foo.scala | 4 ++ .../nested-type-params/Providers.scala | 4 ++ .../nested-type-params/changes/Bar.scala | 1 + .../changes/Providers.scala | 4 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../nested-type-params/project/plugins.sbt | 1 + .../nested-type-params/test | 8 ++++ .../package-object-name/A.scala | 3 ++ .../package-object-name/b.scala | 1 + .../package-object-name/changes/A1.scala | 5 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../package-object-name/project/plugins.sbt | 1 + .../package-object-name/test | 3 ++ .../package-object-nested-class/A.scala | 6 +++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../package-object-nested-class/test | 2 + .../packageobject-and-traits/Bar.scala | 7 +++ .../packageobject-and-traits/Baz.scala | 3 ++ .../packageobject-and-traits/Foo.scala | 3 ++ .../packageobject-and-traits/foo.scala2 | 3 ++ .../packageobject-and-traits/pending | 4 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../pkg-private-class/A.scala | 4 ++ .../pkg-private-class/B.scala | 5 ++ .../pkg-private-class/changes/A.scala | 4 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../pkg-private-class/project/plugins.sbt | 1 + .../pkg-private-class/test | 5 ++ .../recorded-products/DefaultPkg.scala | 3 ++ .../recorded-products/Local.scala | 12 +++++ .../recorded-products/Nested.scala | 17 +++++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../recorded-products/project/plugins.sbt | 1 + .../recorded-products/test | 4 ++ .../struct-projection/A.scala | 3 ++ .../struct-projection/B.scala | 3 ++ .../struct-projection/changes/A.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../struct-projection/project/plugins.sbt | 1 + .../struct-projection/test | 4 ++ .../source-dependencies/struct-usage/A.scala | 3 ++ .../source-dependencies/struct-usage/B.scala | 3 ++ .../struct-usage/changes/A.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../struct-usage/project/plugins.sbt | 1 + .../source-dependencies/struct-usage/test | 5 ++ .../source-dependencies/struct/A.scala | 3 ++ .../source-dependencies/struct/B.scala | 4 ++ .../source-dependencies/struct/C.scala | 4 ++ .../struct/changes/A.scala | 3 ++ .../struct/project/DottyInjectedPlugin.scala | 12 +++++ .../struct/project/plugins.sbt | 1 + .../sbt-test/source-dependencies/struct/test | 9 ++++ .../subproject-dependency-b/build.sbt | 14 ++++++ .../subproject-dependency-b/changes/A1.scala | 4 ++ .../subproject-dependency-b/changes/A2.scala | 5 ++ .../subproject-dependency-b/pending | 9 ++++ .../subproject-dependency-b/provider/A.scala | 3 ++ .../subproject-dependency-b/use/B.scala | 4 ++ .../trait-private-val/changes/Base.scala | 8 ++++ .../trait-private-val/pending | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../trait-private-val/project/plugins.sbt | 1 + .../src/main/scala/foo/Base.scala | 5 ++ .../src/main/scala/foo/TestApp.scala | 5 ++ .../transitive-class/A.scala | 1 + .../transitive-class/BC.scala | 2 + .../transitive-class/D.scala | 4 ++ .../transitive-class/changes/A.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../transitive-class/project/plugins.sbt | 1 + .../source-dependencies/transitive-class/test | 3 ++ .../type-member-nested-object/A.scala | 6 +++ .../type-member-nested-object/B.scala | 3 ++ .../type-member-nested-object/C.scala | 3 ++ .../changes/B2.scala | 3 ++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../project/plugins.sbt | 1 + .../type-member-nested-object/test | 4 ++ .../unexpanded-names/Foo.scala | 19 ++++++++ .../project/DottyInjectedPlugin.scala | 12 +++++ .../unexpanded-names/project/plugins.sbt | 1 + .../source-dependencies/unexpanded-names/test | 2 + 250 files changed, 1464 insertions(+) create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/JJ.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/build.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/A.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/B.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/D.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/changes/A2.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/incOptions.properties create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/pending create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Sealed.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Usage.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-classes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-classes/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-classes/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-classes/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-dependencies/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-dependencies/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-dependencies/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-dependencies/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-products/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-products/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-products/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-products/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/D.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/check-recompilations/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/changes/A1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/incOptions.properties create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/changes/A2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/Foo.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/Use.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/build.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/pending create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/continuations/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/cross-source/pending create mode 100644 sbt-dotty/sbt-test/source-dependencies/cross-source/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/cross-source/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.10/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.9.3/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/empty-modified-names/T.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/empty-modified-names/changes/T.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/empty-modified-names/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/changed/FactoryProvider.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/FactoryProvider.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Lib.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Usage.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/M.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/JJ.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/build.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-anonymous/Outer.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-anonymous/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-enum/changes/SomeEnum.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-enum/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-enum/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-enum/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-inner/A.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-inner/C.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-inner/D.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-inner/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-inner/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-inner/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/Example.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/JFunction2$mcJDD$sp.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/A.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/B.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/D.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/changes/A2.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/D.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/changes/A2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/B.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name/Boo.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name/changes/BooUser.java create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/malformed-class-name/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/Bar.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/Foo.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/Providers.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Bar.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Providers.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/nested-type-params/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-name/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-name/b.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-name/changes/A1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-name/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-name/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-name/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Bar.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Baz.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Foo.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/foo.scala2 create mode 100644 sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/pending create mode 100644 sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/pkg-private-class/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/pkg-private-class/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/pkg-private-class/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/pkg-private-class/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/recorded-products/DefaultPkg.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/recorded-products/Local.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/recorded-products/Nested.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/recorded-products/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/recorded-products/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/recorded-products/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-projection/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-projection/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-projection/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-projection/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-projection/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-projection/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-usage/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-usage/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-usage/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-usage/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct-usage/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/struct/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A1.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending create mode 100644 sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/provider/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/use/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/trait-private-val/changes/Base.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/trait-private-val/pending create mode 100644 sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/Base.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/TestApp.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/transitive-class/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/transitive-class/BC.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/transitive-class/D.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/transitive-class/changes/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/transitive-class/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/transitive-class/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/transitive-class/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/A.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/B.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/C.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/changes/B2.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/test create mode 100644 sbt-dotty/sbt-test/source-dependencies/unexpanded-names/Foo.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/DottyInjectedPlugin.scala create mode 100644 sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/plugins.sbt create mode 100644 sbt-dotty/sbt-test/source-dependencies/unexpanded-names/test diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/JJ.java b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/JJ.java new file mode 100644 index 000000000000..3b9d25102fdd --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/JJ.java @@ -0,0 +1,11 @@ +public class JJ { + public static void main(String[] args) { + // Declare anonymous class depending on Scala class + S s = new S() { + public void foo(String s) { + System.out.println(s); + } + }; + s.foo("ahoy"); + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/build.sbt b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/build.sbt new file mode 100644 index 000000000000..f59b98eb6267 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/build.sbt @@ -0,0 +1 @@ +compileOrder := CompileOrder.Mixed diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S1.scala b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S1.scala new file mode 100644 index 000000000000..2400ac4da6df --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S1.scala @@ -0,0 +1,3 @@ +abstract class S { + def foo(s:String): Unit +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S2.scala b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S2.scala new file mode 100644 index 000000000000..dd84be54b8eb --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/changes/S2.scala @@ -0,0 +1,3 @@ +abstract class S { + def foo2(s:String): Unit +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/test b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/test new file mode 100644 index 000000000000..502d3699257f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-class-java-depends-on-scala/test @@ -0,0 +1,4 @@ +$ copy-file changes/S1.scala S.scala +> compile +$ copy-file changes/S2.scala S.scala +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/A.java b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/A.java new file mode 100644 index 000000000000..0ae4e417add2 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/A.java @@ -0,0 +1,3 @@ +public class A { + public A() {} +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/B.java b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/B.java new file mode 100644 index 000000000000..71f266b3596f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/B.java @@ -0,0 +1,3 @@ +public class B extends A { + public B() {} +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/C.scala b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/C.scala new file mode 100644 index 000000000000..23b26a9d6233 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/C.scala @@ -0,0 +1,5 @@ +class C { + def foo: Unit = { + val myFoo = new B {} + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/D.scala b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/D.scala new file mode 100644 index 000000000000..765d291e5733 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/D.scala @@ -0,0 +1,5 @@ +class D extends C { + // mention abc name to check if local inheritance dependencies are _not_ included in member reference + // extension of inheritance invalidation + def bar(abc: Int): Int = abc +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/changes/A2.java b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/changes/A2.java new file mode 100644 index 000000000000..a56de2c644f4 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/changes/A2.java @@ -0,0 +1,6 @@ +public class A { + public A() {} + public String hey() { + return "Hey"; + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/test b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/test new file mode 100644 index 000000000000..167accc3012d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/test @@ -0,0 +1,16 @@ +# Verifies if dependencies introduced by Java inheritance by local classes are handled correctly. +# See sbt-test 'local-class-inheritance' for a similar test in Scala. + +> compile + +$ copy-file changes/A2.java A.java +> compile +# D should be compiled only at the beginning; it depends by inheritance only +# on C and C's public interface is not affected by changes to A +> checkRecompilations 0 D +# A is explicitly changed +> checkRecompilations 1 A +# B is recompiled because it depends by inheritance on A +# C is recompiled because it depends by local inheritance on B but its +# dependencies (D) are not recompiled +> checkRecompilations 2 B C diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed1.scala b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed1.scala new file mode 100644 index 000000000000..e3dc637f6c3c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed1.scala @@ -0,0 +1,9 @@ +package foo + +sealed trait Sealed + +object Child1 extends Sealed with Base +object Child2 extends Sealed with OtherBase + +trait Base +trait OtherBase extends Base \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed2.scala b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed2.scala new file mode 100644 index 000000000000..c58157acc81e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/changed/Sealed2.scala @@ -0,0 +1,9 @@ +package foo + +sealed trait Sealed + +object Child1 extends Sealed with Base +object Child2 extends Sealed with OtherBase + +trait Base +trait OtherBase \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/incOptions.properties b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/incOptions.properties new file mode 100644 index 000000000000..fad0545c8f66 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/incOptions.properties @@ -0,0 +1 @@ +scalac.options = -Xfatal-warnings \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/pending b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/pending new file mode 100644 index 000000000000..a1c04ccbd3d2 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/pending @@ -0,0 +1,10 @@ +# Compilation with warning should fail +-> compile + +# Remove warning +$ copy-file changed/Sealed1.scala src/main/scala/foo/Sealed.scala +> compile + +# Add warning again without touching Child2 definition +$ copy-file changed/Sealed2.scala src/main/scala/foo/Sealed.scala +-> compile \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Sealed.scala b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Sealed.scala new file mode 100644 index 000000000000..8c618c7dda03 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Sealed.scala @@ -0,0 +1,9 @@ +package foo + +sealed trait Sealed + +object Child1 extends Sealed with Base +object Child2 extends Sealed // 'with Base' will be added then removed + +trait Base +trait OtherBase extends Base \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Usage.scala b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Usage.scala new file mode 100644 index 000000000000..b5275c33ce39 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/changedTypeOfChildOfSealed/src/main/scala/foo/Usage.scala @@ -0,0 +1,8 @@ +package foo + +object Usage{ + def ala(a: Sealed) = a match { + case _: Base => + 1 + } +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-classes/A.scala b/sbt-dotty/sbt-test/source-dependencies/check-classes/A.scala new file mode 100644 index 000000000000..528ffce71c5f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-classes/A.scala @@ -0,0 +1 @@ +object A \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-classes/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/check-classes/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-classes/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/check-classes/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/check-classes/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-classes/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/check-classes/test b/sbt-dotty/sbt-test/source-dependencies/check-classes/test new file mode 100644 index 000000000000..07102eb11c46 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-classes/test @@ -0,0 +1,2 @@ +> compile +> checkClasses A.scala: A diff --git a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/A.scala b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/A.scala new file mode 100644 index 000000000000..7413db57f482 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/A.scala @@ -0,0 +1 @@ +class A extends B with C \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/B.scala b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/B.scala new file mode 100644 index 000000000000..3a691aca2c27 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/B.scala @@ -0,0 +1 @@ +trait B \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/C.scala b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/C.scala new file mode 100644 index 000000000000..4b6f6492bba5 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/C.scala @@ -0,0 +1 @@ +trait C \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/test b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/test new file mode 100644 index 000000000000..dffaeef47e2b --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/test @@ -0,0 +1,3 @@ +> compile + +> checkDependencies A: B C \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-products/A.scala b/sbt-dotty/sbt-test/source-dependencies/check-products/A.scala new file mode 100644 index 000000000000..528ffce71c5f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-products/A.scala @@ -0,0 +1 @@ +object A \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-products/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/check-products/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-products/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/check-products/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/check-products/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-products/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/check-products/test b/sbt-dotty/sbt-test/source-dependencies/check-products/test new file mode 100644 index 000000000000..a36de2f35fac --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-products/test @@ -0,0 +1,2 @@ +> compile +> checkProducts A.scala: A.class A$.class \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/A.scala b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/A.scala new file mode 100644 index 000000000000..44662722128f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/A.scala @@ -0,0 +1,3 @@ +object A { + def foo = 0 +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/B.scala b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/B.scala new file mode 100644 index 000000000000..45553257be07 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/B.scala @@ -0,0 +1,3 @@ +object B { + def bar = A.foo +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/C.scala b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/C.scala new file mode 100644 index 000000000000..9581d2b04a44 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/C.scala @@ -0,0 +1,3 @@ +object C { + def baz = A.foo +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/D.scala b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/D.scala new file mode 100644 index 000000000000..dfcc8661936e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/D.scala @@ -0,0 +1,3 @@ +object D { + def foobar = C.baz +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/changes/A.scala new file mode 100644 index 000000000000..5cb6c0e738f6 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/changes/A.scala @@ -0,0 +1,3 @@ +object A { + def foo = "" +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/test b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/test new file mode 100644 index 000000000000..60220ed86e57 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/test @@ -0,0 +1,10 @@ +> compile + +$ copy-file changes/A.scala A.scala + +> compile + +> checkRecompilations 0 +> checkRecompilations 1 A +> checkRecompilations 2 B C +> checkRecompilations 3 D diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A1.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A1.scala new file mode 100644 index 000000000000..bb0e18f9fd13 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A1.scala @@ -0,0 +1,5 @@ +class A { + class AA +} + +class A2 diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A2.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A2.scala new file mode 100644 index 000000000000..2063aea9e5bb --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/changes/A2.scala @@ -0,0 +1,8 @@ +class A { + class AA { + // add a member to an inner class, dependencies on A shouldn't be recompiled + def foo: Int = 123 + } +} + +class A2 diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/A.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/A.scala new file mode 100644 index 000000000000..cee8704bb6a0 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/A.scala @@ -0,0 +1,5 @@ +class A { + // class AA +} + +class A2 diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/B.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/B.scala new file mode 100644 index 000000000000..11a098a4261d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/B.scala @@ -0,0 +1 @@ +class B extends A2 diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/C.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/C.scala new file mode 100644 index 000000000000..3316d2e6ad68 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/src/main/scala/C.scala @@ -0,0 +1 @@ +class C extends A diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/test b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/test new file mode 100644 index 000000000000..56f649bedd4d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/test @@ -0,0 +1,21 @@ +# Test for class-based invalidation of dependencies +# by inheritance. The source file A.scala defines +# A and A2 classes. The B.scala inherits from A2 but +# in the test api of A is modified. B.scala shouldn't +# get invalidated if invalidation happens at +# class level +# this test case covers https://github.com/sbt/sbt/issues/2320 + +# introduces first compile iteration +> compile +$ copy-file changes/A1.scala src/main/scala/A.scala +# second iteration and third iteration (due to invalidation of C) +> compile +$ copy-file changes/A2.scala src/main/scala/A.scala +# fourth iteration +> compile +# check if there were exactly four compile iterations performed +> checkRecompilations 0 B +> checkRecompilations 1 +> checkRecompilations 2 C +> checkRecompilations 3 A A2 A.AA diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/changes/A1.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/changes/A1.scala new file mode 100644 index 000000000000..7de71fc6589d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/changes/A1.scala @@ -0,0 +1,7 @@ +class A1 { + //def foo: Int = 123 +} + +class A2 { + def bar: Int = 42 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/incOptions.properties b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/incOptions.properties new file mode 100644 index 000000000000..b538c59f6192 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/incOptions.properties @@ -0,0 +1 @@ +recompileAllFraction = 1.0 diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/A.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/A.scala new file mode 100644 index 000000000000..6bf9c6b139b9 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/A.scala @@ -0,0 +1,7 @@ +class A1 { + def foo: Int = 123 +} + +class A2 { + def bar: Int = 42 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/B.scala b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/B.scala new file mode 100644 index 000000000000..833512600062 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/src/main/scala/B.scala @@ -0,0 +1,6 @@ +class B1(a1: A1) + +class B2(a2: A2) { + def foo: Int = 53 + def abc: Int = foo + a2.bar +} diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/test b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/test new file mode 100644 index 000000000000..83b615b90c47 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/test @@ -0,0 +1,11 @@ +# Test for class-based invalidation of dependencies by member reference +# This test checks if name hashes are tracked at the class level so +# only classes that depend on an API of a modified class are invalidated + +# introduces first compile iteration +> compile +$ copy-file changes/A1.scala src/main/scala/A.scala +# second iteration +> compile +> checkRecompilations 0 B1 B2 +> checkRecompilations 1 A1 A2 diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/A.scala b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/A.scala new file mode 100644 index 000000000000..b8c61e25e190 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/A.scala @@ -0,0 +1,2 @@ +class A(a: Int) +object A { val x = 3 } diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/B.scala b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/B.scala new file mode 100644 index 000000000000..5578bb7a6d23 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/B.scala @@ -0,0 +1 @@ +class B { val y = A.x } diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/changes/A2.scala b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/changes/A2.scala new file mode 100644 index 000000000000..da14d8945d10 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/changes/A2.scala @@ -0,0 +1,2 @@ +class A(a: String) +object A { val x = 3 } diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test new file mode 100644 index 000000000000..efd4edd50098 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test @@ -0,0 +1,6 @@ +> compile +$ copy-file changes/A2.scala A.scala +# Second compilation round, there should be no third round (we don't need to recompile B.scala) +> compile +# Check that there were only two rounds of compilation +> checkIterations 2 diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/Foo.scala b/sbt-dotty/sbt-test/source-dependencies/continuations/Foo.scala new file mode 100644 index 000000000000..580f7175ab62 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/Foo.scala @@ -0,0 +1,3 @@ +trait Foo +trait BarA +trait BarB \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/Use.scala b/sbt-dotty/sbt-test/source-dependencies/continuations/Use.scala new file mode 100644 index 000000000000..bdb8484647d6 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/Use.scala @@ -0,0 +1,6 @@ +import scala.util.continuations._ + +class Use { + val a = new Baz + def bar: (Foo with BarA) @cpsParam[Unit, Unit] = a.foo +} diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/build.sbt b/sbt-dotty/sbt-test/source-dependencies/continuations/build.sbt new file mode 100644 index 000000000000..b0f2eb814602 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/build.sbt @@ -0,0 +1,7 @@ +autoCompilerPlugins := true + +addCompilerPlugin("org.scala-lang.plugins" % "continuations" % "2.9.2") + +scalaVersion := "2.9.2" + +scalacOptions += "-P:continuations:enable" \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def1.scala b/sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def1.scala new file mode 100644 index 000000000000..3cc76e19313e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def1.scala @@ -0,0 +1,5 @@ +import scala.util.continuations._ + +class Baz { + def foo = shiftUnit[Foo with BarA, Unit, Unit](null) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def2.scala b/sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def2.scala new file mode 100644 index 000000000000..9a176dffbf76 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/changes/Def2.scala @@ -0,0 +1,5 @@ +import scala.util.continuations._ + +class Baz { + def foo = shiftUnit[Foo with BarB, Unit, Unit](null) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/pending b/sbt-dotty/sbt-test/source-dependencies/continuations/pending new file mode 100644 index 000000000000..b89168c25a4d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/pending @@ -0,0 +1,13 @@ +# Compile code with a type (Foo with BarA) @cpsParam... +# The spec says only simple types can be annotated, but scalac allows any type. +$ copy-file changes/Def1.scala Def.scala +> compile + +# To ensure it was properly processed, change it to (Foo with BarB) @cpsParam... +# This should invalidate Use.scala, which expects it to be BarA and so compilation should fail. +$ delete Def.scala +$ copy-file changes/Def2.scala Def.scala +-> compile + +# The following command is added to fail this test intentionally since this scripted doesn't handle compiler plugins +> x diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/continuations/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/continuations/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/continuations/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/continuations/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/cross-source/pending b/sbt-dotty/sbt-test/source-dependencies/cross-source/pending new file mode 100644 index 000000000000..d7964677feb9 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/cross-source/pending @@ -0,0 +1,16 @@ +# A.scala needs B.scala, it won't be in source list +> ++2.11.4 +-> compile + +# A.scala needs B.scala, it would be in source list +> ++2.10.4 +> compile + +# A.scala needs B.scala, it would be in source list +> ++2.9.3 +> compile + +# Injecting the wrong B.scala in source list +$ copy-file src/main/scala-2.10/B.scala src/main/scala-2.9.3/B.scala +> ++2.9.3 +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/cross-source/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/cross-source/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/cross-source/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/cross-source/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/cross-source/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/cross-source/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.10/B.scala b/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.10/B.scala new file mode 100644 index 000000000000..fa8ad30ea336 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.10/B.scala @@ -0,0 +1,3 @@ +object B { + def show(what: String): String = s"String interpolation is ${what.toUpperCase}!" +} diff --git a/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.9.3/B.scala b/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.9.3/B.scala new file mode 100644 index 000000000000..b1d5f8d3aa42 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala-2.9.3/B.scala @@ -0,0 +1,3 @@ +object B { + def show(what: String): String = "String interpolation is " + what.toUpperCase +} diff --git a/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala/A.scala b/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala/A.scala new file mode 100644 index 000000000000..9a6957a19978 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/cross-source/src/main/scala/A.scala @@ -0,0 +1,3 @@ +class A { + def show(what: String): String = B.show(what) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/T.scala b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/T.scala new file mode 100644 index 000000000000..bda3ba02d27c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/T.scala @@ -0,0 +1,3 @@ +trait T2 +trait T1 extends T2 { def foo: String } +class C1 extends T1 { def foo = "test" } diff --git a/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/changes/T.scala b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/changes/T.scala new file mode 100644 index 000000000000..1d0c3cfef089 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/changes/T.scala @@ -0,0 +1,3 @@ +trait T2 { def foo: String } +trait T1 extends T2 +class C1 extends T1 { def foo = "test" } diff --git a/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/test b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/test new file mode 100644 index 000000000000..f8822aa9bb86 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/empty-modified-names/test @@ -0,0 +1,3 @@ +> compile +$ copy-file changes/T.scala T.scala +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/changed/FactoryProvider.scala b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/changed/FactoryProvider.scala new file mode 100644 index 000000000000..7a15e03339f1 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/changed/FactoryProvider.scala @@ -0,0 +1,6 @@ +package foo + +object FactoryProvider { + import Types.:: + type MyFactory = FactoryA :: Nil +} diff --git a/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/FactoryProvider.scala b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/FactoryProvider.scala new file mode 100644 index 000000000000..224479fd9da5 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/FactoryProvider.scala @@ -0,0 +1,6 @@ +package foo + +object FactoryProvider { + import Types.:: + type MyFactory = FactoryB :: Nil +} diff --git a/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Lib.scala b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Lib.scala new file mode 100644 index 000000000000..16c7f75a7b07 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Lib.scala @@ -0,0 +1,36 @@ +package foo + +trait Factory { + type Product +} + +trait Type extends Factory { + type Prepend[P <: Factory] <: Type +} + +trait Types[A <: Factory, B <: Type] extends Type { + override type Prepend[P <: Factory] = Types[P, Types[A, B]] + type Product = A#Product with B#Product +} + +object Types { + type ::[H <: Factory, T <: Type] = T#Prepend[H] +} + +trait Nil extends Type { + type Prepend[P <: Factory] = Types[P, Nil] +} + +trait FactoryA extends Type { + override type Product = A +} + +trait A + +trait FactoryB extends Factory { + override type Product = B +} + +trait B { + def foo = 1 +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Usage.scala b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Usage.scala new file mode 100644 index 000000000000..a59a0ce86589 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/src/main/scala/foo/Usage.scala @@ -0,0 +1,7 @@ +package foo + +trait Usage { + def x: FactoryProvider.type#MyFactory#Product + + x.foo +} diff --git a/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/test b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/test new file mode 100644 index 000000000000..1b3bdede11da --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/expanded-type-projection/test @@ -0,0 +1,5 @@ +> compile +$ copy-file changed/FactoryProvider.scala src/main/scala/foo/FactoryProvider.scala +-> compile +> clean +-> compile \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A1.scala b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A1.scala new file mode 100644 index 000000000000..c56e4578f9a3 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A1.scala @@ -0,0 +1,3 @@ +import scala.languageFeature.higherKinds +trait A +object A diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A2.scala b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A2.scala new file mode 100644 index 000000000000..1b749793de4f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/A2.scala @@ -0,0 +1,5 @@ +import scala.languageFeature.higherKinds +trait A +object A { + implicit def m[MM[_], A]: MM[A] = ??? +} diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/B.scala b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/B.scala new file mode 100644 index 000000000000..c49ed55ad89a --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/B.scala @@ -0,0 +1,2 @@ + +trait B extends A diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/C.scala b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/C.scala new file mode 100644 index 000000000000..7fd8032223f0 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/C.scala @@ -0,0 +1,3 @@ +object Test { + implicitly[M[B]] +} diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/M.scala b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/M.scala new file mode 100644 index 000000000000..9fd664beae5a --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/changes/M.scala @@ -0,0 +1,6 @@ +import scala.languageFeature.higherKinds + +class M[A](a: A) +object M { + implicit def m[MM[_], A]: MM[A] = ??? +} diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/test b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/test new file mode 100644 index 000000000000..e5f50944f1d4 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/implicit-search-higher-kinded/test @@ -0,0 +1,14 @@ +# Tests if dependencies on implicit scope are tracked properly +# We use higher kinded types in order to make type checker to +# infer more and thus obscure true dependencies +$ copy-file changes/A1.scala A.scala +$ copy-file changes/B.scala B.scala +$ copy-file changes/M.scala M.scala +$ copy-file changes/C.scala C.scala +> compile + +$ copy-file changes/A2.scala A.scala +-> compile + +> clean +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/JJ.java b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/JJ.java new file mode 100644 index 000000000000..1ae12067396e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/JJ.java @@ -0,0 +1,12 @@ +public class JJ { + public static void main(String[] args) { + // Declare anonymous class depending on Scala class + class FromScala extends S { + public void foo(String s) { + System.out.println(s); + } + } + S s = new FromScala(); + s.foo("ahoy"); + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/build.sbt b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/build.sbt new file mode 100644 index 000000000000..f59b98eb6267 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/build.sbt @@ -0,0 +1 @@ +compileOrder := CompileOrder.Mixed diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S1.scala b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S1.scala new file mode 100644 index 000000000000..2400ac4da6df --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S1.scala @@ -0,0 +1,3 @@ +abstract class S { + def foo(s:String): Unit +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S2.scala b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S2.scala new file mode 100644 index 000000000000..dd84be54b8eb --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/changes/S2.scala @@ -0,0 +1,3 @@ +abstract class S { + def foo2(s:String): Unit +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/test b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/test new file mode 100644 index 000000000000..502d3699257f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class-java-depends-on-scala/test @@ -0,0 +1,4 @@ +$ copy-file changes/S1.scala S.scala +> compile +$ copy-file changes/S2.scala S.scala +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/java-anonymous/Outer.java b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/Outer.java new file mode 100644 index 000000000000..6b0da572204b --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/Outer.java @@ -0,0 +1,9 @@ +class Outer { + Object getAnonymous() { + return new Object() { + int foo() { + return 842; + } + }; + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/java-anonymous/test b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/test new file mode 100644 index 000000000000..a43628b0f196 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-anonymous/test @@ -0,0 +1,2 @@ +# This test doesn't check anything due to: https://github.com/sbt/zinc/issues/83 +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/java-enum/changes/SomeEnum.java b/sbt-dotty/sbt-test/source-dependencies/java-enum/changes/SomeEnum.java new file mode 100644 index 000000000000..b0fed9f02725 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-enum/changes/SomeEnum.java @@ -0,0 +1,18 @@ +package pl.typosafe; + +/** + * Author: Krzysztof Romanowski + */ +public enum SomeEnum { + Baz, + Bar { + @Override + public int foo() { + return 2; + } + }; + + public int foo(){ + return 1; + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-enum/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/java-enum/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-enum/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-enum/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/java-enum/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-enum/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/java-enum/test b/sbt-dotty/sbt-test/source-dependencies/java-enum/test new file mode 100644 index 000000000000..6b3955e8d713 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-enum/test @@ -0,0 +1,2 @@ +$ copy-file changes/SomeEnum.java src/main/java/pl/typosafe/SomeEnum.java +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/java-inner/A.java b/sbt-dotty/sbt-test/source-dependencies/java-inner/A.java new file mode 100644 index 000000000000..bcd7b8034986 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-inner/A.java @@ -0,0 +1,5 @@ +class A { + class B { + public D d = new D(); + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-inner/C.java b/sbt-dotty/sbt-test/source-dependencies/java-inner/C.java new file mode 100644 index 000000000000..c52551876c67 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-inner/C.java @@ -0,0 +1,5 @@ + +class C { + A a = new A(); + A.B b = a.new B(); +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/java-inner/D.java b/sbt-dotty/sbt-test/source-dependencies/java-inner/D.java new file mode 100644 index 000000000000..5cbe69a4f706 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-inner/D.java @@ -0,0 +1,2 @@ + +class D {} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-inner/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/java-inner/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-inner/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-inner/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/java-inner/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-inner/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/java-inner/test b/sbt-dotty/sbt-test/source-dependencies/java-inner/test new file mode 100644 index 000000000000..3300a912beae --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-inner/test @@ -0,0 +1,6 @@ +> compile +> checkProducts A.java: A.class A$B.class +> checkProducts C.java: C.class +> checkDependencies A: A.B +> checkDependencies A.B: A D +> checkDependencies C: A A.B diff --git a/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/Example.java b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/Example.java new file mode 100644 index 000000000000..413bb68d59f8 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/Example.java @@ -0,0 +1,26 @@ +package typeparameters; + +import java.util.function.Supplier; + +public class Example { + + static void call() { + Supplier> blah = () -> + new BaseBlah() { + @Override + protected O getResponseInternal(I i) { + return null; + } + }; + } + + public static void main(String[] args) { + Example.call(); + } +} + +abstract class BaseBlah { + protected O getResponseInternal(I i) { + return null; + } +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/test b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/test new file mode 100644 index 000000000000..73a68203f3f1 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-lambda-typeparams/test @@ -0,0 +1 @@ +> compile \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/JFunction2$mcJDD$sp.java b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/JFunction2$mcJDD$sp.java new file mode 100644 index 000000000000..a3e928e6c6e1 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/JFunction2$mcJDD$sp.java @@ -0,0 +1,5 @@ +public interface JFunction2$mcJDD$sp { + long apply$mcJDD$sp(double v1, double v2); + + Object apply(Object v1, Object v2); +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/test b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/test new file mode 100644 index 000000000000..a43628b0f196 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/java-name-with-dollars/test @@ -0,0 +1,2 @@ +# This test doesn't check anything due to: https://github.com/sbt/zinc/issues/83 +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/A.java b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/A.java new file mode 100644 index 000000000000..0ae4e417add2 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/A.java @@ -0,0 +1,3 @@ +public class A { + public A() {} +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/B.java b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/B.java new file mode 100644 index 000000000000..71f266b3596f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/B.java @@ -0,0 +1,3 @@ +public class B extends A { + public B() {} +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/C.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/C.scala new file mode 100644 index 000000000000..2e16281b342d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/C.scala @@ -0,0 +1,5 @@ +class C { + def foo: Unit = { + class Foo extends B + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/D.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/D.scala new file mode 100644 index 000000000000..765d291e5733 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/D.scala @@ -0,0 +1,5 @@ +class D extends C { + // mention abc name to check if local inheritance dependencies are _not_ included in member reference + // extension of inheritance invalidation + def bar(abc: Int): Int = abc +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/changes/A2.java b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/changes/A2.java new file mode 100644 index 000000000000..a56de2c644f4 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/changes/A2.java @@ -0,0 +1,6 @@ +public class A { + public A() {} + public String hey() { + return "Hey"; + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/test b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/test new file mode 100644 index 000000000000..167accc3012d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/test @@ -0,0 +1,16 @@ +# Verifies if dependencies introduced by Java inheritance by local classes are handled correctly. +# See sbt-test 'local-class-inheritance' for a similar test in Scala. + +> compile + +$ copy-file changes/A2.java A.java +> compile +# D should be compiled only at the beginning; it depends by inheritance only +# on C and C's public interface is not affected by changes to A +> checkRecompilations 0 D +# A is explicitly changed +> checkRecompilations 1 A +# B is recompiled because it depends by inheritance on A +# C is recompiled because it depends by local inheritance on B but its +# dependencies (D) are not recompiled +> checkRecompilations 2 B C diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/A.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/A.scala new file mode 100644 index 000000000000..83d15dc739b5 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/A.scala @@ -0,0 +1 @@ +class A diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/B.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/B.scala new file mode 100644 index 000000000000..26e47fd25fdb --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/B.scala @@ -0,0 +1 @@ +class B extends A \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/C.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/C.scala new file mode 100644 index 000000000000..2e16281b342d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/C.scala @@ -0,0 +1,5 @@ +class C { + def foo: Unit = { + class Foo extends B + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/D.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/D.scala new file mode 100644 index 000000000000..765d291e5733 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/D.scala @@ -0,0 +1,5 @@ +class D extends C { + // mention abc name to check if local inheritance dependencies are _not_ included in member reference + // extension of inheritance invalidation + def bar(abc: Int): Int = abc +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/changes/A2.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/changes/A2.scala new file mode 100644 index 000000000000..5220e08b9a07 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/changes/A2.scala @@ -0,0 +1,3 @@ +class A { + def abc: Int = 124 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/test b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/test new file mode 100644 index 000000000000..8345c0764058 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/test @@ -0,0 +1,17 @@ +# Verifies if dependencies introduced by inheritance by local classes are handled correctly. +# They are different from regular inheritance dependencies because they should not be +# invalidated transitively, see: https://github.com/sbt/sbt/issues/1104#issuecomment-169146039 + +> compile + +$ copy-file changes/A2.scala A.scala +> compile +# D should be compiled only at the beginning; it depends by inheritance only +# on C and C's public interface is not affected by changes to A +> checkRecompilations 0 D +# A is explicitly changed +> checkRecompilations 1 A +# B is recompiled because it depends by inheritance on A +# C is recompiled because it depends by local inheritance on B but its +# dependencies (D) are not recompiled +> checkRecompilations 2 B C diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/B.java b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/B.java new file mode 100644 index 000000000000..2482b5bb465d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/B.java @@ -0,0 +1,5 @@ +public class B { + public static class C$ { + public static int x = 42; + } +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/changes/A.scala new file mode 100644 index 000000000000..d17a3273a0c8 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/changes/A.scala @@ -0,0 +1,3 @@ +object A { + def foo = B.C$.x +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/test b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/test new file mode 100644 index 000000000000..b0353a1a0cca --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name-with-dollar/test @@ -0,0 +1,3 @@ +> compile +$ copy-file changes/A.scala A.scala +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/Boo.scala b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/Boo.scala new file mode 100644 index 000000000000..ed982b750cdf --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/Boo.scala @@ -0,0 +1,48 @@ +package repro + +abstract class Boo { + val b = Boo +} + +// Tests simple class in nested objects +object Boo { + object Foo { + class Impl + } +} + +abstract class Boo2 { + val b2 = Boo2 +} + +// Tests simple class in object, special-cased (by Scala) +// It does and should not trigger malformed class name. +object Boo2 { + class Impl +} + +abstract class Boo3 { + val b3 = Boo3 +} + +// Tests three nested object + class +object Boo3 { + object Foo2 { + object Bar { + class Impl + } + } +} + +abstract class Boo4 { + val b4 = Boo4 +} + +// Tests nested classes inside nested objects +object Boo4 { + object Foo3 { + class BarClass { + class Impl + } + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/changes/BooUser.java b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/changes/BooUser.java new file mode 100644 index 000000000000..005f86c1ade0 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/changes/BooUser.java @@ -0,0 +1,32 @@ +package repro; + +import repro.Boo; +import repro.Boo2; +import repro.Boo3; +import repro.Boo4; + +public class BooUser { + private static Boo getOwnBuf() { + return new Boo() {}; + } + + private static Boo2 getOwnBuf2() { + return new Boo2() {}; + } + + private static Boo3 getOwnBuf3() { + return new Boo3() {}; + } + + private static Boo4 getOwnBuf4() { + return new Boo4() {}; + } + + public static void main(String[] args) { + Boo boo = getOwnBuf(); + Boo2 boo2 = getOwnBuf2(); + Boo3 boo3 = getOwnBuf3(); + Boo4 boo4 = getOwnBuf4(); + System.out.println("Made a buf: " + boo); + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/test b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/test new file mode 100644 index 000000000000..cbe46d17f239 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/malformed-class-name/test @@ -0,0 +1,3 @@ +> compile +$ copy-file changes/BooUser.java BooUser.java +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala new file mode 100644 index 000000000000..acafe2da159d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala @@ -0,0 +1 @@ +case class A(a: Int) diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala new file mode 100644 index 000000000000..2c4519ab3a1c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala @@ -0,0 +1 @@ +class B { def test(a: A) = a.copy() } diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt new file mode 100644 index 000000000000..cd5970b1cf89 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt @@ -0,0 +1,5 @@ +lazy val root = (project in file(".")). + settings( + scalaVersion := "2.11.7", + incOptions := incOptions.value.withIncludeSynthToNameHashing(true) + ) diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala new file mode 100644 index 000000000000..57eb90ceef54 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala @@ -0,0 +1 @@ +case class A(a: Int) { private def copy = ??? } diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test new file mode 100644 index 000000000000..4896f0dcc042 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test @@ -0,0 +1,5 @@ +> compile + +$ copy-file changes/A.scala A.scala + +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/A.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/A.scala new file mode 100644 index 000000000000..7bfd0a4e4b24 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/A.scala @@ -0,0 +1 @@ +trait A { def a = 1 } \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/B.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/B.scala new file mode 100644 index 000000000000..ab2df2a85ad6 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/B.scala @@ -0,0 +1 @@ +trait B { def b = 1.0 } \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Bar.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Bar.scala new file mode 100644 index 000000000000..331d12769d9a --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Bar.scala @@ -0,0 +1 @@ +object Bar { Foo.provide.a } \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Foo.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Foo.scala new file mode 100644 index 000000000000..a1bf7a7ac8e1 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Foo.scala @@ -0,0 +1,4 @@ +object Foo { + // Compilation will also fail if we change Providers.type#SomeProvider to Provider + def provide: Providers.type#SomeProvider#Operations = ??? +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Providers.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Providers.scala new file mode 100644 index 000000000000..8747ea143c43 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/Providers.scala @@ -0,0 +1,4 @@ +trait Provider { type Operations = A } + +object Providers { type SomeProvider = Provider } + diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Bar.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Bar.scala new file mode 100644 index 000000000000..2c9f2a546be9 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Bar.scala @@ -0,0 +1 @@ +object Bar { Foo.provide.b } \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Providers.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Providers.scala new file mode 100644 index 000000000000..e20f723e012d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/changes/Providers.scala @@ -0,0 +1,4 @@ +trait Provider { type Operations = B } + +object Providers { type SomeProvider = Provider } + diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/test b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/test new file mode 100644 index 000000000000..0c3e2ab7f68c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/test @@ -0,0 +1,8 @@ +> compile + +$ copy-file changes/Providers.scala Providers.scala +$ copy-file changes/Bar.scala Bar.scala + +-> compile # This should compile +> clean +> compile # Make sure that clean compile is fine \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-name/A.scala b/sbt-dotty/sbt-test/source-dependencies/package-object-name/A.scala new file mode 100644 index 000000000000..8f3c381af340 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-name/A.scala @@ -0,0 +1,3 @@ +package b + +class A diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-name/b.scala b/sbt-dotty/sbt-test/source-dependencies/package-object-name/b.scala new file mode 100644 index 000000000000..0a6e215a5258 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-name/b.scala @@ -0,0 +1 @@ +package object b extends A diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-name/changes/A1.scala b/sbt-dotty/sbt-test/source-dependencies/package-object-name/changes/A1.scala new file mode 100644 index 000000000000..b759f29cb5b6 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-name/changes/A1.scala @@ -0,0 +1,5 @@ +package b + +class A { + def foo = 1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-name/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/package-object-name/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-name/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-name/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/package-object-name/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-name/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-name/test b/sbt-dotty/sbt-test/source-dependencies/package-object-name/test new file mode 100644 index 000000000000..7c3c1b8f3bfd --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-name/test @@ -0,0 +1,3 @@ +> compile +$ copy-file changes/A1.scala A.scala +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/A.scala b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/A.scala new file mode 100644 index 000000000000..3ccf3c3a5561 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/A.scala @@ -0,0 +1,6 @@ +package object abc { + object BuildInfoKey { + sealed trait Entry + } + class Foo +} diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/test b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/test new file mode 100644 index 000000000000..8a33e63a9c93 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/package-object-nested-class/test @@ -0,0 +1,2 @@ +> compile + diff --git a/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Bar.scala b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Bar.scala new file mode 100644 index 000000000000..540cf78387f8 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Bar.scala @@ -0,0 +1,7 @@ +import foo.Foo +import Baz.myNr + + +class Bar { + val nr: Int = implicitly +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Baz.scala b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Baz.scala new file mode 100644 index 000000000000..f3d6070b846d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Baz.scala @@ -0,0 +1,3 @@ +object Baz { + implicit val myNr = 1234 +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Foo.scala b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Foo.scala new file mode 100644 index 000000000000..6374dc2d5d73 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/Foo.scala @@ -0,0 +1,3 @@ +package foo + +trait Foo \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/foo.scala2 b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/foo.scala2 new file mode 100644 index 000000000000..bb7e2e513814 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/foo.scala2 @@ -0,0 +1,3 @@ +package object foo { + implicit val Foo = 123 +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/pending b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/pending new file mode 100644 index 000000000000..2c026c0b4e30 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/pending @@ -0,0 +1,4 @@ +> compile +$ copy-file foo.scala2 foo.scala +# clean compile fails correctly +-> compile \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/packageobject-and-traits/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/A.scala b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/A.scala new file mode 100644 index 000000000000..3669f315aab5 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/A.scala @@ -0,0 +1,4 @@ +package pkg1 +private class A { + def foo: Int = 1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/B.scala b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/B.scala new file mode 100644 index 000000000000..49fc39b478b6 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/B.scala @@ -0,0 +1,5 @@ +package pkg1 + +class B { + def bar(a: A): Int = a.foo +} diff --git a/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/changes/A.scala new file mode 100644 index 000000000000..c1720c821deb --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/changes/A.scala @@ -0,0 +1,4 @@ +package pkg1 +private class A { + //def foo: Int = 1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/test b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/test new file mode 100644 index 000000000000..4896f0dcc042 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/pkg-private-class/test @@ -0,0 +1,5 @@ +> compile + +$ copy-file changes/A.scala A.scala + +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/recorded-products/DefaultPkg.scala b/sbt-dotty/sbt-test/source-dependencies/recorded-products/DefaultPkg.scala new file mode 100644 index 000000000000..933a667d7b61 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/recorded-products/DefaultPkg.scala @@ -0,0 +1,3 @@ +class A + +object B diff --git a/sbt-dotty/sbt-test/source-dependencies/recorded-products/Local.scala b/sbt-dotty/sbt-test/source-dependencies/recorded-products/Local.scala new file mode 100644 index 000000000000..1229fe717146 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/recorded-products/Local.scala @@ -0,0 +1,12 @@ + +class Container { + def foo = { + class C + } + def bar = { + // anonymous class + new T {} + } +} + +trait T diff --git a/sbt-dotty/sbt-test/source-dependencies/recorded-products/Nested.scala b/sbt-dotty/sbt-test/source-dependencies/recorded-products/Nested.scala new file mode 100644 index 000000000000..1c908527bd0e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/recorded-products/Nested.scala @@ -0,0 +1,17 @@ +package foo.bar + +class Outer { + object InnerO { + class A + object B + } + class InnerC { + trait T + } +} + +object Outer { + class X { + object Y + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/recorded-products/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/recorded-products/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/recorded-products/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/recorded-products/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/recorded-products/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/recorded-products/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/recorded-products/test b/sbt-dotty/sbt-test/source-dependencies/recorded-products/test new file mode 100644 index 000000000000..300da70fe8f8 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/recorded-products/test @@ -0,0 +1,4 @@ +> compile +> checkProducts DefaultPkg.scala: A.class B$.class B.class +> checkProducts Nested.scala: foo/bar/Outer$InnerC$T.class foo/bar/Outer$InnerO$B$.class foo/bar/Outer$InnerO$.class foo/bar/Outer$X.class foo/bar/Outer$.class foo/bar/Outer.class foo/bar/Outer$InnerC.class foo/bar/Outer$X$Y$.class foo/bar/Outer$InnerO$A.class +> checkProducts Local.scala: T.class Container.class Container$$anon$1.class Container$C$1.class diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-projection/A.scala b/sbt-dotty/sbt-test/source-dependencies/struct-projection/A.scala new file mode 100644 index 000000000000..f5a48b4ade9e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-projection/A.scala @@ -0,0 +1,3 @@ +object A { + def m: ({type T <: Int})#T = ??? +} diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-projection/B.scala b/sbt-dotty/sbt-test/source-dependencies/struct-projection/B.scala new file mode 100644 index 000000000000..8890082305ea --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-projection/B.scala @@ -0,0 +1,3 @@ +object B { + val x: Int = A.m +} diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-projection/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/struct-projection/changes/A.scala new file mode 100644 index 000000000000..da04006f2628 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-projection/changes/A.scala @@ -0,0 +1,3 @@ +object A { + def m: ({type T <: String})#T = ??? +} diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-projection/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/struct-projection/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-projection/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-projection/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/struct-projection/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-projection/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-projection/test b/sbt-dotty/sbt-test/source-dependencies/struct-projection/test new file mode 100644 index 000000000000..ea02287e6997 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-projection/test @@ -0,0 +1,4 @@ +> compile +$ copy-file changes/A.scala A.scala +# Compilation of B.scala should fail because type of A.m changed +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/A.scala b/sbt-dotty/sbt-test/source-dependencies/struct-usage/A.scala new file mode 100644 index 000000000000..b295547546c4 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-usage/A.scala @@ -0,0 +1,3 @@ +object A { + def x: { def q: Int } = sys.error("not important") +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala b/sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala new file mode 100644 index 000000000000..0d37132f1458 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala @@ -0,0 +1,3 @@ +object B { + val y: Int = A.x.q +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/struct-usage/changes/A.scala new file mode 100644 index 000000000000..00841314fa55 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-usage/changes/A.scala @@ -0,0 +1,3 @@ +object A { + def x: { def q: String } = sys.error("not important") +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/struct-usage/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-usage/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/struct-usage/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-usage/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/test b/sbt-dotty/sbt-test/source-dependencies/struct-usage/test new file mode 100644 index 000000000000..751cde01bc62 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct-usage/test @@ -0,0 +1,5 @@ +> compile + +$ copy-file changes/A.scala A.scala + +-> compile \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/A.scala b/sbt-dotty/sbt-test/source-dependencies/struct/A.scala new file mode 100644 index 000000000000..d17a6e20a2c1 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct/A.scala @@ -0,0 +1,3 @@ +object A { + def x: Int = 3 +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/B.scala b/sbt-dotty/sbt-test/source-dependencies/struct/B.scala new file mode 100644 index 000000000000..6355687275f0 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct/B.scala @@ -0,0 +1,4 @@ +object B { + def onX(m: { def x: Int } ) = + m.x +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/C.scala b/sbt-dotty/sbt-test/source-dependencies/struct/C.scala new file mode 100644 index 000000000000..413cd6d636cd --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct/C.scala @@ -0,0 +1,4 @@ +object C { + def main(args: Array[String]) = + println(B.onX(A)) +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/struct/changes/A.scala new file mode 100644 index 000000000000..dc9bbd3c07d5 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct/changes/A.scala @@ -0,0 +1,3 @@ +object A { + def x: Byte = 3 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/struct/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/struct/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/test b/sbt-dotty/sbt-test/source-dependencies/struct/test new file mode 100644 index 000000000000..72a7a8ebd654 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/struct/test @@ -0,0 +1,9 @@ +# Marked as pending because name hashing doesn't support structural types +# in some cases. See: https://github.com/sbt/sbt/issues/1545 + +> compile + +# modify A.scala so that it does not conform to the structural type in B.scala +$ copy-file changes/A.scala A.scala + +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt new file mode 100644 index 000000000000..eb7dacf3414f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt @@ -0,0 +1,14 @@ +lazy val commonSettings = Seq( + logLevel := Level.Debug +) +lazy val provider = project.settings(commonSettings) +lazy val use = project.settings(commonSettings).dependsOn(provider) + +InputKey[Unit]("check-number-of-compiler-iterations") <<= inputTask { (argTask: TaskKey[Seq[String]]) => + (argTask, compile in Compile in use) map { (args: Seq[String], a: sbt.inc.Analysis) => + assert(args.size == 1) + val expectedIterationsNumber = args(0).toInt + assert(a.compilations.allCompilations.size == expectedIterationsNumber, + "a.compilations.allCompilations.size = %d (expected %d)".format(a.compilations.allCompilations.size, expectedIterationsNumber)) + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A1.scala b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A1.scala new file mode 100644 index 000000000000..fdd5b55b9c78 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A1.scala @@ -0,0 +1,4 @@ +// add a comment to trigger a recompilation of A.scala, this should not trigger a recompilation of B.scala +class A { + class Inner +} diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A2.scala b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A2.scala new file mode 100644 index 000000000000..93226f59e491 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/changes/A2.scala @@ -0,0 +1,5 @@ +class A { + class Inner { + def foo: Int = 187 + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending new file mode 100644 index 000000000000..ee782c14ca26 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending @@ -0,0 +1,9 @@ +> compile + +$ copy-file changes/A1.scala provider/A.scala +> compile +> check-number-of-compiler-iterations 1 + +$ copy-file changes/A2.scala provider/A.scala +> compile +> check-number-of-compiler-iterations 1 diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/provider/A.scala b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/provider/A.scala new file mode 100644 index 000000000000..6e013e61e1a1 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/provider/A.scala @@ -0,0 +1,3 @@ +class A { + class Inner +} diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/use/B.scala b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/use/B.scala new file mode 100644 index 000000000000..d895226ce25e --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/use/B.scala @@ -0,0 +1,4 @@ +class B extends A { + // introduce dependency on Inner + def inner: Inner = null +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-val/changes/Base.scala b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/changes/Base.scala new file mode 100644 index 000000000000..b497cd62e871 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/changes/Base.scala @@ -0,0 +1,8 @@ +package foo + +import scala.util.Random + +trait Base { + private val myRandom = Random.nextInt(100) + def somePublicMethod(): Int = 123 +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-val/pending b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/pending new file mode 100644 index 000000000000..930e6cfd5f4b --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/pending @@ -0,0 +1,3 @@ +> run +$ copy-file changes/Base.scala src/main/scala/foo/Base.scala +> run \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/Base.scala b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/Base.scala new file mode 100644 index 000000000000..7301d4d2bdb0 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/Base.scala @@ -0,0 +1,5 @@ +package foo + +trait Base { + def somePublicMethod(): Int = 123 +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/TestApp.scala b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/TestApp.scala new file mode 100644 index 000000000000..d38e195be246 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/src/main/scala/foo/TestApp.scala @@ -0,0 +1,5 @@ +package foo + +object TestApp extends App with Base{ + println("OK") +} \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/A.scala b/sbt-dotty/sbt-test/source-dependencies/transitive-class/A.scala new file mode 100644 index 000000000000..68c5796a7c6b --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/A.scala @@ -0,0 +1 @@ +abstract class A diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/BC.scala b/sbt-dotty/sbt-test/source-dependencies/transitive-class/BC.scala new file mode 100644 index 000000000000..150a8f195a9f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/BC.scala @@ -0,0 +1,2 @@ +class B extends A +class C extends B diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/D.scala b/sbt-dotty/sbt-test/source-dependencies/transitive-class/D.scala new file mode 100644 index 000000000000..08ebf2e9608c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/D.scala @@ -0,0 +1,4 @@ +class D extends C +object Hello extends App { + new D +} diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/transitive-class/changes/A.scala new file mode 100644 index 000000000000..a02e9e5db4e7 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/changes/A.scala @@ -0,0 +1,3 @@ +abstract class A { + def foo: String = "" +} diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/transitive-class/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/transitive-class/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/test b/sbt-dotty/sbt-test/source-dependencies/transitive-class/test new file mode 100644 index 000000000000..b4847740f4cf --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/test @@ -0,0 +1,3 @@ +> compile +$ copy-file changes/A.scala A.scala +> checkRecompilations 2 A B C D Hello diff --git a/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/A.scala b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/A.scala new file mode 100644 index 000000000000..7ff41856ca07 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/A.scala @@ -0,0 +1,6 @@ +abstract class A { + val t: AnyRef + object X { + def foo: t.type = t + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/B.scala b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/B.scala new file mode 100644 index 000000000000..7ba16a6f2ceb --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/B.scala @@ -0,0 +1,3 @@ +class B extends A { + val t: String = "b" +} diff --git a/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/C.scala b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/C.scala new file mode 100644 index 000000000000..00ebd17d5fdf --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/C.scala @@ -0,0 +1,3 @@ +object C extends B { + val proxy: String = t +} diff --git a/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/changes/B2.scala b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/changes/B2.scala new file mode 100644 index 000000000000..d72933d9b60f --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/changes/B2.scala @@ -0,0 +1,3 @@ +class B extends A { + val t: Int = 1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/test b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/test new file mode 100644 index 000000000000..134321021e63 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/type-member-nested-object/test @@ -0,0 +1,4 @@ +> compile +$ copy-file changes/B2.scala B.scala +# Compilation of D.scala should fail because B is no longer a subtype of A +-> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/Foo.scala b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/Foo.scala new file mode 100644 index 000000000000..1b99e3e20e2c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/Foo.scala @@ -0,0 +1,19 @@ +class Fooo { + // This one is problematic because of expanded names + private[Fooo] object Bar +} + +package issue127 { + class Foo { + private[Foo] object Bar + class Baz { + private[Baz] object Bazz + } + } + + object Foo { + private[issue127] class Bippy + // This one is problematic because of expanded names + private[issue127] object Bippy + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +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"), + scalacOptions += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/test b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/test new file mode 100644 index 000000000000..e3d1046bf1bb --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/unexpanded-names/test @@ -0,0 +1,2 @@ +# See https://github.com/sbt/zinc/issues/127 +> compile \ No newline at end of file From 97c5d92a5a809f77b8197424be0c99ac70ca179d Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Fri, 9 Mar 2018 15:19:42 +0100 Subject: [PATCH 076/101] Workaround the broken hashCode of api.* classes When adding a single field to `Type`, incremental compilation using Scala 2.12 was compiling 1 file, then 12 files, then stopped. But incremental compilation with Dotty did not stop until the whole project was recompiled, this happened because lookups in the `refinedTypeCache` failed, which I tracked down to sbt-contraband generating broken hashCode implementations (https://github.com/sbt/contraband/issues/119). We work around this by using a ListMap instead of a HashMap. --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index b114520f59d9..b729362146c9 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -137,8 +137,11 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder /** This cache is necessary to avoid unstable name hashing when `typeCache` is present, * see the comment in the `RefinedType` case in `computeType` * The cache key is (api of RefinedType#parent, api of RefinedType#refinedInfo). - */ - private[this] val refinedTypeCache = new mutable.HashMap[(api.Type, api.Definition), api.Structure] + */ + // FIXME: This should be a HashMap but cannot be until the fix for + // https://github.com/sbt/contraband/issues/119 is part of a released version + // of sbt, until then we cannot rely on the hashCode method of the api.* classes. + private[this] val refinedTypeCache = new mutable.ListMap[(api.Type, api.Definition), api.Structure] private[this] val allNonLocalClassesInSrc = new mutable.HashSet[xsbti.api.ClassLike] private[this] val _mainClasses = new mutable.HashSet[String] From 950735d05a3c4e0446489bd1d30921d1956d7674 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 9 Mar 2018 16:10:36 +0100 Subject: [PATCH 077/101] Fix/Disable newly added tests TODO: implement these functionalities for scripted tests: - checkRecompilations - checkClasses - checkDependencies - checkProducts --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 2 +- .../anon-java-scala-class/{test => disabled} | 2 ++ .../check-classes/{test => disabled} | 2 ++ .../check-dependencies/{test => disabled} | 2 ++ .../check-products/{test => disabled} | 2 ++ .../check-recompilations/{test => disabled} | 2 ++ .../class-based-inheritance/{test => disabled} | 2 ++ .../class-based-memberRef/{test => disabled} | 2 ++ .../constructors-unrelated/build.sbt | 12 ++++++++++++ .../java-inner/{test => disabled} | 2 ++ .../{test => disabled} | 2 ++ .../local-class-inheritance/{test => disabled} | 2 ++ .../source-dependencies/naha-synthetic/A.scala | 1 - .../source-dependencies/naha-synthetic/B.scala | 1 - .../source-dependencies/naha-synthetic/build.sbt | 5 ----- .../naha-synthetic/changes/A.scala | 1 - .../naha-synthetic/project/DottyInjectedPlugin.scala | 12 ------------ .../naha-synthetic/project/plugins.sbt | 1 - .../sbt-test/source-dependencies/naha-synthetic/test | 5 ----- .../source-dependencies/nested-type-params/test | 7 +++++-- .../recorded-products/{test => disabled} | 2 ++ .../source-dependencies/struct-usage/B.scala | 2 ++ .../struct-usage/{test => pending} | 0 .../sbt-test/source-dependencies/struct/B.scala | 2 ++ .../source-dependencies/struct/{test => disabled} | 0 .../trait-private-val/{pending => test} | 0 .../transitive-class/{test => disabled} | 2 ++ 27 files changed, 46 insertions(+), 29 deletions(-) rename sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/{test => disabled} (94%) rename sbt-dotty/sbt-test/source-dependencies/check-classes/{test => disabled} (52%) rename sbt-dotty/sbt-test/source-dependencies/check-dependencies/{test => disabled} (50%) rename sbt-dotty/sbt-test/source-dependencies/check-products/{test => disabled} (60%) rename sbt-dotty/sbt-test/source-dependencies/check-recompilations/{test => disabled} (80%) rename sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/{test => disabled} (95%) rename sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/{test => disabled} (91%) create mode 100644 sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt rename sbt-dotty/sbt-test/source-dependencies/java-inner/{test => disabled} (76%) rename sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/{test => disabled} (94%) rename sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/{test => disabled} (95%) delete mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala delete mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala delete mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt delete mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala delete mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala delete mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt delete mode 100644 sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test rename sbt-dotty/sbt-test/source-dependencies/recorded-products/{test => disabled} (92%) rename sbt-dotty/sbt-test/source-dependencies/struct-usage/{test => pending} (100%) rename sbt-dotty/sbt-test/source-dependencies/struct/{test => disabled} (100%) rename sbt-dotty/sbt-test/source-dependencies/trait-private-val/{pending => test} (100%) rename sbt-dotty/sbt-test/source-dependencies/transitive-class/{test => disabled} (68%) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index b729362146c9..f5c80e538f5a 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -428,7 +428,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // that some API changed when it didn't, leading to overcompilation // (recompiling more things than what is needed for incremental // compilation to be correct). - val prefix = if (sym.owner.is(Package)) + val prefix = if (sym.maybeOwner.is(Package)) // { type T } here T does not have an owner sym.owner.thisType else tp.prefix diff --git a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/test b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/disabled similarity index 94% rename from sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/test rename to sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/disabled index 167accc3012d..c4a216c9a182 100644 --- a/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/test +++ b/sbt-dotty/sbt-test/source-dependencies/anon-java-scala-class/disabled @@ -1,3 +1,5 @@ +# TODO: Implement checkRecompilations + # Verifies if dependencies introduced by Java inheritance by local classes are handled correctly. # See sbt-test 'local-class-inheritance' for a similar test in Scala. diff --git a/sbt-dotty/sbt-test/source-dependencies/check-classes/test b/sbt-dotty/sbt-test/source-dependencies/check-classes/disabled similarity index 52% rename from sbt-dotty/sbt-test/source-dependencies/check-classes/test rename to sbt-dotty/sbt-test/source-dependencies/check-classes/disabled index 07102eb11c46..44f8ea3685a8 100644 --- a/sbt-dotty/sbt-test/source-dependencies/check-classes/test +++ b/sbt-dotty/sbt-test/source-dependencies/check-classes/disabled @@ -1,2 +1,4 @@ +# TODO: Implement checkClasses + > compile > checkClasses A.scala: A diff --git a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/test b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/disabled similarity index 50% rename from sbt-dotty/sbt-test/source-dependencies/check-dependencies/test rename to sbt-dotty/sbt-test/source-dependencies/check-dependencies/disabled index dffaeef47e2b..13458f266160 100644 --- a/sbt-dotty/sbt-test/source-dependencies/check-dependencies/test +++ b/sbt-dotty/sbt-test/source-dependencies/check-dependencies/disabled @@ -1,3 +1,5 @@ +# TODO: implement checkDependencies + > compile > checkDependencies A: B C \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-products/test b/sbt-dotty/sbt-test/source-dependencies/check-products/disabled similarity index 60% rename from sbt-dotty/sbt-test/source-dependencies/check-products/test rename to sbt-dotty/sbt-test/source-dependencies/check-products/disabled index a36de2f35fac..23a04dd3dc4f 100644 --- a/sbt-dotty/sbt-test/source-dependencies/check-products/test +++ b/sbt-dotty/sbt-test/source-dependencies/check-products/disabled @@ -1,2 +1,4 @@ +# TODO: implement check-products + > compile > checkProducts A.scala: A.class A$.class \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/test b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/disabled similarity index 80% rename from sbt-dotty/sbt-test/source-dependencies/check-recompilations/test rename to sbt-dotty/sbt-test/source-dependencies/check-recompilations/disabled index 60220ed86e57..9449b39b0266 100644 --- a/sbt-dotty/sbt-test/source-dependencies/check-recompilations/test +++ b/sbt-dotty/sbt-test/source-dependencies/check-recompilations/disabled @@ -1,3 +1,5 @@ +# TODO: Implement checkRecompilations + > compile $ copy-file changes/A.scala A.scala diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/test b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/disabled similarity index 95% rename from sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/test rename to sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/disabled index 56f649bedd4d..d8506accf74f 100644 --- a/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/test +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-inheritance/disabled @@ -1,3 +1,5 @@ +# TODO: implement checkRecompilations + # Test for class-based invalidation of dependencies # by inheritance. The source file A.scala defines # A and A2 classes. The B.scala inherits from A2 but diff --git a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/test b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/disabled similarity index 91% rename from sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/test rename to sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/disabled index 83b615b90c47..c0ec7f6f0f5c 100644 --- a/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/test +++ b/sbt-dotty/sbt-test/source-dependencies/class-based-memberRef/disabled @@ -1,3 +1,5 @@ +# TODO: Implement checkRecompilations + # Test for class-based invalidation of dependencies by member reference # This test checks if name hashes are tracked at the class level so # only classes that depend on an API of a modified class are invalidated diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt new file mode 100644 index 000000000000..d7524d433978 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt @@ -0,0 +1,12 @@ +import complete.DefaultParsers._ + +val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") + +checkIterations := { + val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] + + val expected: Int = (Space ~> NatBasic).parsed + val actual: Int = analysis.compilations.allCompilations.size + assert(expected == actual, s"Expected $expected compilations, got $actual") +} + diff --git a/sbt-dotty/sbt-test/source-dependencies/java-inner/test b/sbt-dotty/sbt-test/source-dependencies/java-inner/disabled similarity index 76% rename from sbt-dotty/sbt-test/source-dependencies/java-inner/test rename to sbt-dotty/sbt-test/source-dependencies/java-inner/disabled index 3300a912beae..1ab92f1e7e65 100644 --- a/sbt-dotty/sbt-test/source-dependencies/java-inner/test +++ b/sbt-dotty/sbt-test/source-dependencies/java-inner/disabled @@ -1,3 +1,5 @@ +# TODO: Implement checkProducts, checkDependencies + > compile > checkProducts A.java: A.class A$B.class > checkProducts C.java: C.class diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/test b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/disabled similarity index 94% rename from sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/test rename to sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/disabled index 167accc3012d..c4a216c9a182 100644 --- a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/test +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance-from-java/disabled @@ -1,3 +1,5 @@ +# TODO: Implement checkRecompilations + # Verifies if dependencies introduced by Java inheritance by local classes are handled correctly. # See sbt-test 'local-class-inheritance' for a similar test in Scala. diff --git a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/test b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/disabled similarity index 95% rename from sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/test rename to sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/disabled index 8345c0764058..2feb6c3c5dc9 100644 --- a/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/test +++ b/sbt-dotty/sbt-test/source-dependencies/local-class-inheritance/disabled @@ -1,3 +1,5 @@ +# TODO: Implement checkRecompilations + # Verifies if dependencies introduced by inheritance by local classes are handled correctly. # They are different from regular inheritance dependencies because they should not be # invalidated transitively, see: https://github.com/sbt/sbt/issues/1104#issuecomment-169146039 diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala deleted file mode 100644 index acafe2da159d..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/A.scala +++ /dev/null @@ -1 +0,0 @@ -case class A(a: Int) diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala deleted file mode 100644 index 2c4519ab3a1c..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/B.scala +++ /dev/null @@ -1 +0,0 @@ -class B { def test(a: A) = a.copy() } diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt deleted file mode 100644 index cd5970b1cf89..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/build.sbt +++ /dev/null @@ -1,5 +0,0 @@ -lazy val root = (project in file(".")). - settings( - scalaVersion := "2.11.7", - incOptions := incOptions.value.withIncludeSynthToNameHashing(true) - ) diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala deleted file mode 100644 index 57eb90ceef54..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/changes/A.scala +++ /dev/null @@ -1 +0,0 @@ -case class A(a: Int) { private def copy = ??? } diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala deleted file mode 100644 index ce3d46d79921..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/DottyInjectedPlugin.scala +++ /dev/null @@ -1,12 +0,0 @@ -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"), - scalacOptions += "-language:Scala2" - ) -} diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt deleted file mode 100644 index c17caab2d98c..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test b/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test deleted file mode 100644 index 4896f0dcc042..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/naha-synthetic/test +++ /dev/null @@ -1,5 +0,0 @@ -> compile - -$ copy-file changes/A.scala A.scala - --> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/test b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/test index 0c3e2ab7f68c..91ef01d64823 100644 --- a/sbt-dotty/sbt-test/source-dependencies/nested-type-params/test +++ b/sbt-dotty/sbt-test/source-dependencies/nested-type-params/test @@ -3,6 +3,9 @@ $ copy-file changes/Providers.scala Providers.scala $ copy-file changes/Bar.scala Bar.scala --> compile # This should compile +# This should compile +> compile + +# Make sure that clean compile is fine > clean -> compile # Make sure that clean compile is fine \ No newline at end of file +> compile diff --git a/sbt-dotty/sbt-test/source-dependencies/recorded-products/test b/sbt-dotty/sbt-test/source-dependencies/recorded-products/disabled similarity index 92% rename from sbt-dotty/sbt-test/source-dependencies/recorded-products/test rename to sbt-dotty/sbt-test/source-dependencies/recorded-products/disabled index 300da70fe8f8..60dd3bd42cc9 100644 --- a/sbt-dotty/sbt-test/source-dependencies/recorded-products/test +++ b/sbt-dotty/sbt-test/source-dependencies/recorded-products/disabled @@ -1,3 +1,5 @@ +# TODO: Implement checkProducts + > compile > checkProducts DefaultPkg.scala: A.class B$.class B.class > checkProducts Nested.scala: foo/bar/Outer$InnerC$T.class foo/bar/Outer$InnerO$B$.class foo/bar/Outer$InnerO$.class foo/bar/Outer$X.class foo/bar/Outer$.class foo/bar/Outer.class foo/bar/Outer$InnerC.class foo/bar/Outer$X$Y$.class foo/bar/Outer$InnerO$A.class diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala b/sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala index 0d37132f1458..b32b6c72097e 100644 --- a/sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala +++ b/sbt-dotty/sbt-test/source-dependencies/struct-usage/B.scala @@ -1,3 +1,5 @@ +import scala.reflect.Selectable.reflectiveSelectable + object B { val y: Int = A.x.q } \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/struct-usage/test b/sbt-dotty/sbt-test/source-dependencies/struct-usage/pending similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/struct-usage/test rename to sbt-dotty/sbt-test/source-dependencies/struct-usage/pending diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/B.scala b/sbt-dotty/sbt-test/source-dependencies/struct/B.scala index 6355687275f0..901e7deeff67 100644 --- a/sbt-dotty/sbt-test/source-dependencies/struct/B.scala +++ b/sbt-dotty/sbt-test/source-dependencies/struct/B.scala @@ -1,3 +1,5 @@ +import scala.reflect.Selectable.reflectiveSelectable + object B { def onX(m: { def x: Int } ) = m.x diff --git a/sbt-dotty/sbt-test/source-dependencies/struct/test b/sbt-dotty/sbt-test/source-dependencies/struct/disabled similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/struct/test rename to sbt-dotty/sbt-test/source-dependencies/struct/disabled diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-private-val/pending b/sbt-dotty/sbt-test/source-dependencies/trait-private-val/test similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/trait-private-val/pending rename to sbt-dotty/sbt-test/source-dependencies/trait-private-val/test diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-class/test b/sbt-dotty/sbt-test/source-dependencies/transitive-class/disabled similarity index 68% rename from sbt-dotty/sbt-test/source-dependencies/transitive-class/test rename to sbt-dotty/sbt-test/source-dependencies/transitive-class/disabled index b4847740f4cf..2e4cdfcc052e 100644 --- a/sbt-dotty/sbt-test/source-dependencies/transitive-class/test +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-class/disabled @@ -1,3 +1,5 @@ > compile $ copy-file changes/A.scala A.scala + +# TODO: implement checkRecompilations > checkRecompilations 2 A B C D Hello From 6d339d0cf7bdaf3ff7656dd61fe537a8be2d3d27 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 9 Mar 2018 18:46:20 +0100 Subject: [PATCH 078/101] Port Unit test from latest Zinc --- .../test/xsbt/DependencySpecification.scala | 210 ++++++---- .../test/xsbt/ExtractAPISpecification.scala | 220 +++++++--- .../xsbt/ExtractUsedNamesSpecification.scala | 385 ++++++++++++------ 3 files changed, 543 insertions(+), 272 deletions(-) diff --git a/sbt-bridge/test/xsbt/DependencySpecification.scala b/sbt-bridge/test/xsbt/DependencySpecification.scala index 0fbd285ee35d..639be7e0a7d2 100644 --- a/sbt-bridge/test/xsbt/DependencySpecification.scala +++ b/sbt-bridge/test/xsbt/DependencySpecification.scala @@ -1,92 +1,156 @@ -/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/DependencySpecification.scala */ package xsbt -import org.junit.runner.RunWith -import xsbti.api.ClassLike -import xsbti.api.Def -import xsbt.api.SameAPI -import org.specs2.mutable.Specification -import org.specs2.runner.JUnitRunner - import xsbti.TestCallback.ExtractedClassDependencies -@RunWith(classOf[JUnitRunner]) -class DependencySpecification extends Specification { +import org.junit.Test +import org.junit.Assert._ + +class DependencySpecification { - "Extracted source dependencies from public members" in { + @Test + def extractedClassDependenciesFromPublicMembers = { val classDependencies = extractClassDependenciesPublic val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance - memberRef("A") === Set.empty - inheritance("A") === Set.empty - memberRef("B") === Set("A", "D") - inheritance("B") === Set("D") - memberRef("C") === Set("A") - inheritance("C") === Set.empty - memberRef("D") === Set.empty - inheritance("D") === Set.empty - memberRef("E") === Set.empty - inheritance("E") === Set.empty - memberRef("F") === Set("A", "B", "C", "D", "E", "G") - inheritance("F") === Set("A", "E") - memberRef("H") === Set("B", "E", "G") + assertEquals(memberRef("A"), Set.empty) + assertEquals(inheritance("A"), Set.empty) + assertEquals(memberRef("B"), Set("A", "D")) + assertEquals(inheritance("B"), Set("D")) + assertEquals(memberRef("C"), Set("A")) + assertEquals(inheritance("C"), Set.empty) + assertEquals(memberRef("D"), Set.empty) + assertEquals(inheritance("D"), Set.empty) + assertEquals(memberRef("E"), Set.empty) + assertEquals(inheritance("E"), Set.empty) + assertEquals(memberRef("F"), Set("A", "B", "D", "E", "G", "C")) // C is the underlying type of MyC + assertEquals(inheritance("F"), Set("A", "E")) + assertEquals(memberRef("H"), Set("B", "E", "G")) // aliases and applied type constructors are expanded so we have inheritance dependency on B - inheritance("H") === Set("B", "E") + assertEquals(inheritance("H"), Set("B", "E")) } - "Extracted source dependencies from private members" in { - val classDependencies = extractClassDependenciesPrivate + @Test + def extractedClassDependenciesFromLocalMembers = { + val classDependencies = extractClassDependenciesLocal val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance - memberRef("A") === Set.empty - inheritance("A") === Set.empty - memberRef("B") === Set.empty - inheritance("B") === Set.empty - memberRef("C.Inner1") === Set("A") - inheritance("C.Inner1") === Set("A") - memberRef("D._$Inner2") === Set("B") - inheritance("D._$Inner2") === Set("B") + val localInheritance = classDependencies.localInheritance + assertEquals(memberRef("A"), Set.empty) + assertEquals(inheritance("A"), Set.empty) + assertEquals(memberRef("B"), Set.empty) + assertEquals(inheritance("B"), Set.empty) + assertEquals(memberRef("C.Inner1"), Set("A")) + assertEquals(inheritance("C.Inner1"), Set("A")) + assertEquals(memberRef("D"), Set("B")) + assertEquals(inheritance("D"), Set.empty) + assertEquals(localInheritance("D"), Set("B")) + assertEquals(memberRef("E"), Set("B")) + assertEquals(inheritance("E"), Set.empty) + assertEquals(localInheritance("E"), Set("B")) } - "Extracted source dependencies with trait as first parent" in { + @Test + def extractedClassDependenciesWithTraitAsFirstParent = { val classDependencies = extractClassDependenciesTraitAsFirstPatent val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance - memberRef("A") === Set.empty - inheritance("A") === Set.empty - memberRef("B") === Set("A") - inheritance("B") === Set("A") + assertEquals(memberRef("A"), Set.empty) + assertEquals(inheritance("A"), Set.empty) + assertEquals(memberRef("B"), Set("A")) + assertEquals(inheritance("B"), Set("A")) // verify that memberRef captures the oddity described in documentation of `Relations.inheritance` // we are mainly interested whether dependency on A is captured in `memberRef` relation so // the invariant that says that memberRef is superset of inheritance relation is preserved - memberRef("C") === Set("A", "B") - inheritance("C") === Set("A", "B") + assertEquals(memberRef("C"), Set("A", "B")) + assertEquals(inheritance("C"), Set("A", "B")) // same as above but indirect (C -> B -> A), note that only A is visible here - memberRef("D") === Set("A", "C") - inheritance("D") === Set("A", "C") + assertEquals(memberRef("D"), Set("A", "C")) + assertEquals(inheritance("D"), Set("A", "C")) } - /* - "Extracted source dependencies from macro arguments" in { - val classDependencies = extractClassDependenciesFromMacroArgument + @Test + def extractedClassDependenciesFromARefinement = { + val srcFoo = + "object Outer {\n class Inner { type Xyz }\n\n type TypeInner = Inner { type Xyz = Int }\n}" + val srcBar = "object Bar {\n def bar: Outer.TypeInner = null\n}" + + val compilerForTesting = new ScalaCompilerForUnitTesting + val classDependencies = + compilerForTesting.extractDependenciesFromSrcs(srcFoo, srcBar) + val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance + assertEquals(memberRef("Outer"), Set.empty) + assertEquals(inheritance("Outer"), Set.empty) + assertEquals(memberRef("Bar"), Set("Outer", "Outer$.Inner")) + assertEquals(inheritance("Bar"), Set.empty) + } + + @Test + def extractedClassDependenciesOnAnObjectCorrectly = { + val srcA = + """object A { + | def foo = { B; () } + |}""".stripMargin + val srcB = "object B" + + val compilerForTesting = new ScalaCompilerForUnitTesting + val classDependencies = + compilerForTesting.extractDependenciesFromSrcs(srcA, srcB) - memberRef("A") === Set("B", "C") - inheritance("A") === Set.empty - memberRef("B") === Set.empty - inheritance("B") === Set.empty - memberRef("C") === Set.empty - inheritance("C") === Set.empty + val memberRef = classDependencies.memberRef + val inheritance = classDependencies.inheritance + assertEquals(memberRef("A"), Set("B")) + assertEquals(inheritance("A"), Set.empty) + assertEquals(memberRef("B"), Set.empty) + assertEquals(inheritance("B"), Set.empty) + } + + @Test + def extractedTopLevelImportDependencies = { + val srcA = + """ + |package abc + |object A { + | class Inner + |} + |class A2""".stripMargin + val srcB = "import abc.A; import abc.A.Inner; class B" + val srcC = "import abc.{A, A2}; class C" + val srcD = "import abc.{A2 => Foo}; class D" + val srcE = "import abc.A._; class E" + val srcF = "import abc._; class F" + val srcG = + """|package foo { + | package bar { + | import abc.A + | class G + | } + |} + """.stripMargin + val srcH = "class H { import abc.A }" + + val compilerForTesting = new ScalaCompilerForUnitTesting + val deps = compilerForTesting + .extractDependenciesFromSrcs(srcA, srcB, srcC, srcD, srcE, srcF, srcG, srcH) + .memberRef + + assertEquals(deps("A"), Set.empty) + assertEquals(deps("B"), Set("abc.A", "abc.A$.Inner")) + assertEquals(deps("C"), Set("abc.A", "abc.A2")) + assertEquals(deps("D"), Set("abc.A2")) + assertEquals(deps("E"), Set("abc.A")) + assertEquals(deps("F"), Set.empty) + assertEquals(deps("foo.bar.G"), Set("abc.A")) + assertEquals(deps("H"), Set("abc.A")) } - */ private def extractClassDependenciesPublic: ExtractedClassDependencies = { val srcA = "class A" val srcB = "class B extends D[A]" val srcC = """|class C { - | def a: A = null - |}""".stripMargin + | def a: A = null + |}""".stripMargin val srcD = "class D[T]" val srcE = "trait E[T]" val srcF = "trait F extends A with E[D[B]] { self: G.MyC => }" @@ -97,20 +161,21 @@ class DependencySpecification extends Specification { val srcH = "trait H extends G.T[Int] with (E[Int] @unchecked)" val compilerForTesting = new ScalaCompilerForUnitTesting - val classDependencies = compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, - srcD, srcE, srcF, srcG, srcH) + val classDependencies = + compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, srcD, srcE, srcF, srcG, srcH) classDependencies } - private def extractClassDependenciesPrivate: ExtractedClassDependencies = { + private def extractClassDependenciesLocal: ExtractedClassDependencies = { val srcA = "class A" val srcB = "class B" val srcC = "class C { private class Inner1 extends A }" val srcD = "class D { def foo: Unit = { class Inner2 extends B } }" + val srcE = "class E { def foo: Unit = { new B {} } }" val compilerForTesting = new ScalaCompilerForUnitTesting val classDependencies = - compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, srcD) + compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, srcD, srcE) classDependencies } @@ -125,27 +190,4 @@ class DependencySpecification extends Specification { compilerForTesting.extractDependenciesFromSrcs(srcA, srcB, srcC, srcD) classDependencies } - - /* - private def extractClassDependenciesFromMacroArgument: ExtractedClassDependencies = { - val srcA = "class A { println(B.printTree(C.foo)) }" - val srcB = """ - |import scala.language.experimental.macros - |import scala.reflect.macros._ - |object B { - | def printTree(arg: Any) = macro printTreeImpl - | def printTreeImpl(c: Context)(arg: c.Expr[Any]): c.Expr[String] = { - | val argStr = arg.tree.toString - | val literalStr = c.universe.Literal(c.universe.Constant(argStr)) - | c.Expr[String](literalStr) - | } - |}""".stripMargin - val srcC = "object C { val foo = 1 }" - - val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) - val classDependencies = - compilerForTesting.extractDependenciesFromSrcs(List(Map('B -> srcB, 'C -> srcC), Map('A -> srcA))) - classDependencies - } - */ -} +} \ No newline at end of file diff --git a/sbt-bridge/test/xsbt/ExtractAPISpecification.scala b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala index 8d867511e899..15544ce1301a 100644 --- a/sbt-bridge/test/xsbt/ExtractAPISpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala @@ -1,45 +1,126 @@ -/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/ExtractAPISpecification.scala */ package xsbt -import org.junit.runner.RunWith import xsbti.api._ -import dotty.tools.dotc.sbt.DefaultShowAPI -import org.specs2.mutable.Specification -import org.specs2.runner.JUnitRunner +import xsbt.api.SameAPI -@RunWith(classOf[JUnitRunner]) -class ExtractAPISpecification extends Specification { +import org.junit.{ Test, Ignore } +import org.junit.Assert._ - "Existential types in method signatures" should { - "have stable names" in { stableExistentialNames } +class ExtractAPISpecification { + + @Test + def extractChildrenOfSealedClass = { + def compileAndGetFooClassApi(src: String): ClassLike = { + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src) + val FooApi = apis.find(_.name() == "Foo").get + FooApi + } + val src1 = + """|sealed abstract class Foo + |case class C1(x: Int) extends Foo + |""".stripMargin + val fooClassApi1 = compileAndGetFooClassApi(src1) + val src2 = + """|sealed abstract class Foo + |case class C1(x: Int) extends Foo + |case class C2(x: Int) extends Foo + |""".stripMargin + val fooClassApi2 = compileAndGetFooClassApi(src2) + assertFalse(SameAPI(fooClassApi1, fooClassApi2)) + } + + @Ignore + def extractDefinitionTypeOfPackageObject = { + val src = "package object foo".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src) + val Seq(fooClassApi) = apis.toSeq + assertEquals(fooClassApi.definitionType, DefinitionType.PackageModule) } - def stableExistentialNames: Boolean = { + @Test + def extractNestedClasses = { + val src = + """class A { + | class B + |}""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src).map(c => c.name -> c).toMap + assertEquals(apis.keys, Set("A", "A.B")) + } + + @Test + def extractLocalClasses = { + val src = + """class A + |class B + |class C { def foo: Unit = { class Inner2 extends B } } + |class D { def foo: Unit = { new B {} } }""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src).map(c => c.name -> c).toMap + assertEquals(apis.keys, Set("A", "B", "C", "D")) + } + + @Ignore + def extractFlatApiOfNestedClass = { + def compileAndGetFooClassApi(src: String): ClassLike = { + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src) + val FooApi = apis.find(_.name() == "Foo").get + FooApi + } + val src1 = + """class Foo { + | class A + |}""".stripMargin + val fooClassApi1 = compileAndGetFooClassApi(src1) + val src2 = + """class Foo { + | class A { + | def foo: Int = 123 + | } + |}""".stripMargin + val fooClassApi2 = compileAndGetFooClassApi(src2) + assertTrue(SameAPI(fooClassApi1, fooClassApi2)) + } + + @Test + def extractPivateClasses = { + val src = + """private class A + |class B { private class Inner1 extends A } + |""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src).map(c => c.name -> c).toMap + assertEquals(apis.keys, Set("A", "B", "B.Inner1")) + } + + @Test + def extractStableExistentialNames = { def compileAndGetFooMethodApi(src: String): Def = { val compilerForTesting = new ScalaCompilerForUnitTesting val sourceApi = compilerForTesting.extractApiFromSrc(src) - val FooApi = sourceApi.find(_.name() == "Foo").get.asInstanceOf[ClassLike] + val FooApi = sourceApi.find(_.name() == "Foo").get val fooMethodApi = FooApi.structure().declared().find(_.name == "foo").get fooMethodApi.asInstanceOf[Def] } val src1 = """ - |class Box[T] - |class Foo { - | def foo: Box[_] = null - | - }""".stripMargin + |class Box[T] + |class Foo { + | def foo: Box[_] = null + | + }""".stripMargin val fooMethodApi1 = compileAndGetFooMethodApi(src1) val src2 = """ - |class Box[T] - |class Foo { - | def bar: Box[_] = null - | def foo: Box[_] = null - |}""".stripMargin + |class Box[T] + |class Foo { + | def bar: Box[_] = null + | def foo: Box[_] = null + | + }""".stripMargin val fooMethodApi2 = compileAndGetFooMethodApi(src2) - - fooMethodApi1 == fooMethodApi2 - // Fails because xsbt.api is compiled with Scala 2.10 - // SameAPI.apply(fooMethodApi1, fooMethodApi2) + assertTrue("APIs are not the same.", SameAPI(fooMethodApi1, fooMethodApi2)) } /** @@ -47,45 +128,68 @@ class ExtractAPISpecification extends Specification { * is stable between compiling from source and unpickling. We compare extracted APIs of Global when Global * is compiled together with Namers or Namers is compiled first and then Global refers * to Namers by unpickling types from class files. - * - * See https://github.com/sbt/sbt/issues/2504 */ - "Self variable and no self type" in { - def selectNamer(api: Seq[Definition]): ClassLike = { - def selectClass(defs: Iterable[Definition], name: String): ClassLike = defs.collectFirst { - case cls: ClassLike if cls.name == name => cls - }.get - selectClass(api, "Namers.Namer") + @Ignore + def extractStableRepresentationOfSelfVariableThatHasNoSelfType = { + def selectNamer(apis: Seq[ClassLike]): ClassLike = { + // TODO: this doesn't work yet because inherited classes are not extracted + apis.find(_.name == "Global.Foo.Namer").get } val src1 = """|class Namers { - | class Namer { thisNamer => } - |} - |""".stripMargin + | class Namer { thisNamer => } + |} + |""".stripMargin val src2 = """|class Global { - | class Foo extends Namers - |} - |""".stripMargin + | class Foo extends Namers + |} + |""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting - val apis = compilerForTesting.extractApisFromSrcs(reuseCompilerInstance = false)(List(src1, src2), List(src2)) + val apis = + compilerForTesting.extractApisFromSrcs(reuseCompilerInstance = false)(List(src1, src2), + List(src2)) val _ :: src2Api1 :: src2Api2 :: Nil = apis.toList val namerApi1 = selectNamer(src2Api1) val namerApi2 = selectNamer(src2Api2) + assertTrue(SameAPI(namerApi1, namerApi2)) + } - DefaultShowAPI(namerApi1) == DefaultShowAPI(namerApi2) - // Fails because xsbt.api is compiled with Scala 2.10 - // SameAPI(namerApi1, namerApi2) + @Ignore + def extractDifferentRepresentationForAnInheritedClass = { + val src = + """|class A[T] { + | abstract class AA { def t: T } + |} + |class B extends A[Int] + """.stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src).map(a => a.name -> a).toMap + assertEquals(apis.keySet, Set("A", "A.AA", "B", "B.AA")) + assertNotEquals(apis("A.AA"), apis("B.AA")) + } + + @Test + def handlePackageObjectsAndTypeCompanions = { + val src = + """|package object abc { + | type BuildInfoKey = BuildInfoKey.Entry[_] + | object BuildInfoKey { + | sealed trait Entry[A] + | } + |} + """.stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val apis = compilerForTesting.extractApiFromSrc(src).map(a => a.name -> a).toMap + assertEquals(apis.keySet, Set("abc.package", "abc.package$.BuildInfoKey", "abc.package$.BuildInfoKey$.Entry")) } /** * Checks if self type is properly extracted in various cases of declaring a self type - * with our without a self variable. + * with or without a self variable. */ - "Self type" in { - def collectFirstClass(defs: Iterable[Definition]): ClassLike = defs.collectFirst { - case c: ClassLike => c - }.get + @Ignore + def representASelfTypeCorrectly = { val srcX = "trait X" val srcY = "trait Y" val srcC1 = "class C1 { this: C1 => }" @@ -94,21 +198,19 @@ class ExtractAPISpecification extends Specification { val srcC4 = "class C4 { thisC: X => }" val srcC5 = "class C5 extends AnyRef with X with Y { self: X with Y => }" val srcC6 = "class C6 extends AnyRef with X { self: X with Y => }" - // val srcC7 = "class C7 { _ => }" // DOTTY: Syntax not supported + // val srcC7 = "class C7 { _ => }" val srcC8 = "class C8 { self => }" val compilerForTesting = new ScalaCompilerForUnitTesting - val apis = compilerForTesting.extractApisFromSrcs(reuseCompilerInstance = true)( - List(srcX, srcY, srcC1, srcC2, srcC3, srcC4, srcC5, srcC6, srcC8) - ).map(collectFirstClass) - val emptyType = EmptyType.create() + val apis = compilerForTesting + .extractApisFromSrcs(reuseCompilerInstance = true)( + List(srcX, srcY, srcC1, srcC2, srcC3, srcC4, srcC5, srcC6, srcC8) + ) + .map(_.head) + val emptyType = EmptyType.of() def hasSelfType(c: ClassLike): Boolean = c.selfType != emptyType val (withSelfType, withoutSelfType) = apis.partition(hasSelfType) - // DOTTY: In the scalac ExtractAPI phase, the self-type is only - // extracted if it differs from the type of the class for stability - // reasons. This isn't necessary in dotty because we always pickle - // the self type. - withSelfType.map(_.name).toSet === Set("C1", "C2", "C3", "C4", "C5", "C6", "C8") - withoutSelfType.map(_.name).toSet === Set("X", "Y") + assertEquals(withSelfType.map(_.name).toSet, Set("C3", "C4", "C5", "C6")) + assertEquals(withoutSelfType.map(_.name).toSet, Set("X", "Y", "C1", "C2", "C8")) } } diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index eda9533fcee4..75fbbb110af7 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -1,91 +1,103 @@ -/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/ExtractUsedNamesSpecification.scala */ package xsbt -import org.junit.runner.RunWith -import xsbti.api.ClassLike -import xsbti.api.Def -import xsbti.api.Package -import xsbt.api.SameAPI -import org.junit.runners.JUnit4 +import xsbti.UseScope -import org.specs2.mutable.Specification +import org.junit.{ Test, Ignore } +import org.junit.Assert._ -@RunWith(classOf[JUnit4]) -class ExtractUsedNamesSpecification extends Specification { +class ExtractUsedNamesSpecification { - /** - * Standard names that appear in every compilation unit that has any class - * definition. - */ - private val standardNames = Set( - // All class extend Object - "Object", - // All class have a default constructor called - "", - // the return type of the default constructor is Unit - "Unit" - ) + @Test + def extractImportedName = { + val src = """package a { class A } + |package b { + | import a.{A => A2} + |}""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) + val expectedNames = standardNames ++ Set("a", "A", "A2", "b") + // names used at top level are attributed to the first class defined in a compilation unit - "imported name" in { - val src = """ - |package a { class A } - |package b { - | import a.{A => A2} - |}""".stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting - val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) - val expectedNames = standardNames ++ Set("a", "A", "A2", "b") - usedNames("a.A") === expectedNames - } + assertEquals(usedNames("a.A"), expectedNames) + } // test covers https://github.com/gkossakowski/sbt/issues/6 - "names in type tree" in { - val srcA = """| - |package a { + @Test + def extractNameInTypeTree = { + val srcA = """|package a { | class A { | class C { class D } | } | class B[T] + |} + |package c { | class BB - |}""".stripMargin - val srcB = """| - |package b { - | abstract class X { + |} + | + |""".stripMargin + val srcB = """|package b { + | abstract class X { | def foo: a.A#C#D - | def bar: a.B[a.BB] + | def bar: a.B[c.BB] | } |}""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - // DOTTY: unlike the scalac sbt phase, this does not contain "X", I believe this is safe - // TODO: report issue against sbt suggesting that they do the same - val expectedNames = standardNames ++ Set("a", "A", "B", "C", "D", "b", "BB") - usedNames("b.X") === expectedNames + val expectedNames = standardNames ++ Set("a", "c", "A", "B", "C", "D", "b", "X", "BB") + assertEquals(usedNames("b.X"), expectedNames) } - // test for https://github.com/gkossakowski/sbt/issues/5 - "symbolic names" in { - val srcA = """| - |class A { - | def `=`: Int = 3 - |}""".stripMargin - val srcB = """| - |class B { - | def foo(a: A) = a.`=` - |}""".stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting - val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - - // DOTTY TODO: "Int" is not actually used, but we collect it because - // it's the inferred return type so it appears in a TypeTree - // We could avoid this by checking if the untyped tree has a return type - // but is it worth it? Revisit this after https://github.com/sbt/sbt/issues/1104 - // has landed. - val expectedNames = standardNames ++ Set("A", "a", "=", "Int") - usedNames("B") === expectedNames - } - - "extract names in the types of trees" in { + // test for https://github.com/gkossakowski/sbt/issues/5 + @Test + def extractSymbolicNames = { + val srcA = """|class A { + | def `=`: Int = 3 + |}""".stripMargin + val srcB = """|class B { + | def foo(a: A) = a.`=` + |}""".stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) + val expectedNames = standardNames ++ Set("A", "a", "B", "=", "Int") + assertEquals(usedNames("B"), expectedNames) + } + + @Test + def extractTypeNamesForObjectsDependingOnAbstractTypes = { + val srcA = + """abstract class A { + | type T + | object X { + | def foo(x: T): T = x + | } + |} + """.stripMargin + val srcB = "class B extends A { type T = Int }" + val srcC = "object C extends B" + val srcD = "object D { C.X.foo(12) }" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB, srcC, srcD) + val scalaVersion = scala.util.Properties.versionNumberString + // TODO: Find out what's making these types appear in 2.10 + // They don't come from type dependency traverser, but from `addSymbol` + val versionDependentNames = + if (scalaVersion.contains("2.10")) Set("Nothing", "Any") else Set() + val namesA = standardNames ++ Set("A") ++ versionDependentNames + val namesAX = standardNames ++ Set("X", "x", "T", "A") + val namesB = Set("B", "A", "Int", "A;init;", "scala") + val namesC = Set("B;init;", "C", "B") + val namesD = standardNames ++ Set("D", "C", "X", "foo", "Int", "T") + assertEquals(usedNames("A"), namesA) + assertEquals(usedNames("A.X"), namesAX) + assertEquals(usedNames("B"), namesB) + assertEquals(usedNames("C"), namesC) + assertEquals(usedNames("D"), namesD) + } + + // See source-dependencies/types-in-used-names-a for an example where + // this is required. + @Test + def extractUsedNamesInTypeOfTree = { val src1 = """|class X0 |class X1 extends X0 |class Y @@ -122,68 +134,183 @@ class ExtractUsedNamesSpecification extends Specification { |""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(src1, src2) - val expectedNames_lista = standardNames ++ Set("Test_lista", "Test_lista$", "B", "B$", "lista", "List", "A") - val expectedNames_at = standardNames ++ Set("Test_at", "Test_at$", "B", "B$", "at", "A", "T", "X0", "X1") - val expectedNames_as = standardNames ++ Set("Test_as", "Test_as$", "B", "B$", "as", "S", "Y") + val expectedNames_lista = standardNames ++ Set("Test_lista", "x", "B", "lista", "List", "A") + val expectedNames_at = standardNames ++ Set("Test_at", "x", "B", "at", "A", "T", "X0", "X1") + val expectedNames_as = standardNames ++ Set("Test_as", "x", "B", "as", "S", "Y") val expectedNames_foo = standardNames ++ Set("Test_foo", - "Test_foo$", - "B", - "B$", - "foo", - "M", - "N", - "Predef", - "Predef$", - "???", - "Nothing") + "x", + "B", + "foo", + "M", + "N", + "Predef", + "???", + "Nothing") val expectedNames_bar = standardNames ++ Set("Test_bar", - "Test_bar$", - "B", - "B$", - "bar", - "P1", - "P0", - "Predef", - "Predef$", - "???", - "Nothing") - usedNames("Test_lista") === expectedNames_lista - usedNames("Test_at") === expectedNames_at - usedNames("Test_as") === expectedNames_as - usedNames("Test_foo") === expectedNames_foo - usedNames("Test_bar") === expectedNames_bar + "x", + "B", + "bar", + "Param", + "P1", + "P0", + "Predef", + "???", + "Nothing") + assertEquals(usedNames("Test_lista"), expectedNames_lista) + assertEquals(usedNames("Test_at"), expectedNames_at) + assertEquals(usedNames("Test_as"), expectedNames_as) + assertEquals(usedNames("Test_foo"), expectedNames_foo) + assertEquals(usedNames("Test_bar"), expectedNames_bar) + } + + @Test + def extractUsedNamesFromExistential = { + val srcFoo = + """import scala.language.existentials + |class Foo { + | val foo: T forSome { type T <: Double } = ??? + |} + """.stripMargin + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcFoo) + val expectedNames = standardNames ++ Seq("Double", + "Foo", + "T", + "foo", + "scala", + "language", + "existentials", + "Nothing", + "???", + "Predef") + assertEquals(usedNames("Foo"), expectedNames) + } + + @Test + def extractUsedNamesFromRefinement = { + val srcFoo = + "object Outer {\n class Inner { type Xyz }\n\n type TypeInner = Inner { type Xyz = Int }\n}" + val srcBar = "object Bar {\n def bar: Outer.TypeInner = null\n}" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcFoo, srcBar) + val expectedNames = standardNames ++ Set("Bar", "Outer", "TypeInner", "Inner", "Xyz", "Int") + assertEquals(usedNames("Bar"), expectedNames) + } + + // test for https://github.com/gkossakowski/sbt/issues/3 + @Test + def extractUsedNamesFromSameCompilationUnit = { + val src = "class A { def foo: Int = 0; def bar: Int = foo }" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) + val expectedNames = standardNames ++ Set("A", "foo", "Int") + assertEquals(usedNames("A"), expectedNames) + } + + // pending test for https://issues.scala-lang.org/browse/SI-7173 + @Test + def extractUsedNamesOfConstants = { + val src = "class A { final val foo = 12; def bar: Int = foo }" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) + val expectedNames = standardNames ++ Set("A", "foo", "Int") + assertEquals(usedNames("A"), expectedNames) } - // test for https://github.com/gkossakowski/sbt/issues/3 - "used names from the same compilation unit" in { - val src = "class A { def foo: Int = 0; def bar: Int = foo }" - val compilerForTesting = new ScalaCompilerForUnitTesting - val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) - val expectedNames = standardNames ++ Set("A", "foo", "Int") - usedNames("A") === expectedNames - } - - // pending test for https://issues.scala-lang.org/browse/SI-7173 - "names of constants" in { - val src = "class A { final val foo = 12; def bar: Int = foo }" - val compilerForTesting = new ScalaCompilerForUnitTesting - val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) - val expectedNames = standardNames ++ Set("A", "foo", "Int") - usedNames("A") === expectedNames - } - - // pending test for https://github.com/gkossakowski/sbt/issues/4 - // TODO: we should fix it by having special treatment of `selectDynamic` and `applyDynamic` calls - "names from method calls on Dynamic" in { - val srcA = """|import scala.language.dynamics - |class A extends Dynamic { - | def selectDynamic(name: String): Int = name.length - |}""".stripMargin - val srcB = "class B { def foo(a: A): Int = a.bla }" - val compilerForTesting = new ScalaCompilerForUnitTesting - val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - val expectedNames = standardNames ++ Set("B", "A", "a", "Int", "selectDynamic", "bla") - usedNames("") === expectedNames - }.pendingUntilFixed("Call to Dynamic is desugared in type checker so Select nodes is turned into string literal.") - -} + // test for https://github.com/gkossakowski/sbt/issues/4 + // TODO: we should fix it by having special treatment of `selectDynamic` and `applyDynamic` calls + @Test + def extractNamesFromMethodCallOnDynamic = { + val srcA = """|import scala.language.dynamics + |class A extends Dynamic { + | def selectDynamic(name: String): Int = name.length + |}""".stripMargin + val srcB = "class B { def foo(a: A): Int = a.bla }" + val compilerForTesting = new ScalaCompilerForUnitTesting + val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) + val expectedNames = standardNames ++ Set("B", "A", "a", "Int", "selectDynamic", "bla") + assertEquals(usedNames("B"), expectedNames) + } + + @Test + def extractSealedClassScope = { + val sealedClassName = "Sealed" + val sealedClass = + s"""package base + | + |sealed class $sealedClassName + |object Usage extends $sealedClassName + |object Usage2 extends $sealedClassName + """.stripMargin + + def findPatMatUsages(in: String): Set[String] = { + val compilerForTesting = new ScalaCompilerForUnitTesting + val (_, callback) = + compilerForTesting.compileSrcs(List(List(sealedClass, in)), reuseCompilerInstance = false) + val clientNames = callback.usedNamesAndScopes.filterKeys(!_.startsWith("base.")) + + val names: Set[String] = clientNames.flatMap { + case (_, usages) => + usages.filter(_.scopes.contains(UseScope.PatMatTarget)).map(_.name) + }(collection.breakOut) + + names + } + + def classWithPatMatOfType(tpe: String = sealedClassName) = + s"""package client + |import base._ + | + |class test(a: $tpe) { + | a match { + | case _ => 1 + | } + |} + """.stripMargin + + assertEquals(findPatMatUsages(classWithPatMatOfType()), Set(sealedClassName)) + // Option is sealed + assertEquals(findPatMatUsages(classWithPatMatOfType(s"Option[$sealedClassName]")), + Set(sealedClassName, "Option")) + // Seq and Set is not + assertEquals(findPatMatUsages(classWithPatMatOfType(s"Seq[Set[$sealedClassName]]")), Set(sealedClassName)) + + def inNestedCase(tpe: String) = + s"""package client + |import base._ + | + |class test(a: Any) { + | a match { + | case _: $tpe => 1 + | } + |}""".stripMargin + + assertEquals(findPatMatUsages(inNestedCase(sealedClassName)), Set()) + + val notUsedInPatternMatch = + s"""package client + |import base._ + | + |class test(a: Any) { + | a match { + | case _ => 1 + | } + | val aa: $sealedClassName = ??? + |}""".stripMargin + + assertEquals(findPatMatUsages(notUsedInPatternMatch), Set()) + } + + /** + * Standard names that appear in every compilation unit that has any class + * definition. + */ + private val standardNames = Set( + "scala", + // The default parent of a class is "AnyRef" which is an alias for "Object" + "AnyRef", + "Object", + "java;lang;Object;init;" + ) + +} \ No newline at end of file From b769005667cc02fe0a92b785f79dc89e14cbfd53 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 9 Mar 2018 18:54:09 +0100 Subject: [PATCH 079/101] Remove dependency on specs2 --- project/Build.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 549566af241a..7d41b0e7b51c 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -739,9 +739,7 @@ object Build { resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api libraryDependencies ++= Seq( Dependencies.compilerInterface(sbtVersion.value), - (Dependencies.zincApiinfo(sbtVersion.value) % Test).withDottyCompat(scalaVersion.value), - ("org.specs2" %% "specs2-core" % "3.9.1" % Test).withDottyCompat(scalaVersion.value), - ("org.specs2" %% "specs2-junit" % "3.9.1" % Test).withDottyCompat(scalaVersion.value) + (Dependencies.zincApiinfo(sbtVersion.value) % Test).withDottyCompat(scalaVersion.value) ), // The sources should be published with crossPaths := false since they // need to be compiled by the project using the bridge. From e4eed7bca79700765ca1bc0cf41b04797599d127 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 13 Mar 2018 15:47:45 +0100 Subject: [PATCH 080/101] Remove duplicate implementation of isLocal --- compiler/src/dotty/tools/backend/jvm/GenBCode.scala | 3 ++- compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index 0f2f1e076207..d7f392a56d83 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -13,6 +13,7 @@ import scala.tools.nsc.backend.jvm._ import dotty.tools.dotc import dotty.tools.dotc.backend.jvm.DottyPrimitives import dotty.tools.dotc.transform.Erasure +import dotty.tools.dotc.transform.SymUtils._ import dotty.tools.dotc.interfaces import java.util.Optional @@ -265,7 +266,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter // ----------- sbt's callbacks val (fullClassName, isLocal) = ctx.atPhase(ctx.sbtExtractDependenciesPhase) { implicit ctx => - (ExtractDependencies.classNameAsString(claszSymbol), ExtractDependencies.isLocal(claszSymbol)) + (ExtractDependencies.classNameAsString(claszSymbol), claszSymbol.isLocal) } for ((cls, clsFile) <- classNodes.zip(classFiles)) { diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 0ba982e026af..d0145fa4b1fe 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -6,6 +6,7 @@ import core._, core.Decorators._ import util.NoSource.{file => NoSourceFile} import Contexts._, Flags._, Phases._, Trees._, Types._, Symbols._ import Names._, NameOps._, StdNames._ +import transform.SymUtils._ import scala.collection.{Set, mutable} @@ -151,9 +152,6 @@ object ExtractDependencies { def classNameAsString(sym: Symbol)(implicit ctx: Context): String = sym.fullName.stripModuleClassSuffix.toString - def isLocal(sym: Symbol)(implicit ctx: Context): Boolean = - sym.ownersIterator.exists(_.isTerm) - /** Return the enclosing class or the module class if it's a module. */ def enclOrModuleClass(dep: Symbol)(implicit ctx: Context): Symbol = if (dep.is(ModuleVal)) dep.moduleClass else dep.enclosingClass @@ -301,7 +299,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def addInheritanceDependency(tree: Template)(implicit ctx: Context): Unit = if (tree.parents.nonEmpty) { val depContext = - if (isLocal(tree.symbol.owner)) LocalDependencyByInheritance + if (tree.symbol.owner.isLocal) LocalDependencyByInheritance else DependencyByInheritance val from = resolveDependencySource tree.parents.foreach { parent => From ca2b2d59a7de0c603afd991676ecc99869bbd7de Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 13 Mar 2018 16:42:05 +0100 Subject: [PATCH 081/101] Port sbt/zinc#288 Use a different encoding for constructor: constructor.enclosingClass.fullName ++ ";init;" --- .../tools/dotc/sbt/ExtractDependencies.scala | 34 +++++++++++-------- .../xsbt/ExtractUsedNamesSpecification.scala | 2 +- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index d0145fa4b1fe..dd00e300ef93 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -151,10 +151,6 @@ class ExtractDependencies extends Phase { object ExtractDependencies { def classNameAsString(sym: Symbol)(implicit ctx: Context): String = sym.fullName.stripModuleClassSuffix.toString - - /** Return the enclosing class or the module class if it's a module. */ - def enclOrModuleClass(dep: Symbol)(implicit ctx: Context): Symbol = - if (dep.is(ModuleVal)) dep.moduleClass else dep.enclosingClass } private case class ClassDependency(from: Symbol, to: Symbol, context: DependencyContext) @@ -230,7 +226,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT if (_responsibleForImports == null) { val tree = ctx.compilationUnit.tpdTree _responsibleForImports = firstClassOrModule(tree) - if (_responsibleForImports == NoSymbol) + if (!_responsibleForImports.exists) ctx.warning("""|No class, trait or object is defined in the compilation unit. |The incremental compiler cannot record the dependency information in such case. |Some errors like unused import referring to a non-existent class might not be reported. @@ -274,24 +270,32 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def addUsedName(name: Name, scope: UseScope)(implicit ctx: Context): Unit = { val fromClass = resolveDependencySource - if (fromClass ne NoSymbol) { + if (fromClass.exists) { assert(fromClass.isClass) addUsedName(fromClass, name, scope) } } + /** Mangle a JVM symbol name in a format better suited for internal uses by sbt. */ + private def mangledName(sym: Symbol)(implicit ctx: Context): Name = { + def constructorName = sym.enclosingClass.fullName ++ ";init;" + + if (sym.isConstructor) constructorName + else sym.name.stripModuleClassSuffix + } + private def addMemberRefDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { - val depClass = enclOrModuleClass(sym) - // assert(depClass.isClass, s"$depClass, $sym, ${sym.isClass}") + val enclOrModuleClass = if (sym.is(ModuleVal)) sym.moduleClass else sym.enclosingClass + // assert(enclOrModuleClass.isClass, s"$depClass, $sym")) - if (depClass ne NoSymbol) { - assert(depClass.isClass) + if (enclOrModuleClass.exists) { + assert(enclOrModuleClass.isClass) val fromClass = resolveDependencySource - if (fromClass ne NoSymbol) { + if (fromClass.exists) { assert(fromClass.isClass) - _dependencies += ClassDependency(fromClass, depClass, DependencyByMemberRef) - addUsedName(fromClass, sym.name.stripModuleClassSuffix, UseScope.Default) + _dependencies += ClassDependency(fromClass, enclOrModuleClass, DependencyByMemberRef) + addUsedName(fromClass, mangledName(sym), UseScope.Default) } } } @@ -308,7 +312,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT } private def ignoreDependency(sym: Symbol)(implicit ctx: Context) = - sym.eq(NoSymbol) || + !sym.exists || sym.isAnonymousFunction || sym.isAnonymousClass || sym.is(PackageClass) @@ -424,7 +428,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT val traverser = new TypeDependencyTraverser { def addDependency(symbol: Symbol) = if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val usedName = symbol.name.stripModuleClassSuffix + val usedName = mangledName(symbol) addUsedName(usedName, UseScope.PatMatTarget) } } diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index 75fbbb110af7..c39f96d2fe83 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -310,7 +310,7 @@ class ExtractUsedNamesSpecification { // The default parent of a class is "AnyRef" which is an alias for "Object" "AnyRef", "Object", - "java;lang;Object;init;" + "java.lang.Object;init;" ) } \ No newline at end of file From 5247afa67d8125b569f76d5b9837377815e59b1d Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 13 Mar 2018 17:04:59 +0100 Subject: [PATCH 082/101] Remove useless test --- .../tools/dotc/sbt/ExtractDependencies.scala | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index dd00e300ef93..40a836173a8c 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -270,7 +270,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def addUsedName(name: Name, scope: UseScope)(implicit ctx: Context): Unit = { val fromClass = resolveDependencySource - if (fromClass.exists) { + if (fromClass.exists) { // can happen when visiting imports assert(fromClass.isClass) addUsedName(fromClass, name, scope) } @@ -287,16 +287,13 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def addMemberRefDependency(sym: Symbol)(implicit ctx: Context): Unit = if (!ignoreDependency(sym)) { val enclOrModuleClass = if (sym.is(ModuleVal)) sym.moduleClass else sym.enclosingClass - // assert(enclOrModuleClass.isClass, s"$depClass, $sym")) - - if (enclOrModuleClass.exists) { - assert(enclOrModuleClass.isClass) - val fromClass = resolveDependencySource - if (fromClass.exists) { - assert(fromClass.isClass) - _dependencies += ClassDependency(fromClass, enclOrModuleClass, DependencyByMemberRef) - addUsedName(fromClass, mangledName(sym), UseScope.Default) - } + assert(enclOrModuleClass.isClass, s"$enclOrModuleClass, $sym") + + val fromClass = resolveDependencySource + if (fromClass.exists) { // can happen when visiting imports + assert(fromClass.isClass) + _dependencies += ClassDependency(fromClass, enclOrModuleClass, DependencyByMemberRef) + addUsedName(fromClass, mangledName(sym), UseScope.Default) } } From 881f1a8f536d83c1d9b17b4a9f1200dcecf37c06 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 20 Mar 2018 15:06:34 +0100 Subject: [PATCH 083/101] Fix latest unit tests from Zinc --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 6 +- .../tools/dotc/sbt/ExtractDependencies.scala | 34 +++++--- .../xsbt/ExtractUsedNamesSpecification.scala | 86 +++++++------------ 3 files changed, 56 insertions(+), 70 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index f5c80e538f5a..19cd8992fd74 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -62,7 +62,7 @@ class ExtractAPI extends Phase { ctx.sbtCallback.startSource(sourceFile.file) val apiTraverser = new ExtractAPICollector - val sources = apiTraverser.apiSource(unit.tpdTree) + val classes = apiTraverser.apiSource(unit.tpdTree) val mainClasses = apiTraverser.mainClasses if (dumpInc) { @@ -70,12 +70,12 @@ class ExtractAPI extends Phase { val pw = new PrintWriter(File(sourceFile.jpath).changeExtension("inc").toFile .bufferedWriter(append = true), true) try { - sources.foreach(source => pw.println(DefaultShowAPI(source))) + classes.foreach(source => pw.println(DefaultShowAPI(source))) } finally pw.close() } if (ctx.sbtCallback != null) { - sources.foreach(ctx.sbtCallback.api(sourceFile.file, _)) + classes.foreach(ctx.sbtCallback.api(sourceFile.file, _)) mainClasses.foreach(ctx.sbtCallback.mainClass(sourceFile.file, _)) } } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 40a836173a8c..456dee899e50 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -278,7 +278,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT /** Mangle a JVM symbol name in a format better suited for internal uses by sbt. */ private def mangledName(sym: Symbol)(implicit ctx: Context): Name = { - def constructorName = sym.enclosingClass.fullName ++ ";init;" + def constructorName = sym.owner.fullName ++ ";init;" if (sym.isConstructor) constructorName else sym.name.stripModuleClassSuffix @@ -297,7 +297,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT } } - private def addInheritanceDependency(tree: Template)(implicit ctx: Context): Unit = + private def addInheritanceDependencies(tree: Template)(implicit ctx: Context): Unit = if (tree.parents.nonEmpty) { val depContext = if (tree.symbol.owner.isLocal) LocalDependencyByInheritance @@ -310,9 +310,10 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private def ignoreDependency(sym: Symbol)(implicit ctx: Context) = !sym.exists || + sym.is(PackageClass) || + sym.isEffectiveRoot || sym.isAnonymousFunction || - sym.isAnonymousClass || - sym.is(PackageClass) + sym.isAnonymousClass /** Traverse the tree of a source file and record the dependencies and used names which * can be retrieved using `dependencies` and`usedNames`. @@ -328,7 +329,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT addMemberRefDependency(lookupImported(name.toTermName)) addMemberRefDependency(lookupImported(name.toTypeName)) } - selectors foreach { + selectors.foreach { case Ident(name) => addImported(name) case Thicket(Ident(name) :: Ident(rename) :: Nil) => @@ -338,20 +339,31 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT } case _ => } - case Inlined(call, _, _) => - // The inlined call is normally ignored by TreeTraverser but we need to - // record it as a dependency - traverse(call) case t: TypeTree => addTypeDependency(t.tpe) case ref: RefTree => addMemberRefDependency(ref.symbol) addTypeDependency(ref.tpe) case t: Template => - addInheritanceDependency(t) + addInheritanceDependencies(t) + case _ => + } + + tree match { + case Inlined(call, _, _) => + // The inlined call is normally ignored by TreeTraverser but we need to + // record it as a dependency + traverse(call) + case vd: ValDef if vd.symbol.is(ModuleVal) => + // Don't visit module val + case t: Template if t.symbol.owner.is(ModuleClass) => + // Don't visit self type of module class + traverse(t.constr) + t.parents.foreach(traverse) + t.body.foreach(traverse) case _ => + traverseChildren(tree) } - traverseChildren(tree) } /** Traverse a used type and record all the dependencies we need to keep track diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index c39f96d2fe83..fdee490a3673 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -43,7 +43,7 @@ class ExtractUsedNamesSpecification { |}""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - val expectedNames = standardNames ++ Set("a", "c", "A", "B", "C", "D", "b", "X", "BB") + val expectedNames = standardNames ++ Set("a", "c", "A", "B", "C", "D", "b", "BB") assertEquals(usedNames("b.X"), expectedNames) } @@ -58,7 +58,7 @@ class ExtractUsedNamesSpecification { |}""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - val expectedNames = standardNames ++ Set("A", "a", "B", "=", "Int") + val expectedNames = standardNames ++ Set("A", "a", "=", "Int") assertEquals(usedNames("B"), expectedNames) } @@ -78,15 +78,11 @@ class ExtractUsedNamesSpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB, srcC, srcD) val scalaVersion = scala.util.Properties.versionNumberString - // TODO: Find out what's making these types appear in 2.10 - // They don't come from type dependency traverser, but from `addSymbol` - val versionDependentNames = - if (scalaVersion.contains("2.10")) Set("Nothing", "Any") else Set() - val namesA = standardNames ++ Set("A") ++ versionDependentNames - val namesAX = standardNames ++ Set("X", "x", "T", "A") - val namesB = Set("B", "A", "Int", "A;init;", "scala") - val namesC = Set("B;init;", "C", "B") - val namesD = standardNames ++ Set("D", "C", "X", "foo", "Int", "T") + val namesA = standardNames ++ Set("Nothing", "Any") + val namesAX = standardNames ++ Set("x", "T", "A", "Nothing", "Any") + val namesB = Set("A", "Int", "A;init;", "Unit") + val namesC = Set("B;init;", "B", "Unit") + val namesD = standardNames ++ Set("C", "X", "foo", "Int", "T") assertEquals(usedNames("A"), namesA) assertEquals(usedNames("A.X"), namesAX) assertEquals(usedNames("B"), namesB) @@ -134,23 +130,18 @@ class ExtractUsedNamesSpecification { |""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(src1, src2) - val expectedNames_lista = standardNames ++ Set("Test_lista", "x", "B", "lista", "List", "A") - val expectedNames_at = standardNames ++ Set("Test_at", "x", "B", "at", "A", "T", "X0", "X1") - val expectedNames_as = standardNames ++ Set("Test_as", "x", "B", "as", "S", "Y") - val expectedNames_foo = standardNames ++ Set("Test_foo", - "x", - "B", + val expectedNames_lista = standardNames ++ Set("B", "lista", "List", "A") + val expectedNames_at = standardNames ++ Set("B", "at", "A", "T", "X0", "X1") + val expectedNames_as = standardNames ++ Set("B", "as", "S", "Y") + val expectedNames_foo = standardNames ++ Set("B", "foo", "M", "N", "Predef", "???", "Nothing") - val expectedNames_bar = standardNames ++ Set("Test_bar", - "x", - "B", + val expectedNames_bar = standardNames ++ Set("B", "bar", - "Param", "P1", "P0", "Predef", @@ -163,37 +154,20 @@ class ExtractUsedNamesSpecification { assertEquals(usedNames("Test_bar"), expectedNames_bar) } - @Test - def extractUsedNamesFromExistential = { - val srcFoo = - """import scala.language.existentials - |class Foo { - | val foo: T forSome { type T <: Double } = ??? - |} - """.stripMargin - val compilerForTesting = new ScalaCompilerForUnitTesting - val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcFoo) - val expectedNames = standardNames ++ Seq("Double", - "Foo", - "T", - "foo", - "scala", - "language", - "existentials", - "Nothing", - "???", - "Predef") - assertEquals(usedNames("Foo"), expectedNames) - } - @Test def extractUsedNamesFromRefinement = { - val srcFoo = - "object Outer {\n class Inner { type Xyz }\n\n type TypeInner = Inner { type Xyz = Int }\n}" - val srcBar = "object Bar {\n def bar: Outer.TypeInner = null\n}" + val srcFoo = """|object Outer { + | class Inner { type Xyz } + | type TypeInner = Inner { type Xyz = Int } + |} + |""".stripMargin + val srcBar = """|object Bar { + | def bar: Outer.TypeInner = null + |} + |""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcFoo, srcBar) - val expectedNames = standardNames ++ Set("Bar", "Outer", "TypeInner", "Inner", "Xyz", "Int") + val expectedNames = standardNames ++ Set("Outer", "TypeInner", "Inner", "Int") assertEquals(usedNames("Bar"), expectedNames) } @@ -219,7 +193,7 @@ class ExtractUsedNamesSpecification { // test for https://github.com/gkossakowski/sbt/issues/4 // TODO: we should fix it by having special treatment of `selectDynamic` and `applyDynamic` calls - @Test + @Ignore("Call to Dynamic is desugared in type checker so Select nodes is turned into string literal.") def extractNamesFromMethodCallOnDynamic = { val srcA = """|import scala.language.dynamics |class A extends Dynamic { @@ -228,7 +202,7 @@ class ExtractUsedNamesSpecification { val srcB = "class B { def foo(a: A): Int = a.bla }" val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) - val expectedNames = standardNames ++ Set("B", "A", "a", "Int", "selectDynamic", "bla") + val expectedNames = standardNames ++ Set("A", "a", "Int", "selectDynamic", "bla") assertEquals(usedNames("B"), expectedNames) } @@ -306,11 +280,11 @@ class ExtractUsedNamesSpecification { * definition. */ private val standardNames = Set( - "scala", - // The default parent of a class is "AnyRef" which is an alias for "Object" - "AnyRef", + // All classes extend Object "Object", - "java.lang.Object;init;" + // All classes have a default constructor called + "java.lang.Object;init;", + // the return type of the default constructor is Unit + "Unit" ) - -} \ No newline at end of file +} From 8c8a950f800deec3139bc59764221771e154e54d Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 20 Mar 2018 16:05:50 +0100 Subject: [PATCH 084/101] Small Cleanup --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 7 +-- .../tools/dotc/sbt/ExtractDependencies.scala | 58 ++++++++++--------- project/Build.scala | 10 ++-- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 19cd8992fd74..e9ead6654797 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -11,9 +11,7 @@ import Phases._ import Trees._ import Types._ import Symbols._ -import Names._ import NameOps._ -import StdNames._ import NameKinds.DefaultGetterName import typer.Inliner import typer.ErrorReporting.cyclicErrorMsg @@ -22,7 +20,6 @@ import transform.SymUtils._ import dotty.tools.io.File import java.io.PrintWriter -import dotty.tools.dotc.config.JavaPlatform import xsbti.api.DefinitionType import scala.collection.mutable @@ -358,10 +355,10 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder sym.owner.companionModule // default getters for class constructors are found in the companion object else sym.owner - (0 until pnames.length).map(i => + pnames.indices.map(i => qual.info.member(DefaultGetterName(sym.name, start + i)).exists) } else - (0 until pnames.length).map(Function.const(false)) + pnames.indices.map(Function.const(false)) val params = (pnames, ptypes, defaults).zipped.map((pname, ptype, isDefault) => api.MethodParameter.of(pname.toString, apiType(ptype), isDefault, api.ParameterModifier.Plain)) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 456dee899e50..116fe1d9413b 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -1,25 +1,28 @@ package dotty.tools.dotc package sbt -import ast.{Trees, tpd} -import core._, core.Decorators._ -import util.NoSource.{file => NoSourceFile} -import Contexts._, Flags._, Phases._, Trees._, Types._, Symbols._ -import Names._, NameOps._, StdNames._ -import transform.SymUtils._ - -import scala.collection.{Set, mutable} - -import dotty.tools.io -import dotty.tools.io.{AbstractFile, ZipArchive, PlainFile} - import java.io.File - -import java.util.{Arrays, Comparator, EnumSet} - +import java.util.{Arrays, EnumSet} + +import dotty.tools.dotc.ast.Trees._ +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.core.Contexts._ +import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.Flags._ +import dotty.tools.dotc.core.NameOps._ +import dotty.tools.dotc.core.Names._ +import dotty.tools.dotc.core.Phases._ +import dotty.tools.dotc.core.StdNames._ +import dotty.tools.dotc.core.Symbols._ +import dotty.tools.dotc.core.Types._ +import dotty.tools.dotc.transform.SymUtils._ +import dotty.tools.io +import dotty.tools.io.{AbstractFile, PlainFile, ZipArchive} +import xsbti.UseScope import xsbti.api.DependencyContext import xsbti.api.DependencyContext._ -import xsbti.UseScope + +import scala.collection.{Set, mutable} /** This phase sends information on classes' dependencies to sbt via callbacks. @@ -191,7 +194,6 @@ private final class UsedNamesInClass { */ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeTraverser => import tpd._ - import ExtractDependencies._ private[this] val _usedNames = new mutable.HashMap[Symbol, UsedNamesInClass] private[this] val _dependencies = new mutable.HashSet[ClassDependency] @@ -243,20 +245,24 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT * class from a given `ctx.owner` */ private def resolveDependencySource(implicit ctx: Context): Symbol = { - def resolveDepSource: Symbol = { - val owners = ctx.owner.ownersIterator - while (owners.hasNext) { - val source = owners.next() - def isLocal = !owners.exists(_.isTerm) // side-effectful: consume iterator elements - if (source.isClass && isLocal) return source + def nonLocalEnclosingClass = { + var clazz = ctx.owner.enclosingClass + var owner = clazz + + while (!owner.is(PackageClass)) { + if (owner.isTerm) { + clazz = owner.enclosingClass + owner = clazz + } else { + owner = owner.owner + } } - assert(false, "unreachable") - NoSymbol + clazz } if (lastOwner != ctx.owner) { lastOwner = ctx.owner - val source = resolveDepSource + val source = nonLocalEnclosingClass lastDepSource = if (source.is(PackageClass)) responsibleForImports else source } diff --git a/project/Build.scala b/project/Build.scala index 7d41b0e7b51c..5f141aae0463 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -135,7 +135,7 @@ object Build { val path = Paths.get(submodule) Files.exists(path) && { val fileStream = Files.list(path) - try fileStream.iterator().hasNext() + try fileStream.iterator().hasNext finally fileStream.close() } } @@ -727,7 +727,7 @@ object Build { cleanSbtBridge := { val home = System.getProperty("user.home") val sbtOrg = "org.scala-sbt" - val bridgeDirectoryPattern = s"*${dottyVersion}*" + val bridgeDirectoryPattern = s"*$dottyVersion*" val log = streams.value.log log.info("Cleaning the dotty-sbt-bridge cache") @@ -899,7 +899,7 @@ object Build { val inputArgs = spaceDelimited("").parsed val codeArgs = if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs val extensionPath = baseDirectory.value.getAbsolutePath - val processArgs = List(s"--extensionDevelopmentPath=${extensionPath}") ++ codeArgs + val processArgs = List(s"--extensionDevelopmentPath=$extensionPath") ++ codeArgs runProcess(codeCommand.value ++ processArgs, wait = true) }.dependsOn(compile in Compile).evaluated @@ -1054,7 +1054,7 @@ object Build { def doCompile(sourcesArgs: List[String]): Unit = { run.run("dotty.tools.dotc.Main", compilerCp, "-classpath" :: cpStr :: - "-d" :: classesDirectory.getAbsolutePath() :: + "-d" :: classesDirectory.getAbsolutePath :: scalacOptions ++: sourcesArgs, patchedLogger) @@ -1067,7 +1067,7 @@ object Build { (sourcesArgs.map(_.length).sum > 1536)) { IO.withTemporaryFile("sourcesargs", ".txt") { sourceListFile => IO.writeLines(sourceListFile, sourcesArgs) - doCompile(List("@"+sourceListFile.getAbsolutePath())) + doCompile(List("@"+sourceListFile.getAbsolutePath)) } } else { doCompile(sourcesArgs) From e9223c192fb2b5f687155f860fc59b5b7a787bc0 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 20 Mar 2018 16:17:49 +0100 Subject: [PATCH 085/101] Enable all tests --- .drone.yml | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.drone.yml b/.drone.yml index 1edf1c84a95a..c98b0963b528 100644 --- a/.drone.yml +++ b/.drone.yml @@ -19,29 +19,29 @@ pipeline: # clone submodules in parallelRiRem - git submodule update --init --recursive --jobs 3 - # # TESTS: - # # We run tests in parallel. Tests run in a copy of the working directory to avoid conflict - # test: - # group: test - # image: lampepfl/dotty:2018-01-17 - # commands: - # - cp -R . /tmp/1/ && cd /tmp/1/ - # - ./project/scripts/sbt ";compile ;test" - # - ./project/scripts/cmdTests + # TESTS: + # We run tests in parallel. Tests run in a copy of the working directory to avoid conflict + test: + group: test + image: lampepfl/dotty:2018-01-17 + commands: + - cp -R . /tmp/1/ && cd /tmp/1/ + - ./project/scripts/sbt ";compile ;test" + - ./project/scripts/cmdTests - # test_bootstrapped: - # group: test - # image: lampepfl/dotty:2018-01-17 - # commands: - # - cp -R . /tmp/2/ && cd /tmp/2/ - # - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" + test_bootstrapped: + group: test + image: lampepfl/dotty:2018-01-17 + commands: + - cp -R . /tmp/2/ && cd /tmp/2/ + - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" - # test_optimised: - # group: test - # image: lampepfl/dotty:2018-01-17 - # commands: - # - cp -R . /tmp/3/ && cd /tmp/3/ - # - ./project/scripts/sbt dotty-optimised/test + test_optimised: + group: test + image: lampepfl/dotty:2018-01-17 + commands: + - cp -R . /tmp/3/ && cd /tmp/3/ + - ./project/scripts/sbt dotty-optimised/test test_sbt: group: test From 066a01cd97c26a7b00e6866adad645b336cf146a Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 21 Mar 2018 10:56:52 +0100 Subject: [PATCH 086/101] Fix vulpix meta test --- tests/vulpix-tests/meta/sbt-output.check | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/vulpix-tests/meta/sbt-output.check b/tests/vulpix-tests/meta/sbt-output.check index 65eb5cbf22f6..f8704de3ab6f 100644 --- a/tests/vulpix-tests/meta/sbt-output.check +++ b/tests/vulpix-tests/meta/sbt-output.check @@ -38,5 +38,5 @@ Testing tests/vulpix-tests/meta/pos/does-not-compile.scala [error] Failed: Total 3, Failed 3, Errors 0, Passed 0 [error] Failed tests: [error] dotty.tools.vulpix.VulpixMetaTests -[error] (dotty-compiler/test:testOnly) sbt.TestsFailedException: Tests unsuccessful +[error] (dotty-compiler / Test / testOnly) sbt.TestsFailedException: Tests unsuccessful [error] Total time: 3 s, completed Feb 5, 2018 5:10:12 PM SKIP From 036a6337ec0eff92a5c9dbcaa3afbee2175231e0 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 21 Mar 2018 11:11:18 +0100 Subject: [PATCH 087/101] Remove dead code --- project/Dependencies.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index f2b503cdbb99..7e52dbc95bd3 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -1,6 +1,3 @@ -import java.io.FileInputStream; -import java.util.Properties - import sbt._ /** A dependency shared between multiple projects should be put here @@ -15,4 +12,4 @@ object Dependencies { def compilerInterface(sbtVersion: String) = "org.scala-sbt" % "compiler-interface" % sbtVersion def zincApiinfo(sbtVersion: String) = "org.scala-sbt" %% "zinc-apiinfo" % sbtVersion -} \ No newline at end of file +} From 0495c850003f17a680a2b612336d5d645acaac2d Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 21 Mar 2018 11:16:22 +0100 Subject: [PATCH 088/101] Only run sbt scripted tests on nightly or deployment --- .drone.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index c98b0963b528..ee5d7685dcf5 100644 --- a/.drone.yml +++ b/.drone.yml @@ -49,9 +49,9 @@ pipeline: commands: - cp -R . /tmp/4/ && cd /tmp/4/ - ./project/scripts/sbt sbt-dotty/scripted - # when: - # sbt scripted tests are slow and don't run on PRs - # event: [ push, tag, deployment ] + when: + # sbt scripted tests are slow and only run on nightly or deployment + event: [ tag, deployment ] # DOCUMENTATION: documentation: From 17762427731bdc5ddf02c7708659512fd10764ec Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 21 Mar 2018 11:49:59 +0100 Subject: [PATCH 089/101] Update CI Docker Image --- .drone.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.drone.yml b/.drone.yml index ee5d7685dcf5..fc309ee7a42c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -23,7 +23,7 @@ pipeline: # We run tests in parallel. Tests run in a copy of the working directory to avoid conflict test: group: test - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 commands: - cp -R . /tmp/1/ && cd /tmp/1/ - ./project/scripts/sbt ";compile ;test" @@ -31,21 +31,21 @@ pipeline: test_bootstrapped: group: test - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 commands: - cp -R . /tmp/2/ && cd /tmp/2/ - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" test_optimised: group: test - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 commands: - cp -R . /tmp/3/ && cd /tmp/3/ - ./project/scripts/sbt dotty-optimised/test test_sbt: group: test - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 commands: - cp -R . /tmp/4/ && cd /tmp/4/ - ./project/scripts/sbt sbt-dotty/scripted @@ -55,7 +55,7 @@ pipeline: # DOCUMENTATION: documentation: - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 commands: - ./project/scripts/genDocs secrets: [ bot_pass ] @@ -67,7 +67,7 @@ pipeline: # PUBLISHING: # Publishing expect NIGHTLYBUILD or RELEASEBUILD to be set. See dottyVersion in Build.scala publish_nightly: - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 environment: - NIGHTLYBUILD=yes commands: @@ -78,7 +78,7 @@ pipeline: environment: nightly publish_release: - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 environment: - RELEASEBUILD=yes commands: @@ -102,7 +102,7 @@ pipeline: event: tag publish_sbt_release: - image: lampepfl/dotty:2018-01-17 + image: lampepfl/dotty:2018-03-21 environment: - RELEASEBUILD=yes commands: From b088b84e994d0a97c31893e555fcfab5df024937 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 27 Mar 2018 02:29:16 +0200 Subject: [PATCH 090/101] Upgrade sbt to 1.1.2 This release contains a fix allowing us to remove the workaround added a few commits earlier. --- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 5 +---- project/build.properties | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 90f1c6fcc74d..892efaacb946 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -135,10 +135,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder * see the comment in the `RefinedType` case in `computeType` * The cache key is (api of RefinedType#parent, api of RefinedType#refinedInfo). */ - // FIXME: This should be a HashMap but cannot be until the fix for - // https://github.com/sbt/contraband/issues/119 is part of a released version - // of sbt, until then we cannot rely on the hashCode method of the api.* classes. - private[this] val refinedTypeCache = new mutable.ListMap[(api.Type, api.Definition), api.Structure] + private[this] val refinedTypeCache = new mutable.HashMap[(api.Type, api.Definition), api.Structure] private[this] val allNonLocalClassesInSrc = new mutable.HashSet[xsbti.api.ClassLike] private[this] val _mainClasses = new mutable.HashSet[String] diff --git a/project/build.properties b/project/build.properties index 31334bbd3df2..05313438a19d 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.1.1 +sbt.version=1.1.2 From 25e8c75dca0edfbe8fc780987629fb81ce2ae00e Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 27 Mar 2018 18:25:24 +0200 Subject: [PATCH 091/101] Don't use deprecated ScalaInstance constructor https://github.com/sbt/zinc/commit/9397b6aaf94ac3cfab386e3abd11c0ef9c2ceaff#diff-ea135f2f26f43e40ff045089da221e1e introduced a new constructor for ScalaInstance and deprecated the old one. We use the new one but don't call it with the proper arguments. It shouldn't matter though as the enw constructor was introduced to fix an issue with `sbt run` that only occurs when `(fork in run) := false`. --- project/Build.scala | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index f0ce84267664..b33b91de6558 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -249,6 +249,9 @@ object Build { // Compile using the non-bootstrapped and non-published dotty managedScalaInstance := false, scalaInstance := { + import sbt.internal.inc.ScalaInstance + import sbt.internal.inc.classpath.ClasspathUtilities + val updateReport = update.value var libraryJar = packageBin.in(`dotty-library`, Compile).value var compilerJar = packageBin.in(`dotty-compiler`, Compile).value @@ -270,8 +273,18 @@ object Build { val allJars = libraryJar :: compilerJar :: otherDependencies.toList val classLoader = state.value.classLoaderCache(allJars) - new sbt.internal.inc.ScalaInstance(scalaVersion.value, - classLoader, libraryJar, compilerJar, allJars.toArray, None) + new ScalaInstance( + scalaVersion.value, + classLoader, + ClasspathUtilities.rootLoader, // FIXME: Should be a class loader which only includes the dotty-lib + // See: https://github.com/sbt/zinc/commit/9397b6aaf94ac3cfab386e3abd11c0ef9c2ceaff#diff-ea135f2f26f43e40ff045089da221e1e + // Should not matter, as it addresses an issue with `sbt run` that + // only occur when `(fork in run) := false` + libraryJar, + compilerJar, + allJars.toArray, + None + ) } ) From 482c65b0d67fa8b425d4aacd28f88f502cef48b3 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 28 Mar 2018 16:03:13 +0200 Subject: [PATCH 092/101] Improve name conflict warning for case-insensitive filesystems --- .../dotty/tools/backend/jvm/GenBCode.scala | 45 ++++++++----------- .../dotty/tools/dotc/CompilationTests.scala | 6 +-- .../fatal-warnings/i2673c.scala | 2 +- tests/pos-special/fatal-warnings/i2673.scala | 6 +++ .../{ => fatal-warnings}/i3323.scala | 0 .../{ => fatal-warnings}/i3323b.scala | 0 .../i3589b.scala} | 0 .../{ => fatal-warnings}/i4166.scala | 0 .../{ => fatal-warnings}/i4185.scala | 0 9 files changed, 27 insertions(+), 32 deletions(-) create mode 100644 tests/pos-special/fatal-warnings/i2673.scala rename tests/pos-special/{ => fatal-warnings}/i3323.scala (100%) rename tests/pos-special/{ => fatal-warnings}/i3323b.scala (100%) rename tests/pos-special/{i3589-b.scala => fatal-warnings/i3589b.scala} (100%) rename tests/pos-special/{ => fatal-warnings}/i4166.scala (100%) rename tests/pos-special/{ => fatal-warnings}/i4185.scala (100%) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index ac1c7588f75f..06398c936083 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -163,7 +163,23 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter */ class Worker1(needsOutFolder: Boolean) { - val caseInsensitively = scala.collection.mutable.HashMap.empty[String, Symbol] + private val lowerCaseNames = mutable.HashMap.empty[String, Symbol] + private def checkForCaseConflict(javaClassName: String, classSymbol: Symbol) = { + val lowerCaseName = javaClassName.toLowerCase + lowerCaseNames.get(lowerCaseName) match { + case None => + lowerCaseNames.put(lowerCaseName, classSymbol) + case Some(dupClassSym) => + // Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting + val (cl1, cl2) = + if (classSymbol.effectiveName.toString < dupClassSym.effectiveName.toString) (classSymbol, dupClassSym) + else (dupClassSym, classSymbol) + ctx.atPhase(ctx.typerPhase) { implicit ctx => + ctx.warning(s"${cl1.show} differs only in case from ${cl2.showLocated}. " + + "Such classes will overwrite one another on case-insensitive filesystems.", cl1.pos) + } + } + } def run(): Unit = { while (true) { @@ -193,30 +209,6 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter val Item1(arrivalPos, cd, cunit) = item val claszSymbol = cd.symbol - // GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739 - def checkName(claszSymbol: Symbol): Unit = { - val lowercaseJavaClassName = claszSymbol.effectiveName.toString.toLowerCase - caseInsensitively.get(lowercaseJavaClassName) match { - case None => - caseInsensitively.put(lowercaseJavaClassName, claszSymbol) - case Some(dupClassSym) => - if (claszSymbol.effectiveName.toString != dupClassSym.effectiveName.toString) { - // Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting - val (cl1, cl2) = - if (claszSymbol.effectiveName.toString < dupClassSym.effectiveName.toString) (claszSymbol, dupClassSym) - else (dupClassSym, claszSymbol) - ctx.warning(s"Class ${cl1.effectiveName} differs only in case from ${cl2.effectiveName}. " + - "Such classes will overwrite one another on case-insensitive filesystems.", cl1.pos) - } - } - } - checkName(claszSymbol) - if (int.symHelper(claszSymbol).isModuleClass) { - val companionModule = claszSymbol.companionModule - if (int.symHelper(companionModule.owner).isPackageClass) - checkName(companionModule) - } - // -------------- mirror class, if needed -------------- val mirrorC = if (int.symHelper(claszSymbol).isTopLevelModuleClass) { @@ -263,6 +255,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter val classFiles = classNodes.map(cls => if (outF != null && cls != null) { try { + checkForCaseConflict(cls.name, claszSymbol) getFileForClassfile(outF, cls.name, ".class") } catch { case e: FileConflictException => @@ -272,7 +265,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter } else null ) - // ----------- sbt's callbacks + // ----------- compiler and sbt's callbacks val (fullClassName, isLocal) = ctx.atPhase(ctx.sbtExtractDependenciesPhase) { implicit ctx => (ExtractDependencies.classNameAsString(claszSymbol), claszSymbol.isLocal) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 2a7b78b6c64c..ee516074bdc4 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -55,14 +55,10 @@ class CompilationTests extends ParallelTesting { compileFile("tests/pos-scala2/rewrites.scala", scala2Mode.and("-rewrite")).copyToTarget() + compileFile("tests/pos-special/utf8encoded.scala", explicitUTF8) + compileFile("tests/pos-special/utf16encoded.scala", explicitUTF16) + - compileFile("tests/pos-special/i3323.scala", defaultOptions.and("-Xfatal-warnings")) + - compileFile("tests/pos-special/i3323b.scala", defaultOptions.and("-Xfatal-warnings")) + - compileFile("tests/pos-special/i3589-b.scala", defaultOptions.and("-Xfatal-warnings")) + - compileFile("tests/pos-special/i4166.scala", defaultOptions.and("-Xfatal-warnings")) + - compileFile("tests/pos-special/i4185.scala", defaultOptions.and("-Xfatal-warnings")) + compileFile("tests/pos-special/completeFromSource/Test.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) + compileFile("tests/pos-special/completeFromSource/Test2.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) + compileFile("tests/pos-special/completeFromSource/Test3.scala", defaultOptions.and("-sourcepath", "tests/pos-special", "-scansource")) + + compileFilesInDir("tests/pos-special/fatal-warnings", defaultOptions.and("-Xfatal-warnings")) + compileList( "compileMixed", List( diff --git a/tests/neg-custom-args/fatal-warnings/i2673c.scala b/tests/neg-custom-args/fatal-warnings/i2673c.scala index 3e9cff320ea2..a677fab3081d 100644 --- a/tests/neg-custom-args/fatal-warnings/i2673c.scala +++ b/tests/neg-custom-args/fatal-warnings/i2673c.scala @@ -1,6 +1,6 @@ package Foos object Outer { - class X // error + case class X() // error object x } diff --git a/tests/pos-special/fatal-warnings/i2673.scala b/tests/pos-special/fatal-warnings/i2673.scala new file mode 100644 index 000000000000..9721f81da217 --- /dev/null +++ b/tests/pos-special/fatal-warnings/i2673.scala @@ -0,0 +1,6 @@ +package Foos + +object Outer { + class X + object x +} diff --git a/tests/pos-special/i3323.scala b/tests/pos-special/fatal-warnings/i3323.scala similarity index 100% rename from tests/pos-special/i3323.scala rename to tests/pos-special/fatal-warnings/i3323.scala diff --git a/tests/pos-special/i3323b.scala b/tests/pos-special/fatal-warnings/i3323b.scala similarity index 100% rename from tests/pos-special/i3323b.scala rename to tests/pos-special/fatal-warnings/i3323b.scala diff --git a/tests/pos-special/i3589-b.scala b/tests/pos-special/fatal-warnings/i3589b.scala similarity index 100% rename from tests/pos-special/i3589-b.scala rename to tests/pos-special/fatal-warnings/i3589b.scala diff --git a/tests/pos-special/i4166.scala b/tests/pos-special/fatal-warnings/i4166.scala similarity index 100% rename from tests/pos-special/i4166.scala rename to tests/pos-special/fatal-warnings/i4166.scala diff --git a/tests/pos-special/i4185.scala b/tests/pos-special/fatal-warnings/i4185.scala similarity index 100% rename from tests/pos-special/i4185.scala rename to tests/pos-special/fatal-warnings/i4185.scala From 67ff1f21241ba860f8072f4a486513f41d116524 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 28 Mar 2018 16:04:50 +0200 Subject: [PATCH 093/101] Use SAM type whenever possible --- compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 116fe1d9413b..fdced5f83953 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -173,10 +173,7 @@ private final class UsedNamesInClass { names.foreach { case (name, scopes) => builder.append(name.mangledString) builder.append(" in [") - scopes.forEach(new java.util.function.Consumer[UseScope]() { // TODO: Adapt to SAM type when #2732 is fixed - override def accept(scope: UseScope): Unit = - builder.append(scope.toString) - }) + scopes.forEach(scope => builder.append(scope.toString)) builder.append("]") builder.append(", ") } From e78a3fbac25aa001d30a13b76dd3a53fdb117ed8 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 29 Mar 2018 10:11:31 +0200 Subject: [PATCH 094/101] Update docker image for sbt 1.1.2 --- .drone.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.drone.yml b/.drone.yml index fc309ee7a42c..95f8582fc254 100644 --- a/.drone.yml +++ b/.drone.yml @@ -23,7 +23,7 @@ pipeline: # We run tests in parallel. Tests run in a copy of the working directory to avoid conflict test: group: test - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 commands: - cp -R . /tmp/1/ && cd /tmp/1/ - ./project/scripts/sbt ";compile ;test" @@ -31,21 +31,21 @@ pipeline: test_bootstrapped: group: test - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 commands: - cp -R . /tmp/2/ && cd /tmp/2/ - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" test_optimised: group: test - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 commands: - cp -R . /tmp/3/ && cd /tmp/3/ - ./project/scripts/sbt dotty-optimised/test test_sbt: group: test - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 commands: - cp -R . /tmp/4/ && cd /tmp/4/ - ./project/scripts/sbt sbt-dotty/scripted @@ -55,7 +55,7 @@ pipeline: # DOCUMENTATION: documentation: - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 commands: - ./project/scripts/genDocs secrets: [ bot_pass ] @@ -67,7 +67,7 @@ pipeline: # PUBLISHING: # Publishing expect NIGHTLYBUILD or RELEASEBUILD to be set. See dottyVersion in Build.scala publish_nightly: - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 environment: - NIGHTLYBUILD=yes commands: @@ -78,7 +78,7 @@ pipeline: environment: nightly publish_release: - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 environment: - RELEASEBUILD=yes commands: @@ -102,7 +102,7 @@ pipeline: event: tag publish_sbt_release: - image: lampepfl/dotty:2018-03-21 + image: lampepfl/dotty:2018-03-29 environment: - RELEASEBUILD=yes commands: From 7a9907442c9146974b3e45b8006b9e64788de471 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 29 Mar 2018 12:58:51 +0200 Subject: [PATCH 095/101] Reorder arguments in assertEquals according to the spec: assertEquals(expected, found) --- .../test/xsbt/DependencySpecification.scala | 100 +++++++++--------- .../test/xsbt/ExtractAPISpecification.scala | 16 +-- .../xsbt/ExtractUsedNamesSpecification.scala | 46 ++++---- 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/sbt-bridge/test/xsbt/DependencySpecification.scala b/sbt-bridge/test/xsbt/DependencySpecification.scala index 639be7e0a7d2..d702c5993be3 100644 --- a/sbt-bridge/test/xsbt/DependencySpecification.scala +++ b/sbt-bridge/test/xsbt/DependencySpecification.scala @@ -12,21 +12,21 @@ class DependencySpecification { val classDependencies = extractClassDependenciesPublic val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance - assertEquals(memberRef("A"), Set.empty) - assertEquals(inheritance("A"), Set.empty) - assertEquals(memberRef("B"), Set("A", "D")) - assertEquals(inheritance("B"), Set("D")) - assertEquals(memberRef("C"), Set("A")) - assertEquals(inheritance("C"), Set.empty) - assertEquals(memberRef("D"), Set.empty) - assertEquals(inheritance("D"), Set.empty) - assertEquals(memberRef("E"), Set.empty) - assertEquals(inheritance("E"), Set.empty) - assertEquals(memberRef("F"), Set("A", "B", "D", "E", "G", "C")) // C is the underlying type of MyC - assertEquals(inheritance("F"), Set("A", "E")) - assertEquals(memberRef("H"), Set("B", "E", "G")) + assertEquals(Set.empty, memberRef("A")) + assertEquals(Set.empty, inheritance("A")) + assertEquals(Set("A", "D"), memberRef("B")) + assertEquals(Set("D"), inheritance("B")) + assertEquals(Set("A"), memberRef("C")) + assertEquals(Set.empty, inheritance("C")) + assertEquals(Set.empty, memberRef("D")) + assertEquals(Set.empty, inheritance("D")) + assertEquals(Set.empty, memberRef("E")) + assertEquals(Set.empty, inheritance("E")) + assertEquals(Set("A", "B", "D", "E", "G", "C"), memberRef("F")) // C is the underlying type of MyC + assertEquals(Set("A", "E"), inheritance("F")) + assertEquals(Set("B", "E", "G"), memberRef("H")) // aliases and applied type constructors are expanded so we have inheritance dependency on B - assertEquals(inheritance("H"), Set("B", "E")) + assertEquals(Set("B", "E"), inheritance("H")) } @Test @@ -35,18 +35,18 @@ class DependencySpecification { val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance val localInheritance = classDependencies.localInheritance - assertEquals(memberRef("A"), Set.empty) - assertEquals(inheritance("A"), Set.empty) - assertEquals(memberRef("B"), Set.empty) - assertEquals(inheritance("B"), Set.empty) - assertEquals(memberRef("C.Inner1"), Set("A")) - assertEquals(inheritance("C.Inner1"), Set("A")) - assertEquals(memberRef("D"), Set("B")) - assertEquals(inheritance("D"), Set.empty) - assertEquals(localInheritance("D"), Set("B")) - assertEquals(memberRef("E"), Set("B")) - assertEquals(inheritance("E"), Set.empty) - assertEquals(localInheritance("E"), Set("B")) + assertEquals(Set.empty, memberRef("A")) + assertEquals(Set.empty, inheritance("A")) + assertEquals(Set.empty, memberRef("B")) + assertEquals(Set.empty, inheritance("B")) + assertEquals(Set("A"), memberRef("C.Inner1")) + assertEquals(Set("A"), inheritance("C.Inner1")) + assertEquals(Set("B"), memberRef("D")) + assertEquals(Set.empty, inheritance("D")) + assertEquals(Set("B"), localInheritance("D")) + assertEquals(Set("B"), memberRef("E")) + assertEquals(Set.empty, inheritance("E")) + assertEquals(Set("B"), localInheritance("E")) } @Test @@ -54,18 +54,18 @@ class DependencySpecification { val classDependencies = extractClassDependenciesTraitAsFirstPatent val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance - assertEquals(memberRef("A"), Set.empty) - assertEquals(inheritance("A"), Set.empty) - assertEquals(memberRef("B"), Set("A")) - assertEquals(inheritance("B"), Set("A")) + assertEquals(Set.empty, memberRef("A")) + assertEquals(Set.empty, inheritance("A")) + assertEquals(Set("A"), memberRef("B")) + assertEquals(Set("A"), inheritance("B")) // verify that memberRef captures the oddity described in documentation of `Relations.inheritance` // we are mainly interested whether dependency on A is captured in `memberRef` relation so // the invariant that says that memberRef is superset of inheritance relation is preserved - assertEquals(memberRef("C"), Set("A", "B")) - assertEquals(inheritance("C"), Set("A", "B")) + assertEquals(Set("A", "B"), memberRef("C")) + assertEquals(Set("A", "B"), inheritance("C")) // same as above but indirect (C -> B -> A), note that only A is visible here - assertEquals(memberRef("D"), Set("A", "C")) - assertEquals(inheritance("D"), Set("A", "C")) + assertEquals(Set("A", "C"), memberRef("D")) + assertEquals(Set("A", "C"), inheritance("D")) } @Test @@ -80,10 +80,10 @@ class DependencySpecification { val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance - assertEquals(memberRef("Outer"), Set.empty) - assertEquals(inheritance("Outer"), Set.empty) - assertEquals(memberRef("Bar"), Set("Outer", "Outer$.Inner")) - assertEquals(inheritance("Bar"), Set.empty) + assertEquals(Set.empty, memberRef("Outer")) + assertEquals(Set.empty, inheritance("Outer")) + assertEquals(Set("Outer", "Outer$.Inner"), memberRef("Bar")) + assertEquals(Set.empty, inheritance("Bar")) } @Test @@ -100,10 +100,10 @@ class DependencySpecification { val memberRef = classDependencies.memberRef val inheritance = classDependencies.inheritance - assertEquals(memberRef("A"), Set("B")) - assertEquals(inheritance("A"), Set.empty) - assertEquals(memberRef("B"), Set.empty) - assertEquals(inheritance("B"), Set.empty) + assertEquals(Set("B"), memberRef("A")) + assertEquals(Set.empty, inheritance("A")) + assertEquals(Set.empty, memberRef("B")) + assertEquals(Set.empty, inheritance("B")) } @Test @@ -135,14 +135,14 @@ class DependencySpecification { .extractDependenciesFromSrcs(srcA, srcB, srcC, srcD, srcE, srcF, srcG, srcH) .memberRef - assertEquals(deps("A"), Set.empty) - assertEquals(deps("B"), Set("abc.A", "abc.A$.Inner")) - assertEquals(deps("C"), Set("abc.A", "abc.A2")) - assertEquals(deps("D"), Set("abc.A2")) - assertEquals(deps("E"), Set("abc.A")) - assertEquals(deps("F"), Set.empty) - assertEquals(deps("foo.bar.G"), Set("abc.A")) - assertEquals(deps("H"), Set("abc.A")) + assertEquals(Set.empty, deps("A")) + assertEquals(Set("abc.A", "abc.A$.Inner"), deps("B")) + assertEquals(Set("abc.A", "abc.A2"), deps("C")) + assertEquals(Set("abc.A2"), deps("D")) + assertEquals(Set("abc.A"), deps("E")) + assertEquals(Set.empty, deps("F")) + assertEquals(Set("abc.A"), deps("foo.bar.G")) + assertEquals(Set("abc.A"), deps("H")) } private def extractClassDependenciesPublic: ExtractedClassDependencies = { diff --git a/sbt-bridge/test/xsbt/ExtractAPISpecification.scala b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala index 15544ce1301a..dfbcbf2181a2 100644 --- a/sbt-bridge/test/xsbt/ExtractAPISpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala @@ -36,7 +36,7 @@ class ExtractAPISpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApiFromSrc(src) val Seq(fooClassApi) = apis.toSeq - assertEquals(fooClassApi.definitionType, DefinitionType.PackageModule) + assertEquals(DefinitionType.PackageModule, fooClassApi.definitionType) } @Test @@ -47,7 +47,7 @@ class ExtractAPISpecification { |}""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApiFromSrc(src).map(c => c.name -> c).toMap - assertEquals(apis.keys, Set("A", "A.B")) + assertEquals(Set("A", "A.B"), apis.keys) } @Test @@ -59,7 +59,7 @@ class ExtractAPISpecification { |class D { def foo: Unit = { new B {} } }""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApiFromSrc(src).map(c => c.name -> c).toMap - assertEquals(apis.keys, Set("A", "B", "C", "D")) + assertEquals(Set("A", "B", "C", "D"), apis.keys) } @Ignore @@ -93,7 +93,7 @@ class ExtractAPISpecification { |""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApiFromSrc(src).map(c => c.name -> c).toMap - assertEquals(apis.keys, Set("A", "B", "B.Inner1")) + assertEquals(Set("A", "B", "B.Inner1"), apis.keys) } @Test @@ -165,7 +165,7 @@ class ExtractAPISpecification { """.stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApiFromSrc(src).map(a => a.name -> a).toMap - assertEquals(apis.keySet, Set("A", "A.AA", "B", "B.AA")) + assertEquals(Set("A", "A.AA", "B", "B.AA"), apis.keySet) assertNotEquals(apis("A.AA"), apis("B.AA")) } @@ -181,7 +181,7 @@ class ExtractAPISpecification { """.stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val apis = compilerForTesting.extractApiFromSrc(src).map(a => a.name -> a).toMap - assertEquals(apis.keySet, Set("abc.package", "abc.package$.BuildInfoKey", "abc.package$.BuildInfoKey$.Entry")) + assertEquals(Set("abc.package", "abc.package$.BuildInfoKey", "abc.package$.BuildInfoKey$.Entry"), apis.keySet) } /** @@ -210,7 +210,7 @@ class ExtractAPISpecification { def hasSelfType(c: ClassLike): Boolean = c.selfType != emptyType val (withSelfType, withoutSelfType) = apis.partition(hasSelfType) - assertEquals(withSelfType.map(_.name).toSet, Set("C3", "C4", "C5", "C6")) - assertEquals(withoutSelfType.map(_.name).toSet, Set("X", "Y", "C1", "C2", "C8")) + assertEquals(Set("C3", "C4", "C5", "C6"), withSelfType.map(_.name).toSet) + assertEquals(Set("X", "Y", "C1", "C2", "C8"), withoutSelfType.map(_.name).toSet) } } diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index fdee490a3673..1c05fd3b6394 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -18,7 +18,7 @@ class ExtractUsedNamesSpecification { val expectedNames = standardNames ++ Set("a", "A", "A2", "b") // names used at top level are attributed to the first class defined in a compilation unit - assertEquals(usedNames("a.A"), expectedNames) + assertEquals(expectedNames, usedNames("a.A")) } // test covers https://github.com/gkossakowski/sbt/issues/6 @@ -44,7 +44,7 @@ class ExtractUsedNamesSpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) val expectedNames = standardNames ++ Set("a", "c", "A", "B", "C", "D", "b", "BB") - assertEquals(usedNames("b.X"), expectedNames) + assertEquals(expectedNames, usedNames("b.X")) } // test for https://github.com/gkossakowski/sbt/issues/5 @@ -59,7 +59,7 @@ class ExtractUsedNamesSpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) val expectedNames = standardNames ++ Set("A", "a", "=", "Int") - assertEquals(usedNames("B"), expectedNames) + assertEquals(expectedNames, usedNames("B")) } @Test @@ -83,11 +83,11 @@ class ExtractUsedNamesSpecification { val namesB = Set("A", "Int", "A;init;", "Unit") val namesC = Set("B;init;", "B", "Unit") val namesD = standardNames ++ Set("C", "X", "foo", "Int", "T") - assertEquals(usedNames("A"), namesA) - assertEquals(usedNames("A.X"), namesAX) - assertEquals(usedNames("B"), namesB) - assertEquals(usedNames("C"), namesC) - assertEquals(usedNames("D"), namesD) + assertEquals(namesA, usedNames("A")) + assertEquals(namesAX, usedNames("A.X")) + assertEquals(namesB, usedNames("B")) + assertEquals(namesC, usedNames("C")) + assertEquals(namesD, usedNames("D")) } // See source-dependencies/types-in-used-names-a for an example where @@ -147,11 +147,11 @@ class ExtractUsedNamesSpecification { "Predef", "???", "Nothing") - assertEquals(usedNames("Test_lista"), expectedNames_lista) - assertEquals(usedNames("Test_at"), expectedNames_at) - assertEquals(usedNames("Test_as"), expectedNames_as) - assertEquals(usedNames("Test_foo"), expectedNames_foo) - assertEquals(usedNames("Test_bar"), expectedNames_bar) + assertEquals(expectedNames_lista, usedNames("Test_lista")) + assertEquals(expectedNames_at, usedNames("Test_at")) + assertEquals(expectedNames_as, usedNames("Test_as")) + assertEquals(expectedNames_foo, usedNames("Test_foo")) + assertEquals(expectedNames_bar, usedNames("Test_bar")) } @Test @@ -168,7 +168,7 @@ class ExtractUsedNamesSpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcFoo, srcBar) val expectedNames = standardNames ++ Set("Outer", "TypeInner", "Inner", "Int") - assertEquals(usedNames("Bar"), expectedNames) + assertEquals(expectedNames, usedNames("Bar")) } // test for https://github.com/gkossakowski/sbt/issues/3 @@ -178,7 +178,7 @@ class ExtractUsedNamesSpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) val expectedNames = standardNames ++ Set("A", "foo", "Int") - assertEquals(usedNames("A"), expectedNames) + assertEquals(expectedNames, usedNames("A")) } // pending test for https://issues.scala-lang.org/browse/SI-7173 @@ -188,7 +188,7 @@ class ExtractUsedNamesSpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(src) val expectedNames = standardNames ++ Set("A", "foo", "Int") - assertEquals(usedNames("A"), expectedNames) + assertEquals(expectedNames, usedNames("A")) } // test for https://github.com/gkossakowski/sbt/issues/4 @@ -203,7 +203,7 @@ class ExtractUsedNamesSpecification { val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB) val expectedNames = standardNames ++ Set("A", "a", "Int", "selectDynamic", "bla") - assertEquals(usedNames("B"), expectedNames) + assertEquals(expectedNames, usedNames("B")) } @Test @@ -242,12 +242,12 @@ class ExtractUsedNamesSpecification { |} """.stripMargin - assertEquals(findPatMatUsages(classWithPatMatOfType()), Set(sealedClassName)) + assertEquals(Set(sealedClassName), findPatMatUsages(classWithPatMatOfType())) // Option is sealed - assertEquals(findPatMatUsages(classWithPatMatOfType(s"Option[$sealedClassName]")), - Set(sealedClassName, "Option")) + assertEquals(Set(sealedClassName, "Option"), + findPatMatUsages(classWithPatMatOfType(s"Option[$sealedClassName]"))) // Seq and Set is not - assertEquals(findPatMatUsages(classWithPatMatOfType(s"Seq[Set[$sealedClassName]]")), Set(sealedClassName)) + assertEquals(Set(sealedClassName), findPatMatUsages(classWithPatMatOfType(s"Seq[Set[$sealedClassName]]"))) def inNestedCase(tpe: String) = s"""package client @@ -259,7 +259,7 @@ class ExtractUsedNamesSpecification { | } |}""".stripMargin - assertEquals(findPatMatUsages(inNestedCase(sealedClassName)), Set()) + assertEquals(Set(), findPatMatUsages(inNestedCase(sealedClassName))) val notUsedInPatternMatch = s"""package client @@ -272,7 +272,7 @@ class ExtractUsedNamesSpecification { | val aa: $sealedClassName = ??? |}""".stripMargin - assertEquals(findPatMatUsages(notUsedInPatternMatch), Set()) + assertEquals(Set(), findPatMatUsages(notUsedInPatternMatch)) } /** From f107d7438e4a82bc4ab7b024f693ea7c98bd5315 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 3 Apr 2018 10:18:57 +0200 Subject: [PATCH 096/101] Enable sbt scripted tests --- .drone.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index 95f8582fc254..e1e42e16c0a7 100644 --- a/.drone.yml +++ b/.drone.yml @@ -49,9 +49,9 @@ pipeline: commands: - cp -R . /tmp/4/ && cd /tmp/4/ - ./project/scripts/sbt sbt-dotty/scripted - when: - # sbt scripted tests are slow and only run on nightly or deployment - event: [ tag, deployment ] + # when: + # # sbt scripted tests are slow and only run on nightly or deployment + # event: [ tag, deployment ] # DOCUMENTATION: documentation: From 9e73acaf91305c805c6057dd8c7836adc0381627 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 9 Apr 2018 23:54:53 +0200 Subject: [PATCH 097/101] Upgrade to sbt 1.1.4 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 05313438a19d..64cf32f7f961 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.1.2 +sbt.version=1.1.4 From 3f3ab9a354a5fe89dd973bf20d1efe3bc492ce3a Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Tue, 10 Apr 2018 10:58:08 +0200 Subject: [PATCH 098/101] Update docker image --- .drone.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.drone.yml b/.drone.yml index e1e42e16c0a7..53f9516b7a6a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -23,7 +23,7 @@ pipeline: # We run tests in parallel. Tests run in a copy of the working directory to avoid conflict test: group: test - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 commands: - cp -R . /tmp/1/ && cd /tmp/1/ - ./project/scripts/sbt ";compile ;test" @@ -31,21 +31,21 @@ pipeline: test_bootstrapped: group: test - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 commands: - cp -R . /tmp/2/ && cd /tmp/2/ - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" test_optimised: group: test - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 commands: - cp -R . /tmp/3/ && cd /tmp/3/ - ./project/scripts/sbt dotty-optimised/test test_sbt: group: test - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 commands: - cp -R . /tmp/4/ && cd /tmp/4/ - ./project/scripts/sbt sbt-dotty/scripted @@ -55,7 +55,7 @@ pipeline: # DOCUMENTATION: documentation: - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 commands: - ./project/scripts/genDocs secrets: [ bot_pass ] @@ -67,7 +67,7 @@ pipeline: # PUBLISHING: # Publishing expect NIGHTLYBUILD or RELEASEBUILD to be set. See dottyVersion in Build.scala publish_nightly: - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 environment: - NIGHTLYBUILD=yes commands: @@ -78,7 +78,7 @@ pipeline: environment: nightly publish_release: - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 environment: - RELEASEBUILD=yes commands: @@ -102,7 +102,7 @@ pipeline: event: tag publish_sbt_release: - image: lampepfl/dotty:2018-03-29 + image: lampepfl/dotty:2018-04-10 environment: - RELEASEBUILD=yes commands: From 08d8336031b0336973793f4f3e0489bdc032f143 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 12 Apr 2018 15:08:06 +0200 Subject: [PATCH 099/101] Fix publishing --- project/Build.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index b33b91de6558..50eda89e89f5 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -174,6 +174,11 @@ object Build { resourceDirectory in Compile := baseDirectory.value / "resources", resourceDirectory in Test := baseDirectory.value / "test-resources", + // Disable scaladoc generation, it's way too slow and we'll replace it + // by dottydoc anyway. We still publish an empty -javadoc.jar to make + // sonatype happy. + sources in (Compile, doc) := Seq(), + // Prevent sbt from rewriting our dependencies scalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(false))), @@ -680,11 +685,6 @@ object Build { } lazy val nonBootstrapedDottyCompilerSettings = commonDottyCompilerSettings ++ Seq( - // Disable scaladoc generation, it's way too slow and we'll replace it - // by dottydoc anyway. We still publish an empty -javadoc.jar to make - // sonatype happy. - sources in (Compile, doc) := Seq(), - // packageAll packages all and then returns a map with the abs location packageAll := { Map( From a15d0cdbff988ab7d8a62eb02259aa39ae647fdd Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 12 Apr 2018 15:50:13 +0200 Subject: [PATCH 100/101] Cleanup build imports --- project/Build.scala | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 50eda89e89f5..e93cbb946b88 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1,36 +1,23 @@ -import sbt.Keys._ -import sbt._ -import complete.DefaultParsers._ import java.io.File -import java.nio.channels.FileLock import java.nio.file._ -import java.util.Calendar - -import scala.reflect.io.Path +import Modes._ +import com.typesafe.sbt.pgp.PgpKeys +import com.typesafe.sbteclipse.plugin.EclipsePlugin.EclipseKeys +import sbt.Keys._ +import sbt._ +import complete.DefaultParsers._ +import pl.project13.scala.sbt.JmhPlugin +import pl.project13.scala.sbt.JmhPlugin.JmhKeys.Jmh +import sbt.Package.ManifestAttributes +import sbt.ScriptedPlugin.autoImport._ import xerial.sbt.pack.PackPlugin import xerial.sbt.pack.PackPlugin.autoImport._ -import sbt.Package.ManifestAttributes - import dotty.tools.sbtplugin.DottyPlugin.autoImport._ import dotty.tools.sbtplugin.DottyIDEPlugin.{ prepareCommand, runProcess } import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._ -import com.typesafe.sbt.pgp.PgpKeys - -import pl.project13.scala.sbt.JmhPlugin -import JmhPlugin.JmhKeys.Jmh - -import sbt.ScriptedPlugin.autoImport._ - -import xerial.sbt.pack.PackPlugin.packSettings -import xerial.sbt.pack.PackPlugin.autoImport._ - -import com.typesafe.sbteclipse.plugin.EclipsePlugin.EclipseKeys - -import Modes._ - /* In sbt 0.13 the Build trait would expose all vals to the shell, where you * can use them in "set a := b" like expressions. This re-exposes them. */ From fed52328ac09f84917bd366784017f8aaea2e855 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 12 Apr 2018 16:51:46 +0200 Subject: [PATCH 101/101] Only run scripted tests on nightly --- .drone.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index 53f9516b7a6a..07ee3a45f974 100644 --- a/.drone.yml +++ b/.drone.yml @@ -49,9 +49,9 @@ pipeline: commands: - cp -R . /tmp/4/ && cd /tmp/4/ - ./project/scripts/sbt sbt-dotty/scripted - # when: - # # sbt scripted tests are slow and only run on nightly or deployment - # event: [ tag, deployment ] + when: + # sbt scripted tests are slow and only run on nightly or deployment + event: [ tag, deployment ] # DOCUMENTATION: documentation: