From 8c6f71a18057217ade4d56b9d1f6be1a7e2a15ae Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Thu, 12 Apr 2018 12:30:11 -0700 Subject: [PATCH 01/27] Bump io My next commit replaces the implementation of Watched.executeContinuously using apis that are available only in a pending io pull request (https://github.com/sbt/io/pull/142). --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index bcefc8b4e..81aced917 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,7 +8,7 @@ object Dependencies { val baseScalaVersion = scala212 // sbt modules - private val ioVersion = "1.1.6" + private val ioVersion = "1.1.6-SNAPSHOT" private val utilVersion = "1.1.3" private val lmVersion = "1.1.4" private val zincVersion = "1.1.5" From 754385125acb1debb5bb95e6b1b690a8dd73eb9e Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Thu, 12 Apr 2018 13:06:54 -0700 Subject: [PATCH 02/27] Use new EventMonitor in executeContinuously In https://github.com/sbt/io/pull/142, I add a new api for watching for source file events. This commit updates sbt to use the new EventMonitor based api. The EventMonitor has an anti-entropy parameter, so that multiple events on the same file in a short window of time do not trigger a build. I add a key to tune it. The implementation of executeContinuously is pretty similar. The main changes are that shouldTerminate now blocks (EventMonitor spins up a thread to check the termination condition) and that the EventMonitor.watch method only returns a Boolean. This is because the event monitor contains mutable state. It does, however, have a state() method that returns an immutable snapshot of the state. --- main-command/src/main/scala/sbt/Watched.scala | 81 ++++++++++++------- main/src/main/scala/sbt/Defaults.scala | 5 +- main/src/main/scala/sbt/Keys.scala | 1 + 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/main-command/src/main/scala/sbt/Watched.scala b/main-command/src/main/scala/sbt/Watched.scala index cff9c1597..029702841 100644 --- a/main-command/src/main/scala/sbt/Watched.scala +++ b/main-command/src/main/scala/sbt/Watched.scala @@ -12,7 +12,7 @@ import java.nio.file.FileSystems import sbt.BasicCommandStrings.ClearOnFailure import sbt.State.FailureWall -import sbt.internal.io.{ Source, SourceModificationWatch, WatchState } +import sbt.internal.io.{ EventMonitor, Source, SourceModificationWatch, WatchState } import sbt.internal.util.AttributeKey import sbt.internal.util.Types.const import sbt.io._ @@ -33,6 +33,12 @@ trait Watched { */ def pollInterval: FiniteDuration = Watched.PollDelay + /** + * The duration for which the EventMonitor while ignore file events after a file triggers + * a new build. + */ + def antiEntropy: FiniteDuration = Watched.AntiEntropy + /** The message to show when triggered execution waits for sources to change.*/ private[sbt] def watchingMessage(s: WatchState): String = Watched.defaultWatchingMessage(s) @@ -81,52 +87,65 @@ object Watched { override def watchSources(s: State) = (base.watchSources(s) /: paths)(_ ++ _.watchSources(s)) override def terminateWatch(key: Int): Boolean = base.terminateWatch(key) override val pollInterval = (base +: paths).map(_.pollInterval).min + override val antiEntropy = (base +: paths).map(_.antiEntropy).min override def watchingMessage(s: WatchState) = base.watchingMessage(s) override def triggeredMessage(s: WatchState) = base.triggeredMessage(s) } def empty: Watched = new AWatched val PollDelay: FiniteDuration = 500.milliseconds + val AntiEntropy: FiniteDuration = 40.milliseconds def isEnter(key: Int): Boolean = key == 10 || key == 13 def printIfDefined(msg: String) = if (!msg.isEmpty) System.out.println(msg) def executeContinuously(watched: Watched, s: State, next: String, repeat: String): State = { @tailrec def shouldTerminate: Boolean = - (System.in.available > 0) && (watched.terminateWatch(System.in.read()) || shouldTerminate) - val sources = watched.watchSources(s) - val service = s get ContinuousWatchService getOrElse watched.watchService() - val watchState = s get ContinuousState getOrElse WatchState.empty(service, sources) - - if (watchState.count > 0) - printIfDefined(watched watchingMessage watchState) - - val (triggered, newWatchState) = - try { - val (triggered, newWatchState) = - SourceModificationWatch.watch(watched.pollInterval, watchState)(shouldTerminate) - (triggered, newWatchState) - } catch { - case e: Exception => - val log = s.log - log.error("Error occurred obtaining files to watch. Terminating continuous execution...") - State.handleException(e, s, log) - (false, watchState) - } - - if (triggered) { - printIfDefined(watched triggeredMessage newWatchState) - (ClearOnFailure :: next :: FailureWall :: repeat :: s) - .put(ContinuousState, newWatchState) - .put(ContinuousWatchService, service) - } else { - while (System.in.available() > 0) System.in.read() - service.close() - s.remove(ContinuousState).remove(ContinuousWatchService) + watched.terminateWatch(System.in.read()) || shouldTerminate + val log = s.log + val logger = new EventMonitor.Logger { + override def debug(msg: => Any): Unit = log.debug(msg.toString) + } + s get ContinuousEventMonitor match { + case None => + // This is the first iteration, so run the task and create a new EventMonitor + (ClearOnFailure :: next :: FailureWall :: repeat :: s) + .put( + ContinuousEventMonitor, + EventMonitor(WatchState.empty(watched.watchService(), watched.watchSources(s)), + watched.pollInterval, + watched.antiEntropy, + shouldTerminate, + logger) + ) + case Some(eventMonitor) => + printIfDefined(watched watchingMessage eventMonitor.state) + val triggered = try eventMonitor.watch() + catch { + case e: Exception => + log.error( + "Error occurred obtaining files to watch. Terminating continuous execution...") + State.handleException(e, s, log) + false + } + if (triggered) { + printIfDefined(watched triggeredMessage eventMonitor.state) + ClearOnFailure :: next :: FailureWall :: repeat :: s + } else { + while (System.in.available() > 0) System.in.read() + eventMonitor.close() + s.remove(ContinuousEventMonitor) + } } } + + val ContinuousEventMonitor = + AttributeKey[EventMonitor]("watch event monitor", + "Internal: maintains watch state and monitor threads.") + @deprecated("Superseded by ContinuousEventMonitor", "1.1.5") val ContinuousState = AttributeKey[WatchState]("watch state", "Internal: tracks state for continuous execution.") + @deprecated("Superseded by ContinuousEventMonitor", "1.1.5") val ContinuousWatchService = AttributeKey[WatchService]("watch service", "Internal: tracks watch service for continuous execution.") diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 82af2a9e4..e34ccfc04 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -248,6 +248,7 @@ object Defaults extends BuildCommon { concurrentRestrictions := defaultRestrictions.value, parallelExecution :== true, pollInterval :== new FiniteDuration(500, TimeUnit.MILLISECONDS), + watchAntiEntropy :== new FiniteDuration(40, TimeUnit.MILLISECONDS), watchService :== { () => Watched.createWatchService() }, @@ -555,13 +556,15 @@ object Defaults extends BuildCommon { Def.setting { val getService = watchService.value val interval = pollInterval.value + val _antiEntropy = watchAntiEntropy.value val base = thisProjectRef.value val msg = watchingMessage.value val trigMsg = triggeredMessage.value new Watched { val scoped = watchTransitiveSources in base val key = scoped.scopedKey - override def pollInterval = interval + override def antiEntropy: FiniteDuration = _antiEntropy + override def pollInterval: FiniteDuration = interval override def watchingMessage(s: WatchState) = msg(s) override def triggeredMessage(s: WatchState) = trigMsg(s) override def watchService() = getService() diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 8e26b54fb..473bfffba 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -140,6 +140,7 @@ object Keys { val analysis = AttributeKey[CompileAnalysis]("analysis", "Analysis of compilation, including dependencies and generated outputs.", DSetting) val watch = SettingKey(BasicKeys.watch) val suppressSbtShellNotification = settingKey[Boolean]("""True to suppress the "Executing in batch mode.." message.""").withRank(CSetting) + val watchAntiEntropy = settingKey[FiniteDuration]("Duration for which the watch EventMonitor will ignore events for a file after that file has triggered a build.").withRank(BMinusSetting) val pollInterval = settingKey[FiniteDuration]("Interval between checks for modified sources by the continuous execution command.").withRank(BMinusSetting) val watchService = settingKey[() => WatchService]("Service to use to monitor file system changes.").withRank(BMinusSetting) val watchSources = taskKey[Seq[Watched.WatchSource]]("Defines the sources in this project for continuous execution to watch for changes.").withRank(BMinusSetting) From 0de8345e33a40964edbb5420a0fd03a5a37e5bcb Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Fri, 13 Apr 2018 14:11:07 -0700 Subject: [PATCH 03/27] Remove watch loops When source generators write into the unmanaged source directory, bad things can happen. Continuous builds will loop indefinitely and compiling will fail because the generated sources get added to the source list twice, causing the incremental compiler to complain about compiling classes it has already seen. My two-pronged solution is to de-duplicate the sources task and to filter out managed source files in watch sources. The drawback to the latter is that it causes the source generation task to be executed twice per compile. --- main/src/main/scala/sbt/Defaults.scala | 15 +++++++++++++-- sbt/src/sbt-test/tests/watch-loop/build.sbt | 17 +++++++++++++++++ .../watch-loop/project/SourceWrapper.scala | 6 ++++++ .../tests/watch-loop/src/main/scala/Bar.scala | 1 + .../tests/watch-loop/src/main/scala/Foo.scala | 1 + sbt/src/sbt-test/tests/watch-loop/test | 1 + 6 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 sbt/src/sbt-test/tests/watch-loop/build.sbt create mode 100644 sbt/src/sbt-test/tests/watch-loop/project/SourceWrapper.scala create mode 100644 sbt/src/sbt-test/tests/watch-loop/src/main/scala/Bar.scala create mode 100644 sbt/src/sbt-test/tests/watch-loop/src/main/scala/Foo.scala create mode 100644 sbt/src/sbt-test/tests/watch-loop/test diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 82af2a9e4..847d95ee2 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -329,7 +329,18 @@ object Defaults extends BuildCommon { val baseDir = baseDirectory.value val bases = unmanagedSourceDirectories.value val include = (includeFilter in unmanagedSources).value - val exclude = (excludeFilter in unmanagedSources).value + val exclude = (excludeFilter in unmanagedSources).value match { + case e => + (managedSources in ThisScope).value match { + case l if l.nonEmpty => + e || new FileFilter { + private val files = l.toSet + override def accept(pathname: File): Boolean = files.contains(pathname) + override def toString = s"ManagedSourcesFilter($files)" + } + case _ => e + } + } val baseSources = if (sourcesInBase.value) Seq(new Source(baseDir, include, exclude, recursive = false)) else Nil @@ -341,7 +352,7 @@ object Defaults extends BuildCommon { sourceDirectories := Classpaths .concatSettings(unmanagedSourceDirectories, managedSourceDirectories) .value, - sources := Classpaths.concat(unmanagedSources, managedSources).value + sources := Classpaths.concatDistinct(unmanagedSources, managedSources).value ) lazy val resourceConfigPaths = Seq( resourceDirectory := sourceDirectory.value / "resources", diff --git a/sbt/src/sbt-test/tests/watch-loop/build.sbt b/sbt/src/sbt-test/tests/watch-loop/build.sbt new file mode 100644 index 000000000..effea2c79 --- /dev/null +++ b/sbt/src/sbt-test/tests/watch-loop/build.sbt @@ -0,0 +1,17 @@ +import java.nio.file.Files + +lazy val watchLoopTest = taskKey[Unit]("Check that managed sources are filtered") + +sourceGenerators in Compile += Def.task { + val path = baseDirectory.value.toPath.resolve("src/main/scala/Foo.scala") + Files.write(path, "object Foo".getBytes).toFile :: Nil +} + +watchLoopTest := { + val watched = watchSources.value + val managedSource = (managedSources in Compile).value.head + assert(!SourceWrapper.accept(watched, managedSource)) + assert((sources in Compile).value.foldLeft((true, Set.empty[File])) { + case ((res, set), f) => (res && !set.contains(f), set + f) + }._1) +} diff --git a/sbt/src/sbt-test/tests/watch-loop/project/SourceWrapper.scala b/sbt/src/sbt-test/tests/watch-loop/project/SourceWrapper.scala new file mode 100644 index 000000000..ff351168a --- /dev/null +++ b/sbt/src/sbt-test/tests/watch-loop/project/SourceWrapper.scala @@ -0,0 +1,6 @@ +package sbt + +object SourceWrapper { + def accept(sources: Seq[sbt.internal.io.Source], file: File): Boolean = + sources.exists(_.accept(file.toPath)) +} diff --git a/sbt/src/sbt-test/tests/watch-loop/src/main/scala/Bar.scala b/sbt/src/sbt-test/tests/watch-loop/src/main/scala/Bar.scala new file mode 100644 index 000000000..3b43dece6 --- /dev/null +++ b/sbt/src/sbt-test/tests/watch-loop/src/main/scala/Bar.scala @@ -0,0 +1 @@ +object Bar diff --git a/sbt/src/sbt-test/tests/watch-loop/src/main/scala/Foo.scala b/sbt/src/sbt-test/tests/watch-loop/src/main/scala/Foo.scala new file mode 100644 index 000000000..d37c10456 --- /dev/null +++ b/sbt/src/sbt-test/tests/watch-loop/src/main/scala/Foo.scala @@ -0,0 +1 @@ +object Foo \ No newline at end of file diff --git a/sbt/src/sbt-test/tests/watch-loop/test b/sbt/src/sbt-test/tests/watch-loop/test new file mode 100644 index 000000000..41d621982 --- /dev/null +++ b/sbt/src/sbt-test/tests/watch-loop/test @@ -0,0 +1 @@ +> watchLoopTest From 5d63035a273670e75984eb837292bd4a863ecab1 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Mon, 9 Apr 2018 10:15:32 +0200 Subject: [PATCH 04/27] Fix #4073: support detect dotty plugins --- main/src/main/scala/sbt/Defaults.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 82af2a9e4..6e99870fe 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2887,7 +2887,8 @@ object Classpaths { def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File]): Seq[String] = { val pluginClasspath = report.matching(configurationFilter(CompilerPlugin.name)) ++ internalPluginClasspath - val plugins = sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath) + val version = scalaVersion.value + val plugins = sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath, scalaInstance.isDotty(version)) plugins.map("-Xplugin:" + _.getAbsolutePath).toSeq } From 9ad1b120c10471c654d03972e6250a57f6a8aefc Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Mon, 9 Apr 2018 10:51:58 +0200 Subject: [PATCH 05/27] add notes --- notes/1.1.1/dotty-plugin.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 notes/1.1.1/dotty-plugin.md diff --git a/notes/1.1.1/dotty-plugin.md b/notes/1.1.1/dotty-plugin.md new file mode 100644 index 000000000..6250c30dd --- /dev/null +++ b/notes/1.1.1/dotty-plugin.md @@ -0,0 +1,9 @@ +[@liufengyun]: https://github.com/liufengyun + +[4073]: https://github.com/sbt/sbt/issues/4073 +[4084]: https://github.com/sbt/sbt/pull/4084 + + +### Improvements + +- Detect dotty plugins which have descriptor file named `plugin.properties` instead of `scalac-plugin.xml`. [#4073][4073]/[#4084][4084] by [@liufengyun][@liufengyun] From 83212785b02060ee9907e31ee80dc44ce2307dac Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Mon, 9 Apr 2018 10:59:46 +0200 Subject: [PATCH 06/27] add dotty plugin test --- .../dotty-compiler-plugin/build.sbt | 19 +++++++++ .../plugin/DivideZero.scala | 40 +++++++++++++++++++ .../src/main/resources/plugin.properties | 1 + .../dotty-compiler-plugin/project/plugins.sbt | 1 + .../src/main/scala/hello/Hello.scala | 13 ++++++ .../dotty-compiler-plugin/test | 2 + 6 files changed, 76 insertions(+) create mode 100644 sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt create mode 100644 sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala create mode 100644 sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/src/main/resources/plugin.properties create mode 100644 sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt create mode 100644 sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/src/main/scala/hello/Hello.scala create mode 100644 sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/test diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt new file mode 100644 index 000000000..19d921ef1 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt @@ -0,0 +1,19 @@ +lazy val dottyVersion = dottyLatestNightlyBuild + +lazy val pluginSetting = Seq( + name := "dividezero", + version := "0.0.1", + organization := "ch.epfl.lamp", + scalaVersion := dottyVersion, + + libraryDependencies ++= Seq( + "ch.epfl.lamp" %% "dotty" % "provided" + ) +) + +lazy val plugin = (project in file("plugin")).settings(pluginSetting: _*) + +lazy val app = (project in file(".")).settings( + scalaVersion := dottyVersion, + libraryDependencies += compilerPlugin("ch.epfl.lamp" %% "dividezero" % "0.0.1") +) diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala new file mode 100644 index 000000000..1dfe23cf5 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala @@ -0,0 +1,40 @@ +package dividezero + +import dotty.tools.dotc._ +import core._ +import Contexts.Context +import plugins._ +import Phases.Phase +import ast.tpd +import transform.MegaPhase.MiniPhase +import Decorators._ +import Symbols.Symbol +import Constants.Constant +import transform.{LinkAll, Pickler} + +class DivideZero extends PluginPhase with StandardPlugin { + val name: String = "divideZero" + override val description: String = "divide zero check" + + val phaseName = name + + override val runsAfter = Set(Pickler.phaseName) + override val runsBefore = Set(LinkAll.phaseName) + + override def init(options: List[String]): List[PluginPhase] = this :: Nil + + private def isNumericDivide(sym: Symbol)(implicit ctx: Context): Boolean = { + def test(tpe: String): Boolean = + (sym.owner eq ctx.requiredClass(tpe.toTermName)) && sym.name.show == "/" + + test("scala.Int") || test("scala.Long") || test("scala.Short") || test("scala.Float") || test("scala.Double") + } + + override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = tree match { + case tpd.Apply(fun, tpd.Literal(Constants.Constant(v)) :: Nil) if isNumericDivide(fun.symbol) && v == 0 => + ctx.warning("divide by zero", tree.pos) + tpd.Literal(Constant(0)) + case _ => + tree + } +} diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/src/main/resources/plugin.properties b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/src/main/resources/plugin.properties new file mode 100644 index 000000000..db215842c --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/src/main/resources/plugin.properties @@ -0,0 +1 @@ +pluginClass=dividezero.DivideZero \ No newline at end of file diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt new file mode 100644 index 000000000..57022ad6b --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.1.7") diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/src/main/scala/hello/Hello.scala b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/src/main/scala/hello/Hello.scala new file mode 100644 index 000000000..99ae2d0d7 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/src/main/scala/hello/Hello.scala @@ -0,0 +1,13 @@ +package hello +object Hello { + def main(args: Array[String]): Unit = { + val dotty: Int | String = "dotty" + + val y = 5 / 0 // error + 100 + 6 / 0 // error + 6L / 0L // error + val z = 7 / 0.0 // error + + println(s"Hello $dotty!") + } +} diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/test b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/test new file mode 100644 index 000000000..28c06d4d6 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/test @@ -0,0 +1,2 @@ +> plugin/publishLocal +> app/run From 06cf5e56356bcded9f65dd162722a0c813592db1 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Fri, 13 Apr 2018 14:16:23 +0200 Subject: [PATCH 07/27] update sbt-dotty version --- .../compiler-project/dotty-compiler-plugin/project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt index 57022ad6b..ba89aa2bb 100644 --- a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.1.7") +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.2.0") From ecbfdfef25f20ec497448cf6bbbe6aa1fa55d13b Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Thu, 3 May 2018 22:36:17 +0200 Subject: [PATCH 08/27] fix compilation error --- main/src/main/scala/sbt/Defaults.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 6e99870fe..3aaf9858a 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2885,10 +2885,9 @@ object Classpaths { excl: FileFilter): Classpath = (base * (filter -- excl) +++ (base / config.name).descendantsExcept(filter, excl)).classpath - def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File]): Seq[String] = { + def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File], scalaVersion: String): Seq[String] = { val pluginClasspath = report.matching(configurationFilter(CompilerPlugin.name)) ++ internalPluginClasspath - val version = scalaVersion.value - val plugins = sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath, scalaInstance.isDotty(version)) + val plugins = sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath, ScalaInstance.isDotty(scalaVersion)) plugins.map("-Xplugin:" + _.getAbsolutePath).toSeq } @@ -2908,7 +2907,7 @@ object Classpaths { lazy val compilerPluginConfig = Seq( scalacOptions := { val options = scalacOptions.value - val newPlugins = autoPlugins(update.value, internalCompilerPluginClasspath.value.files) + val newPlugins = autoPlugins(update.value, internalCompilerPluginClasspath.value.files, scalaVersion.value) val existing = options.toSet if (autoCompilerPlugins.value) options ++ newPlugins.filterNot(existing) else options } From adf045d4f86225064215dd9a73abc3897b7ee2e2 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Fri, 4 May 2018 16:39:05 +0200 Subject: [PATCH 09/27] move notes to 1.1.5 --- notes/{1.1.1 => 1.1.5}/dotty-plugin.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename notes/{1.1.1 => 1.1.5}/dotty-plugin.md (100%) diff --git a/notes/1.1.1/dotty-plugin.md b/notes/1.1.5/dotty-plugin.md similarity index 100% rename from notes/1.1.1/dotty-plugin.md rename to notes/1.1.5/dotty-plugin.md From 50f2ebce8817a28bbba2522ddb7f7639b04a3400 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Fri, 4 May 2018 17:00:25 +0200 Subject: [PATCH 10/27] overload autoPlugins for binary compatibility --- main/src/main/scala/sbt/Defaults.scala | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 3aaf9858a..fa65596fa 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2885,9 +2885,14 @@ object Classpaths { excl: FileFilter): Classpath = (base * (filter -- excl) +++ (base / config.name).descendantsExcept(filter, excl)).classpath - def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File], scalaVersion: String): Seq[String] = { + + @deprecated("The method only works for Scalac, use the overloaded version to support both Scalac and Dotty", "1.1.5") + def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File]): Seq[String] = + autoPlugins(report, internalPluginClasspath, isDotty = false) + + def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File], isDotty: Boolean): Seq[String] = { val pluginClasspath = report.matching(configurationFilter(CompilerPlugin.name)) ++ internalPluginClasspath - val plugins = sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath, ScalaInstance.isDotty(scalaVersion)) + val plugins = sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath, isDotty) plugins.map("-Xplugin:" + _.getAbsolutePath).toSeq } @@ -2907,7 +2912,7 @@ object Classpaths { lazy val compilerPluginConfig = Seq( scalacOptions := { val options = scalacOptions.value - val newPlugins = autoPlugins(update.value, internalCompilerPluginClasspath.value.files, scalaVersion.value) + val newPlugins = autoPlugins(update.value, internalCompilerPluginClasspath.value.files, ScalaInstance.isDotty(scalaVersion.value)) val existing = options.toSet if (autoCompilerPlugins.value) options ++ newPlugins.filterNot(existing) else options } From 1057dcd2914af02924513661a74f85a4b1915053 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Fri, 4 May 2018 17:10:50 +0200 Subject: [PATCH 11/27] update deprecated message --- main/src/main/scala/sbt/Defaults.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index fa65596fa..ff93c1097 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2886,7 +2886,7 @@ object Classpaths { (base * (filter -- excl) +++ (base / config.name).descendantsExcept(filter, excl)).classpath - @deprecated("The method only works for Scalac, use the overloaded version to support both Scalac and Dotty", "1.1.5") + @deprecated("The method only works for Scala 2, use the overloaded version to support both Scala 2 and Scala 3", "1.1.5") def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File]): Seq[String] = autoPlugins(report, internalPluginClasspath, isDotty = false) From 38d53a941a8d1ac374ba02b853fa4cf1f549efe5 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 5 May 2018 04:53:34 -0400 Subject: [PATCH 12/27] IO 1.1.7, Zinc 1.1.6 --- project/Dependencies.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index b1e9fd0ab..a3e2d35fa 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,10 +8,10 @@ object Dependencies { val baseScalaVersion = scala212 // sbt modules - private val ioVersion = "1.1.6" + private val ioVersion = "1.1.7" private val utilVersion = "1.1.3" private val lmVersion = "1.1.4" - private val zincVersion = "1.1.5" + private val zincVersion = "1.1.6" private val sbtIO = "org.scala-sbt" %% "io" % ioVersion From 094c2c602dd808a4cf0ed5acc76710e74e919274 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 5 May 2018 04:57:14 -0400 Subject: [PATCH 13/27] Formatting --- main/src/main/scala/sbt/Defaults.scala | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index ff93c1097..f78eaeb7b 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2884,15 +2884,18 @@ object Classpaths { filter: FileFilter, excl: FileFilter): Classpath = (base * (filter -- excl) +++ (base / config.name).descendantsExcept(filter, excl)).classpath - - - @deprecated("The method only works for Scala 2, use the overloaded version to support both Scala 2 and Scala 3", "1.1.5") + @deprecated( + "The method only works for Scala 2, use the overloaded version to support both Scala 2 and Scala 3", + "1.1.5") def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File]): Seq[String] = autoPlugins(report, internalPluginClasspath, isDotty = false) - def autoPlugins(report: UpdateReport, internalPluginClasspath: Seq[File], isDotty: Boolean): Seq[String] = { + def autoPlugins(report: UpdateReport, + internalPluginClasspath: Seq[File], + isDotty: Boolean): Seq[String] = { val pluginClasspath = report.matching(configurationFilter(CompilerPlugin.name)) ++ internalPluginClasspath - val plugins = sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath, isDotty) + val plugins = + sbt.internal.inc.classpath.ClasspathUtilities.compilerPlugins(pluginClasspath, isDotty) plugins.map("-Xplugin:" + _.getAbsolutePath).toSeq } @@ -2912,7 +2915,9 @@ object Classpaths { lazy val compilerPluginConfig = Seq( scalacOptions := { val options = scalacOptions.value - val newPlugins = autoPlugins(update.value, internalCompilerPluginClasspath.value.files, ScalaInstance.isDotty(scalaVersion.value)) + val newPlugins = autoPlugins(update.value, + internalCompilerPluginClasspath.value.files, + ScalaInstance.isDotty(scalaVersion.value)) val existing = options.toSet if (autoCompilerPlugins.value) options ++ newPlugins.filterNot(existing) else options } From d8fe09f00776ad45d404fe0319df237bef8cc00f Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 5 May 2018 05:02:53 -0400 Subject: [PATCH 14/27] Adjust to upstream change --- main-command/src/main/scala/sbt/Watched.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main-command/src/main/scala/sbt/Watched.scala b/main-command/src/main/scala/sbt/Watched.scala index 029702841..73e177f83 100644 --- a/main-command/src/main/scala/sbt/Watched.scala +++ b/main-command/src/main/scala/sbt/Watched.scala @@ -12,7 +12,7 @@ import java.nio.file.FileSystems import sbt.BasicCommandStrings.ClearOnFailure import sbt.State.FailureWall -import sbt.internal.io.{ EventMonitor, Source, SourceModificationWatch, WatchState } +import sbt.internal.io.{ EventMonitor, Source, WatchState } import sbt.internal.util.AttributeKey import sbt.internal.util.Types.const import sbt.io._ @@ -119,7 +119,7 @@ object Watched { ) case Some(eventMonitor) => printIfDefined(watched watchingMessage eventMonitor.state) - val triggered = try eventMonitor.watch() + val triggered = try eventMonitor.awaitEvent() catch { case e: Exception => log.error( From 2b099c86b546a14439972494edbe12275db51f92 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 5 May 2018 15:19:47 -0400 Subject: [PATCH 15/27] Fix Dotty plugin test Ref https://github.com/sbt/sbt/pull/4084 --- .../dotty-compiler-plugin/build.sbt | 29 +++++++++---------- .../plugin/DivideZero.scala | 4 +-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt index 19d921ef1..099cd9f71 100644 --- a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/build.sbt @@ -1,19 +1,16 @@ -lazy val dottyVersion = dottyLatestNightlyBuild +// hardcode dottyVersion to make test deterministic +lazy val dottyVersion = "0.8.0-bin-20180424-e77604d-NIGHTLY" -lazy val pluginSetting = Seq( - name := "dividezero", - version := "0.0.1", - organization := "ch.epfl.lamp", - scalaVersion := dottyVersion, - - libraryDependencies ++= Seq( - "ch.epfl.lamp" %% "dotty" % "provided" +lazy val plugin = (project in file("plugin")) + .settings( + name := "dividezero", + version := "0.0.1", + organization := "ch.epfl.lamp", + scalaVersion := dottyVersion, ) -) -lazy val plugin = (project in file("plugin")).settings(pluginSetting: _*) - -lazy val app = (project in file(".")).settings( - scalaVersion := dottyVersion, - libraryDependencies += compilerPlugin("ch.epfl.lamp" %% "dividezero" % "0.0.1") -) +lazy val app = (project in file(".")) + .settings( + scalaVersion := dottyVersion, + libraryDependencies += compilerPlugin("ch.epfl.lamp" %% "dividezero" % "0.0.1"), + ) diff --git a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala index 1dfe23cf5..c110a7cee 100644 --- a/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala +++ b/sbt/src/sbt-test/compiler-project/dotty-compiler-plugin/plugin/DivideZero.scala @@ -18,8 +18,8 @@ class DivideZero extends PluginPhase with StandardPlugin { val phaseName = name - override val runsAfter = Set(Pickler.phaseName) - override val runsBefore = Set(LinkAll.phaseName) + override val runsAfter = Set(Pickler.name) + override val runsBefore = Set(LinkAll.name) override def init(options: List[String]): List[PluginPhase] = this :: Nil From 24946189f093003246f0cfbf06d5a4955717d116 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 7 May 2018 16:18:46 -0400 Subject: [PATCH 16/27] Zinc 1.1.7 --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index a3e2d35fa..c97af475b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -11,7 +11,7 @@ object Dependencies { private val ioVersion = "1.1.7" private val utilVersion = "1.1.3" private val lmVersion = "1.1.4" - private val zincVersion = "1.1.6" + private val zincVersion = "1.1.7" private val sbtIO = "org.scala-sbt" %% "io" % ioVersion From d3ac5274b3ba767d12a6266a6ca9958ea30c1b14 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Tue, 8 May 2018 13:18:13 -0700 Subject: [PATCH 17/27] Revert back to non-blocking watch termination condition A thread blocking on System.in.read() cannot be interrupted, so check System.in.available before blocking. This is how it used to work. It requires https://github.com/sbt/io/pull/149 or else a cpu will be pegged by the EventMonitor user input thread spinning on System.in.available. --- main-command/src/main/scala/sbt/Watched.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-command/src/main/scala/sbt/Watched.scala b/main-command/src/main/scala/sbt/Watched.scala index 73e177f83..4daea053b 100644 --- a/main-command/src/main/scala/sbt/Watched.scala +++ b/main-command/src/main/scala/sbt/Watched.scala @@ -100,7 +100,7 @@ object Watched { def executeContinuously(watched: Watched, s: State, next: String, repeat: String): State = { @tailrec def shouldTerminate: Boolean = - watched.terminateWatch(System.in.read()) || shouldTerminate + (System.in.available > 0) && (watched.terminateWatch(System.in.read()) || shouldTerminate) val log = s.log val logger = new EventMonitor.Logger { override def debug(msg: => Any): Unit = log.debug(msg.toString) From b849894a369759a1d8ff95542326c71206254d8e Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 8 May 2018 17:52:30 -0400 Subject: [PATCH 18/27] IO 1.1.8 --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index c97af475b..9f25f76e9 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,7 +8,7 @@ object Dependencies { val baseScalaVersion = scala212 // sbt modules - private val ioVersion = "1.1.7" + private val ioVersion = "1.1.8" private val utilVersion = "1.1.3" private val lmVersion = "1.1.4" private val zincVersion = "1.1.7" From c8a4dc10e72e995df0cf53e0d1dd803ddcf46f18 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 6 Feb 2018 15:18:50 +0000 Subject: [PATCH 19/27] Add MavenCentral to RunFromSourceMain's repos --- sbt/src/test/scala/sbt/RunFromSourceMain.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sbt/src/test/scala/sbt/RunFromSourceMain.scala b/sbt/src/test/scala/sbt/RunFromSourceMain.scala index d70f02cb0..09e9758b1 100644 --- a/sbt/src/test/scala/sbt/RunFromSourceMain.scala +++ b/sbt/src/test/scala/sbt/RunFromSourceMain.scala @@ -117,8 +117,10 @@ object RunFromSourceMain { def topLoader = new java.net.URLClassLoader(Array(), null) def globalLock = noGlobalLock def bootDirectory = RunFromSourceMain.bootDirectory - def ivyRepositories = Array() - def appRepositories = Array() + final case class PredefRepo(id: Predefined) extends PredefinedRepository + import Predefined._ + def ivyRepositories = Array(PredefRepo(Local), PredefRepo(MavenCentral)) + def appRepositories = Array(PredefRepo(Local), PredefRepo(MavenCentral)) def isOverrideRepositories = false def ivyHome = file(sys.props("user.home")) / ".ivy2" def checksums = Array("sha1", "md5") From 34cc8cd2730318db99770dbadce29fc455ba91ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20H=C3=B8is=C3=A6ther?= Date: Tue, 15 May 2018 13:42:41 +0200 Subject: [PATCH 20/27] Only use first line for multiline descriptions --- main/src/main/scala/sbt/Main.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index da44d0cb8..2a9c88505 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -357,7 +357,7 @@ object BuiltinCommands { } def taskStrings(key: AttributeKey[_]): Option[(String, String)] = key.description map { d => - (key.label, d) + (key.label, d.split("\r?\n")(0)) } def defaults = Command.command(DefaultsCommand) { s => From e83013d3c87a2f8e4113525c2e120fe514e4a039 Mon Sep 17 00:00:00 2001 From: dadarakt Date: Tue, 15 May 2018 14:09:27 +0200 Subject: [PATCH 21/27] Using outputChanged to track the change of the jar file instead of unit --- main-actions/src/main/scala/sbt/Package.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/main-actions/src/main/scala/sbt/Package.scala b/main-actions/src/main/scala/sbt/Package.scala index 76333963e..9970561d4 100644 --- a/main-actions/src/main/scala/sbt/Package.scala +++ b/main-actions/src/main/scala/sbt/Package.scala @@ -23,7 +23,7 @@ import sbt.internal.util.HNil import sbt.internal.util.HListFormats._ import sbt.util.FileInfo.{ exists, lastModified } import sbt.util.CacheImplicits._ -import sbt.util.Tracked.inputChanged +import sbt.util.Tracked.{ inputChanged, outputChanged } sealed trait PackageOption object Package { @@ -71,10 +71,11 @@ object Package { inputs: Map[File, String] :+: FilesInfo[ModifiedFileInfo] :+: Manifest :+: HNil) => import exists.format val sources :+: _ :+: manifest :+: HNil = inputs - inputChanged(cacheStoreFactory make "output") { (outChanged, jar: PlainFileInfo) => - if (inChanged || outChanged) + outputChanged(cacheStoreFactory make "output") { (outChanged, jar: PlainFileInfo) => + if (inChanged || outChanged) { makeJar(sources.toSeq, jar.file, manifest, log) - else + jar.file + } else log.debug("Jar uptodate: " + jar.file) } } From 39cac14ea7ba08e07d486ab7292afe228220e9db Mon Sep 17 00:00:00 2001 From: dadarakt Date: Tue, 15 May 2018 14:25:49 +0200 Subject: [PATCH 22/27] Adapted syntax to match example --- main-actions/src/main/scala/sbt/Package.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-actions/src/main/scala/sbt/Package.scala b/main-actions/src/main/scala/sbt/Package.scala index 9970561d4..54d107917 100644 --- a/main-actions/src/main/scala/sbt/Package.scala +++ b/main-actions/src/main/scala/sbt/Package.scala @@ -82,7 +82,7 @@ object Package { val map = conf.sources.toMap val inputs = map :+: lastModified(map.keySet) :+: manifest :+: HNil - cachedMakeJar(inputs)(exists(conf.jar)) + cachedMakeJar(inputs)(() => exists(conf.jar)) } def setVersion(main: Attributes): Unit = { val version = Attributes.Name.MANIFEST_VERSION From 6214408783f96f896998cc9b3214047109ebb1c4 Mon Sep 17 00:00:00 2001 From: Holden Karau Date: Tue, 15 May 2018 05:31:58 -0700 Subject: [PATCH 23/27] Add support for --error. --- main-command/src/main/scala/sbt/BasicCommandStrings.scala | 6 ++++-- main-command/src/main/scala/sbt/BasicCommands.scala | 3 ++- sbt/src/sbt-test/actions/early-command/test | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/main-command/src/main/scala/sbt/BasicCommandStrings.scala b/main-command/src/main/scala/sbt/BasicCommandStrings.scala index abc2bc9c1..e9e73fba2 100644 --- a/main-command/src/main/scala/sbt/BasicCommandStrings.scala +++ b/main-command/src/main/scala/sbt/BasicCommandStrings.scala @@ -67,7 +67,7 @@ $HelpCommand This will be used as the default level for logging from commands, settings, and tasks. Any explicit `logLevel` configuration in a project overrides this setting. --$level +-$level OR --$level Sets the global logging level as described above, but does so before any other commands are executed on startup, including project loading. This is useful as a startup option: @@ -77,7 +77,9 @@ $HelpCommand def runEarly(command: String) = s"$EarlyCommand($command)" private[sbt] def isEarlyCommand(s: String): Boolean = { - val levelOptions = Level.values.toSeq map { "-" + _ } + val levelOptions = Level.values.toSeq flatMap { elem => + List("-" + elem, "--" + elem) + } (s.startsWith(EarlyCommand + "(") && s.endsWith(")")) || (levelOptions contains s) } diff --git a/main-command/src/main/scala/sbt/BasicCommands.scala b/main-command/src/main/scala/sbt/BasicCommands.scala index 82bb7b883..97ed9d1d6 100644 --- a/main-command/src/main/scala/sbt/BasicCommands.scala +++ b/main-command/src/main/scala/sbt/BasicCommands.scala @@ -69,7 +69,8 @@ object BasicCommands { private[this] def earlyParser: State => Parser[String] = (s: State) => { val p1 = token(EarlyCommand + "(") flatMap (_ => otherCommandParser(s) <~ token(")")) val p2 = token("-") flatMap (_ => levelParser) - p1 | p2 + val p3 = token("--") flatMap (_ => levelParser) + p1 | p2 | p3 } private[this] def earlyHelp = Help(EarlyCommand, EarlyCommandBrief, EarlyCommandDetailed) diff --git a/sbt/src/sbt-test/actions/early-command/test b/sbt/src/sbt-test/actions/early-command/test index 532cef013..66e241ad4 100644 --- a/sbt/src/sbt-test/actions/early-command/test +++ b/sbt/src/sbt-test/actions/early-command/test @@ -1,2 +1,3 @@ > -error > early(error) +> --error \ No newline at end of file From 667a6be99e78fb675644d069a1228a9c6e78d56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20H=C3=B8is=C3=A6ther?= Date: Tue, 15 May 2018 14:33:24 +0200 Subject: [PATCH 24/27] Show all lines when running help , but only first line when listing tasks --- main/src/main/scala/sbt/Main.scala | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 2a9c88505..65b436be0 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -313,8 +313,14 @@ object BuiltinCommands { 'v'.id.+.map(_.size + 1) | ("V" ^^^ Int.MaxValue) )) + + def taskDetail(keys: Seq[AttributeKey[_]], firstOnly: Boolean): Seq[(String, String)] = + sortByLabel(withDescription(keys)) flatMap { t => + taskStrings(t, firstOnly) + } + def taskDetail(keys: Seq[AttributeKey[_]]): Seq[(String, String)] = - sortByLabel(withDescription(keys)) flatMap taskStrings + taskDetail(keys, false) def allTaskAndSettingKeys(s: State): Seq[AttributeKey[_]] = { val extracted = Project.extract(s) @@ -349,16 +355,19 @@ object BuiltinCommands { def tasksHelp(s: State, filter: Seq[AttributeKey[_]] => Seq[AttributeKey[_]], arg: Option[String]): String = { - val commandAndDescription = taskDetail(filter(allTaskAndSettingKeys(s))) + val commandAndDescription = taskDetail(filter(allTaskAndSettingKeys(s)), true) arg match { case Some(selected) => detail(selected, commandAndDescription.toMap) case None => aligned(" ", " ", commandAndDescription) mkString ("\n", "\n", "") } } - def taskStrings(key: AttributeKey[_]): Option[(String, String)] = key.description map { d => - (key.label, d.split("\r?\n")(0)) - } + def taskStrings(key: AttributeKey[_], firstOnly: Boolean): Option[(String, String)] = + key.description map { d => + if (firstOnly) (key.label, d.split("\r?\n")(0)) else (key.label, d) + } + + def taskStrings(key: AttributeKey[_]): Option[(String, String)] = taskStrings(key, false) def defaults = Command.command(DefaultsCommand) { s => s.copy(definedCommands = DefaultCommands) From 833e61635e7e1afd8f31f056165a72ff83850af1 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 27 May 2018 22:38:58 -0400 Subject: [PATCH 25/27] IO 1.1.10 and Zinc 1.1.5 --- project/Dependencies.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 9f25f76e9..bb2a81649 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,9 +8,9 @@ object Dependencies { val baseScalaVersion = scala212 // sbt modules - private val ioVersion = "1.1.8" + private val ioVersion = "1.1.10" private val utilVersion = "1.1.3" - private val lmVersion = "1.1.4" + private val lmVersion = "1.1.5" private val zincVersion = "1.1.7" private val sbtIO = "org.scala-sbt" %% "io" % ioVersion From f2a7e1f1c3911fc9fa911d3fc76f61de28fd7a52 Mon Sep 17 00:00:00 2001 From: Antonio Cunei Date: Mon, 28 May 2018 14:09:13 +0200 Subject: [PATCH 26/27] Fix for #4148 (SessionSettingsSpec intermittently fails) It turns out that `syntaxAnalyzer.UnitParser()` in global now also needs to be synchronized. The alternative is adding `synchronizeNames = true` in the global constructor, but that already proved unreliable in the case of #3743 (see comment https://github.com/sbt/sbt/issues/3170#issuecomment-355218833) --- main/src/main/scala/sbt/internal/parser/SbtParser.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/internal/parser/SbtParser.scala b/main/src/main/scala/sbt/internal/parser/SbtParser.scala index 18dfa2b5e..1a7f52d57 100644 --- a/main/src/main/scala/sbt/internal/parser/SbtParser.scala +++ b/main/src/main/scala/sbt/internal/parser/SbtParser.scala @@ -148,7 +148,9 @@ private[sbt] object SbtParser { reporter.reset() val wrapperFile = new BatchSourceFile(reporterId, code) val unit = new CompilationUnit(wrapperFile) - val parser = new syntaxAnalyzer.UnitParser(unit) + val parser = SbtParser.synchronized { // see https://github.com/sbt/sbt/issues/4148 + new syntaxAnalyzer.UnitParser(unit) + } val parsedTrees = SbtParser.synchronized { // see https://github.com/scala/bug/issues/10605 parser.templateStats() } From 41fc25dba79e6728bc58a9b5745e279ee3a65eb6 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 13 Jun 2018 02:01:17 -0400 Subject: [PATCH 27/27] Fix scripted test --- scripted/sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/scripted/sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala b/scripted/sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala index 77e3b7467..50883790e 100644 --- a/scripted/sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala +++ b/scripted/sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala @@ -167,6 +167,7 @@ final class ScriptedTests( case "actions/external-doc" => LauncherBased // sbt/Package$ case "actions/input-task" => LauncherBased // sbt/Package$ case "actions/input-task-dyn" => LauncherBased // sbt/Package$ + case "compiler-project/dotty-compiler-plugin" => LauncherBased // sbt/Package$ case "compiler-project/run-test" => LauncherBased // sbt/Package$ case "compiler-project/src-dep-plugin" => LauncherBased // sbt/Package$ case "dependency-management/artifact" => LauncherBased // tbd