From 071a00c191def09e02ac9be9fd9bad1dc6d9b75d Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 2 Feb 2019 19:01:37 +0100 Subject: [PATCH 1/8] Build.scala: Remove bootstrapFromPublishedJars setting I don't think anyone uses it, and it won't be needed anymore once we use dotty as our stage0 compiler, so removing in the name of simplicity. --- project/Build.scala | 45 ++------------------------------------------- 1 file changed, 2 insertions(+), 43 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 834b40c96907..58bddde00f9a 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -27,15 +27,6 @@ import sbtbuildinfo.BuildInfoPlugin.autoImport._ import scala.util.Properties.isJavaAtLeast -/* 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. - */ -object ExposedValues extends AutoPlugin { - object autoImport { - val bootstrapFromPublishedJars = Build.bootstrapFromPublishedJars - } -} - object Build { val scalacVersion = "2.12.8" @@ -100,8 +91,6 @@ object Build { // Shorthand for compiling a docs site val dottydoc = inputKey[Unit]("run dottydoc") - val bootstrapFromPublishedJars = settingKey[Boolean]("If true, bootstrap dotty from published non-bootstrapped dotty") - // Only available in vscode-dotty val unpublish = taskKey[Unit]("Unpublish a package") @@ -129,9 +118,6 @@ object Build { javacOptions in (Compile, compile) ++= Seq("-Xlint:unchecked", "-Xlint:deprecation"), - // Change this to true if you want to bootstrap using a published non-bootstrapped compiler - bootstrapFromPublishedJars := false, - // Override `runCode` from sbt-dotty to use the language-server and // vscode extension from the source repository of dotty instead of a // published version. @@ -251,41 +237,14 @@ object Build { // ...but scala-library is libraryDependencies += "org.scala-lang" % "scala-library" % scalacVersion, - ivyConfigurations ++= { - if (bootstrapFromPublishedJars.value) - Seq(Configurations.ScalaTool) - else - Seq() - }, - libraryDependencies ++= { - if (bootstrapFromPublishedJars.value) - Seq( - dottyOrganization %% "dotty-library" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name, - dottyOrganization %% "dotty-compiler" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name - ).map(_.withDottyCompat(scalaVersion.value)) - else - Seq() - }, - // 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 - - if (bootstrapFromPublishedJars.value) { - val jars = updateReport.select( - configuration = configurationFilter(Configurations.ScalaTool.name), - module = moduleFilter(), - artifact = artifactFilter(extension = "jar") - ) - libraryJar = jars.find(_.getName.startsWith("dotty-library_2.12")).get - compilerJar = jars.find(_.getName.startsWith("dotty-compiler_2.12")).get - } + val libraryJar = packageBin.in(`dotty-library`, Compile).value + val compilerJar = packageBin.in(`dotty-compiler`, Compile).value // All dotty-doc's and compiler's dependencies except the library. // (we get the compiler's dependencies because dottydoc depends on the compiler) From 34ae619ba12afa11af826e0221348aae560f58e8 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 2 Feb 2019 19:03:46 +0100 Subject: [PATCH 2/8] Build.scala: remove dead code --- project/Build.scala | 5 ----- 1 file changed, 5 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 58bddde00f9a..c16b4fd30ece 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -293,11 +293,6 @@ object Build { /** Projects -------------------------------------------------------------- */ - // Needed because the dotty project aggregates dotty-sbt-bridge but dotty-sbt-bridge - // currently refers to dotty in its scripted task and "aggregate" does not take by-name - // parameters: https://github.com/sbt/sbt/issues/2200 - lazy val dottySbtBridgeRef = LocalProject("dotty-sbt-bridge") - // The root project: // - aggregates other projects so that "compile", "test", etc are run on all projects at once. // - publishes its own empty artifact "dotty" that depends on "dotty-library" and "dotty-compiler", From 3c9051f6190ac9f92adfb39ecd7054ffe55ad17a Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 11 Feb 2019 13:24:24 +0100 Subject: [PATCH 3/8] sbt-dotty: replace a taskDyn by a settingDyn --- sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index 593867b58b31..96816995666e 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -163,7 +163,7 @@ object DottyPlugin extends AutoPlugin { inc }, - scalaCompilerBridgeBinaryJar := Def.taskDyn { + scalaCompilerBridgeBinaryJar := Def.settingDyn { if (isDotty.value) Def.task { val dottyBridgeArtifacts = fetchArtifactsOf("dotty-sbt-bridge", CrossVersion.disabled).value val jars = dottyBridgeArtifacts.filter(art => art.getName.startsWith("dotty-sbt-bridge") && art.getName.endsWith(".jar")).toArray From ec108de39e30b976cc8ddc36ec9b1feb0cf76900 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 2 Feb 2019 18:56:56 +0100 Subject: [PATCH 4/8] sbt-dotty: Rework classpath and ScalaInstance handling In particular, stop relying on zinc handling of the ScalaTool configuration (by setting managedScalaInstance to false) and instead fetch artifacts ourselves. Also document clearly what should end up on which classpath. --- project/Build.scala | 63 ++--- .../dotty/tools/sbtplugin/DottyPlugin.scala | 220 ++++++++++++++---- 2 files changed, 199 insertions(+), 84 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index c16b4fd30ece..6b0623c9cd9e 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -16,6 +16,7 @@ import xerial.sbt.pack.PackPlugin import xerial.sbt.pack.PackPlugin.autoImport._ import dotty.tools.sbtplugin.DottyPlugin.autoImport._ +import dotty.tools.sbtplugin.DottyPlugin.makeScalaInstance import dotty.tools.sbtplugin.DottyIDEPlugin.{ installCodeExtension, prepareCommand, runProcess } import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._ @@ -206,20 +207,6 @@ object Build { // Use the same name as the non-bootstrapped projects for the artifacts moduleName ~= { _.stripSuffix("-bootstrapped") }, - // Prevent sbt from setting the Scala bootclasspath, otherwise it will - // 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 ~= (_.withAutoBoot(false)), - // ... but when running under Java 8, we still need a Scala bootclasspath that contains the JVM bootclasspath, - // otherwise sbt incremental compilation breaks. - scalacOptions ++= { - if (isJavaAtLeast("9")) - Seq() - else - Seq("-bootclasspath", sys.props("sun.boot.class.path")) - }, - // Enforce that the only Scala 2 classfiles we unpickle come from scala-library /* scalacOptions ++= { @@ -240,34 +227,28 @@ 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 libraryJar = packageBin.in(`dotty-library`, Compile).value - val compilerJar = packageBin.in(`dotty-compiler`, Compile).value - - // All dotty-doc's and compiler's dependencies except the library. - // (we get the compiler's dependencies because dottydoc depends on the compiler) - val otherDependencies = { - val excluded = Set("dotty-library", "dotty-compiler") - fullClasspath.in(`dotty-doc`, Compile).value - .filterNot(_.get(artifact.key).exists(a => excluded.contains(a.name))) - .map(_.data) - } - - val allJars = libraryJar :: compilerJar :: otherDependencies.toList - val classLoader = state.value.classLoaderCache(allJars) - new ScalaInstance( + // TODO: Here we use the output class directories directly, this might impact + // performance when running the compiler (especially on Windows where file + // IO is slow). We should benchmark whether using jars is actually faster + // in practice (especially on our CI), this could be done using + // `exportJars := true`. + val all = fullClasspath.in(`dotty-doc`, Compile).value + def getArtifact(name: String): File = + all.find(_.get(artifact.key).exists(_.name == name)) + .getOrElse(throw new MessageOnlyException(s"Artifact for $name not found in $all")) + .data + + val scalaLibrary = getArtifact("scala-library") + val dottyLibrary = getArtifact("dotty-library") + val compiler = getArtifact("dotty-compiler") + + makeScalaInstance( + state.value, 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 + scalaLibrary, + dottyLibrary, + compiler, + all.map(_.data) ) } ) diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index 96816995666e..f6b43045eda7 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -2,11 +2,12 @@ package dotty.tools.sbtplugin import sbt._ import sbt.Keys._ -import sbt.librarymanagement.DependencyResolution +import sbt.librarymanagement._ import sbt.internal.inc.ScalaInstance import xsbti.compile._ import java.net.URLClassLoader import java.util.Optional +import scala.util.Properties.isJavaAtLeast object DottyPlugin extends AutoPlugin { object autoImport { @@ -165,7 +166,13 @@ object DottyPlugin extends AutoPlugin { scalaCompilerBridgeBinaryJar := Def.settingDyn { if (isDotty.value) Def.task { - val dottyBridgeArtifacts = fetchArtifactsOf("dotty-sbt-bridge", CrossVersion.disabled).value + val dottyBridgeArtifacts = fetchArtifactsOf( + dependencyResolution.value, + scalaModuleInfo.value, + updateConfiguration.value, + (unresolvedWarningConfiguration in update).value, + streams.value.log, + scalaOrganization.value % "dotty-sbt-bridge" % scalaVersion.value).allFiles val jars = dottyBridgeArtifacts.filter(art => art.getName.startsWith("dotty-sbt-bridge") && art.getName.endsWith(".jar")).toArray if (jars.size == 0) throw new MessageOnlyException("No jar found for dotty-sbt-bridge") @@ -187,41 +194,134 @@ object DottyPlugin extends AutoPlugin { scalaBinaryVersion.value }, + // Ideally, we should have: + // + // 1. Nothing but the Java standard library on the _JVM_ bootclasspath + // (starting with Java 9 we cannot inspect it so we don't have a choice) + // + // 2. scala-library, dotty-library, dotty-compiler, dotty-doc on the _JVM_ + // classpath, because we need all of those to actually run the compiler + // and the doc tool. + // NOTE: All of those should have the *same version* (equal to scalaVersion + // for everything but scala-library). + // + // 3. scala-library, dotty-library on the _compiler_ bootclasspath because + // user code should always have access to the symbols from these jars but + // should not be able to shadow them (the compiler bootclasspath has + // higher priority than the compiler classpath). + // NOTE: the versions of {scala,dotty}-library used here do not necessarily + // match the one used in 2. because a dependency of the current project might + // require more recent versions, this is OK. + // + // 4. every other dependency of the user project on the _compiler_ + // classpath. + // + // Unfortunately, zinc assumes that the compiler bootclasspath is only + // made of one jar (scala-library), so to make this work we'll need to + // either change sbt's bootclasspath handling or wait until the + // dotty-library jar and scala-library jars are merged into one jar. + // Furthermore, zinc will put on the compiler bootclasspath the + // scala-library used on the JVM classpath, even if the current project + // transitively depends on a newer scala-library (this works because Scala + // 2 guarantees forward- and backward- binary compatibility, but we don't + // necessarily want to keep doing that in Scala 3). + // So for the moment, let's just put nothing at all on the compiler + // bootclasspath, and instead have scala-library and dotty-library on the + // compiler classpath. This means that user code could shadow symbols + // from these jars but we can live with that for now. + classpathOptions := { + val old = classpathOptions.value + if (isDotty.value) + old + .withAutoBoot(false) // we don't put the library on the compiler bootclasspath (as explained above) + .withFilterLibrary(false) // ...instead, we put it on the compiler classpath + else + old + }, + // ... but when running under Java 8, we still need a compiler bootclasspath + // that contains the JVM bootclasspath, otherwise sbt incremental + // compilation breaks. + scalacOptions ++= { + if (isDotty.value && !isJavaAtLeast("9")) + Seq("-bootclasspath", sys.props("sun.boot.class.path")) + else + Seq() + }, + // If the current scalaVersion is N and we transitively depend on + // {scala, dotty}-{library, compiler, ...} M where M > N, we want the + // newest version on our compiler classpath, but sbt by default will + // instead rewrite all our dependencies to version N, the following line + // prevents this behavior. + scalaModuleInfo := { + val old = scalaModuleInfo.value + if (isDotty.value) + old.map(_.withOverrideScalaVersion(false)) + else + old + }, + // Prevent sbt from creating a ScalaTool configuration + managedScalaInstance := { + val old = managedScalaInstance.value + if (isDotty.value) + false + else + old + }, + // ... instead, we'll fetch the compiler and its dependencies ourselves. scalaInstance := Def.taskDyn { - val si = scalaInstance.value - if (isDotty.value) { - Def.task { - val dottydocArtifacts = fetchArtifactsOf("dotty-doc", CrossVersion.binary).value - val includeArtifact = (f: File) => f.getName.endsWith(".jar") - val dottydocJars = dottydocArtifacts.filter(includeArtifact).toArray - val allJars = (si.allJars ++ dottydocJars).distinct - val loader = new URLClassLoader(Path.toURLs(dottydocJars), si.loader) - new ScalaInstance(si.version, loader, si.loaderLibraryOnly, si.libraryJar, si.compilerJar, allJars, si.explicitActual) - } - } else { - Def.task { si } + if (isDotty.value) Def.task { + val updateReport = + fetchArtifactsOf( + dependencyResolution.value, + scalaModuleInfo.value, + updateConfiguration.value, + (unresolvedWarningConfiguration in update).value, + streams.value.log, + scalaOrganization.value %% "dotty-doc" % scalaVersion.value) + val scalaLibraryJar = getJar(updateReport, + "org.scala-lang", "scala-library", revision = AllPassFilter) + val dottyLibraryJar = getJar(updateReport, + scalaOrganization.value, s"dotty-library_${scalaBinaryVersion.value}", scalaVersion.value) + val compilerJar = getJar(updateReport, + scalaOrganization.value, s"dotty-compiler_${scalaBinaryVersion.value}", scalaVersion.value) + val allJars = + getJars(updateReport, AllPassFilter, AllPassFilter, AllPassFilter) + + makeScalaInstance( + state.value, + scalaVersion.value, + scalaLibraryJar, + dottyLibraryJar, + compilerJar, + allJars + ) + } + else Def.task { + // This should really be `old` with `val old = scalaInstance.value` + // above, except that this would force the original definition of the + // `scalaInstance` task to be computed when `isDotty` is true, which + // would fail because `managedScalaInstance` is false. + Defaults.scalaInstanceTask.value } }.value, + // Because managedScalaInstance is false, sbt won't add the standard library to our dependencies for us + libraryDependencies ++= { + if (isDotty.value && autoScalaLibrary.value) + Seq(scalaOrganization.value %% "dotty-library" % scalaVersion.value) + else + Seq() + }, + + // Turns off the warning: + // [warn] Binary version (0.9.0-RC1) for dependency ...;0.9.0-RC1 + // [warn] in ... differs from Scala binary version in project (0.9). scalaModuleInfo := { val old = scalaModuleInfo.value - if (isDotty.value) { - // Turns off the warning: - // [warn] Binary version (0.9.0-RC1) for dependency ...;0.9.0-RC1 - // [warn] in ... differs from Scala binary version in project (0.9). + if (isDotty.value) old.map(_.withCheckExplicit(false)) - } else old - }, - - updateOptions := { - val old = updateOptions.value - if (isDotty.value) { - // Turn off the warning: - // circular dependency found: - // ch.epfl.lamp#scala-library;0.9.0-RC1->ch.epfl.lamp#dotty-library_0.9;0.9.0-RC1->... - // (This should go away once we merge dotty-library and scala-library in one artefact) - old.withCircularDependencyLevel(sbt.librarymanagement.ivy.CircularDependencyLevel.Ignore) - } else old + else + old } ) ++ inConfig(Compile)(docSettings) ++ inConfig(Test)(docSettings) } @@ -236,23 +336,57 @@ object DottyPlugin extends AutoPlugin { scalacOptions += "-from-tasty" )) - /** Fetch artifacts for scalaOrganization.value %% moduleName % scalaVersion.value */ - private def fetchArtifactsOf(moduleName: String, crossVersion: CrossVersion) = Def.task { - val dependencyResolution = Keys.dependencyResolution.value - val log = streams.value.log - val scalaInfo = scalaModuleInfo.value - val updateConfiguration = Keys.updateConfiguration.value - val warningConfiguration = (unresolvedWarningConfiguration in update).value + /** Fetch artifacts for moduleID */ + def fetchArtifactsOf( + dependencyRes: DependencyResolution, + scalaInfo: Option[ScalaModuleInfo], + updateConfig: UpdateConfiguration, + warningConfig: UnresolvedWarningConfiguration, + log: Logger, + moduleID: ModuleID): UpdateReport = { + val descriptor = dependencyRes.wrapDependencyInModule(moduleID, scalaInfo) - val moduleID = (scalaOrganization.value % moduleName % scalaVersion.value).cross(crossVersion) - val descriptor = dependencyResolution.wrapDependencyInModule(moduleID, scalaInfo) - - dependencyResolution.update(descriptor, updateConfiguration, warningConfiguration, log) match { + dependencyRes.update(descriptor, updateConfig, warningConfig, log) match { case Right(report) => - report.allFiles + report case _ => throw new MessageOnlyException( - s"Couldn't retrieve `${scalaOrganization.value} %% $moduleName %% ${scalaVersion.value}`.") + s"Couldn't retrieve `$moduleID`.") } } + + /** Get all jars in updateReport that match the given filter. */ + def getJars(updateReport: UpdateReport, organization: NameFilter, name: NameFilter, revision: NameFilter): Seq[File] = { + updateReport.select( + configurationFilter(Runtime.name), + moduleFilter(organization, name, revision), + artifactFilter(extension = "jar") + ) + } + + /** Get the single jar in updateReport that match the given filter. + * If zero or more than one jar match, an exception will be thrown. */ + def getJar(updateReport: UpdateReport, organization: NameFilter, name: NameFilter, revision: NameFilter): File = { + val jars = getJars(updateReport, organization, name, revision) + assert(jars.size == 1, s"There should only be one $name jar but found: $jars") + jars.head + } + + def makeScalaInstance( + state: State, dottyVersion: String, scalaLibrary: File, dottyLibrary: File, compiler: File, all: Seq[File] + ): ScalaInstance = { + val loader = state.classLoaderCache(all.toList) + val loaderLibraryOnly = state.classLoaderCache(List(dottyLibrary, scalaLibrary)) + new ScalaInstance( + dottyVersion, + loader, + loaderLibraryOnly, + scalaLibrary, // Should be a Seq also containing dottyLibrary but zinc + // doesn't support this, see comment above our redefinition + // of `classpathOption` + compiler, + all.toArray, + None) + + } } From dd9fd1144b8792551c7f5e5ab8aaa49f42e6b5c4 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 11 Feb 2019 15:08:34 +0100 Subject: [PATCH 5/8] sbt-dotty: Make withDottyCompat work with dotty dependencies Now that we add dotty-library to libraryDependencies, we need to be more careful to make this work: libraryDependencies ~= (_.map(_.withDottyCompat(scalaVersion.value))) This is needed to keep the community-build working. --- .../dotty/tools/sbtplugin/DottyPlugin.scala | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index f6b43045eda7..f4c9638d8cd0 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -72,16 +72,25 @@ object DottyPlugin extends AutoPlugin { * 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. + * NOTE: As a special-case, the cross-version of dotty-library, dotty-compiler and + * dotty will never be rewritten because we know that they're Dotty-only. + * This makes it possible to do something like: + * {{{ + * libraryDependencies ~= (_.map(_.withDottyCompat(scalaVersion.value))) + * }}} */ - def withDottyCompat(scalaVersion: String): ModuleID = - moduleID.crossVersion match { - case _: librarymanagement.Binary if scalaVersion.startsWith("0.") => - moduleID.cross(CrossVersion.constant("2.12")) - case _ => - moduleID - } + def withDottyCompat(scalaVersion: String): ModuleID = { + val name = moduleID.name + if (name != "dotty" && name != "dotty-library" && name != "dotty-compiler") + moduleID.crossVersion match { + case _: librarymanagement.Binary if scalaVersion.startsWith("0.") => + moduleID.cross(CrossVersion.constant("2.12")) + case _ => + moduleID + } + else + moduleID + } } } From 90b3820e35bff1921dbd8aec485e47791b2f0608 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 2 Feb 2019 19:18:56 +0100 Subject: [PATCH 6/8] sbt-dotty: Fix minimum sbt version check This fixes #5671. Also bump the minimum version to 1.2.7 due to scalaCompilerBridgeBinaryJar usage, etc. --- .../dotty/tools/sbtplugin/DottyPlugin.scala | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index f4c9638d8cd0..00457de3dbae 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -2,7 +2,10 @@ package dotty.tools.sbtplugin import sbt._ import sbt.Keys._ -import sbt.librarymanagement._ +import sbt.librarymanagement.{ + ivy, DependencyResolution, ScalaModuleInfo, SemanticSelector, UpdateConfiguration, UnresolvedWarningConfiguration, + VersionNumber +} import sbt.internal.inc.ScalaInstance import xsbti.compile._ import java.net.URLClassLoader @@ -99,20 +102,6 @@ object DottyPlugin extends AutoPlugin { override def requires: Plugins = plugins.JvmPlugin override def trigger = allRequirements - // Adapted from CrossVersionUtil#sbtApiVersion - private def sbtFullVersion(v: String): Option[(Int, Int, Int)] = - { - val ReleaseV = """(\d+)\.(\d+)\.(\d+)(-\d+)?""".r - val CandidateV = """(\d+)\.(\d+)\.(\d+)(-RC\d+)""".r - val NonReleaseV = """(\d+)\.(\d+)\.(\d+)([-\w+]*)""".r - v match { - case ReleaseV(x, y, z, ht) => Some((x.toInt, y.toInt, z.toInt)) - case CandidateV(x, y, z, ht) => Some((x.toInt, y.toInt, z.toInt)) - case NonReleaseV(x, y, z, ht) if z.toInt > 0 => Some((x.toInt, y.toInt, z.toInt)) - case _ => None - } - } - /** Patches the IncOptions so that .tasty and .hasTasty files are pruned as needed. * * This code is adapted from `scalaJSPatchIncOptions` in Scala.js, which needs @@ -142,12 +131,13 @@ object DottyPlugin extends AutoPlugin { override val globalSettings: Seq[Def.Setting[_]] = Seq( onLoad in Global := onLoad.in(Global).value.andThen { state => + + val requiredVersion = ">=1.2.7" + val sbtV = sbtVersion.value - sbtFullVersion(sbtV) match { - case Some((1, sbtMinor, sbtPatch)) if sbtMinor > 1 || (sbtMinor == 1 && sbtPatch >= 5) => - case _ => - sys.error(s"The sbt-dotty plugin cannot work with this version of sbt ($sbtV), sbt >= 1.1.5 is required.") - } + if (!VersionNumber(sbtV).matchesSemVer(SemanticSelector(requiredVersion))) + sys.error(s"The sbt-dotty plugin cannot work with this version of sbt ($sbtV), sbt $requiredVersion is required.") + state } ) From 668a8b3ea6119eeff1b44e09387db5d55cbbb317 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 2 Feb 2019 23:27:01 +0100 Subject: [PATCH 7/8] sbt-dotty: Release 0.3.0 --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index 6b0623c9cd9e..764463ee9015 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -32,7 +32,7 @@ object Build { val scalacVersion = "2.12.8" val baseVersion = "0.13.0" - val baseSbtDottyVersion = "0.2.7" + val baseSbtDottyVersion = "0.3.0" // Versions used by the vscode extension to create a new project // This should be the latest published releases. From 6e92463932ac40130285da2ec96957f9a59d13bb Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 13 Feb 2019 17:50:34 +0100 Subject: [PATCH 8/8] sbt-dotty: Bump to 0.3.1 --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index 764463ee9015..6bcca2ac4537 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -32,7 +32,7 @@ object Build { val scalacVersion = "2.12.8" val baseVersion = "0.13.0" - val baseSbtDottyVersion = "0.3.0" + val baseSbtDottyVersion = "0.3.1" // Versions used by the vscode extension to create a new project // This should be the latest published releases.