From 18353f1ca8ab3b441f5154991645be666e3edfd5 Mon Sep 17 00:00:00 2001 From: Iulian Dragos Date: Fri, 11 Aug 2023 16:08:11 +0200 Subject: [PATCH] Reviewer's suggestions. --- build.sbt | 8 +- main/src/main/scala/sbt/CommandProgress.scala | 35 -------- main/src/main/scala/sbt/EvaluateTask.scala | 35 ++++---- .../src/main/scala/sbt/ExecuteProgress2.scala | 79 +++++++++++++++++++ main/src/main/scala/sbt/Keys.scala | 5 +- main/src/main/scala/sbt/MainLoop.scala | 19 ++--- 6 files changed, 109 insertions(+), 72 deletions(-) delete mode 100644 main/src/main/scala/sbt/CommandProgress.scala create mode 100644 main/src/main/scala/sbt/ExecuteProgress2.scala diff --git a/build.sbt b/build.sbt index ce6a0f709..3edd3c254 100644 --- a/build.sbt +++ b/build.sbt @@ -176,6 +176,8 @@ def mimaSettingsSince(versions: Seq[String]): Seq[Def.Setting[_]] = Def settings exclude[DirectMissingMethodProblem]("sbt.PluginData.apply"), exclude[DirectMissingMethodProblem]("sbt.PluginData.copy"), exclude[DirectMissingMethodProblem]("sbt.PluginData.this"), + exclude[IncompatibleResultTypeProblem]("sbt.EvaluateTask.executeProgress"), + exclude[DirectMissingMethodProblem]("sbt.Keys.currentTaskProgress") ), ) @@ -188,11 +190,11 @@ lazy val sbtRoot: Project = (project in file(".")) minimalSettings, onLoadMessage := { val version = sys.props("java.specification.version") - """ __ __ + """ __ __ | _____/ /_ / /_ | / ___/ __ \/ __/ - | (__ ) /_/ / /_ - | /____/_.___/\__/ + | (__ ) /_/ / /_ + | /____/_.___/\__/ |Welcome to the build for sbt. |""".stripMargin + (if (version != "1.8") diff --git a/main/src/main/scala/sbt/CommandProgress.scala b/main/src/main/scala/sbt/CommandProgress.scala deleted file mode 100644 index 757cd0a60..000000000 --- a/main/src/main/scala/sbt/CommandProgress.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* - * sbt - * Copyright 2023, Scala center - * Copyright 2011 - 2022, Lightbend, Inc. - * Copyright 2008 - 2010, Mark Harrah - * Licensed under Apache License 2.0 (see LICENSE) - */ - -package sbt - -/** - * Tracks command execution progress. In addition to ExecuteProgress, this interface - * adds command start and end events, and gives access to the sbt.State at the beginning - * and end of each command. - */ -trait CommandProgress extends ExecuteProgress[Task] { - - /** - * Called before a command starts processing. The command has not yet been parsed. - * - * @param cmd The command string - * @param state The sbt.State before the command starts executing. - */ - def beforeCommand(cmd: String, state: State): Unit - - /** - * Called after a command finished execution. - * - * @param cmd The command string. - * @param result Left in case of an error. If the command cannot be parsed, it will be - * signalled as a ParseException with a detailed message. If the command - * was cancelled by the user, as sbt.Cancelled. - */ - def afterCommand(cmd: String, result: Either[Throwable, State]): Unit -} diff --git a/main/src/main/scala/sbt/EvaluateTask.scala b/main/src/main/scala/sbt/EvaluateTask.scala index dfeaf9f18..4c3477062 100644 --- a/main/src/main/scala/sbt/EvaluateTask.scala +++ b/main/src/main/scala/sbt/EvaluateTask.scala @@ -258,12 +258,15 @@ object EvaluateTask { extracted: Extracted, structure: BuildStructure, state: State - ): ExecuteProgress[Task] = { + ): ExecuteProgress2 = { state - .get(currentTaskProgress) - .map { tp => - new ExecuteProgress[Task] { - val progress = tp.progress + .get(currentCommandProgress) + .map { progress => + new ExecuteProgress2 { + override def beforeCommand(cmd: String, state: State): Unit = + progress.beforeCommand(cmd, state) + override def afterCommand(cmd: String, result: Either[Throwable, State]): Unit = + progress.afterCommand(cmd, result) override def initial(): Unit = progress.initial() override def afterRegistered( task: Task[_], @@ -279,7 +282,9 @@ object EvaluateTask { progress.afterCompleted(task, result) override def afterAllCompleted(results: RMap[Task, Result]): Unit = progress.afterAllCompleted(results) - override def stop(): Unit = {} + override def stop(): Unit = { + // TODO: this is not a typo, but a questionable decision in 6559c3a0 that is probably obsolete + } } } .getOrElse { @@ -289,20 +294,16 @@ object EvaluateTask { extracted, structure ) - val reporters = maker.map(_.progress) ++ state.get(Keys.taskProgress) ++ getSetting( - Keys.commandProgress, - Seq(), - extracted, - structure - ) ++ + val reporters = maker.map(_.progress) ++ state.get(Keys.taskProgress) ++ (if (SysProp.taskTimings) new TaskTimings(reportOnShutdown = false, state.globalLogging.full) :: Nil else Nil) - reporters match { - case xs if xs.isEmpty => ExecuteProgress.empty[Task] - case xs if xs.size == 1 => xs.head - case xs => ExecuteProgress.aggregate[Task](xs) - } + val cmdProgress = getSetting(Keys.commandProgress, Seq(), extracted, structure) + ExecuteProgress2.aggregate(reporters match { + case xs if xs.isEmpty => cmdProgress + case xs if xs.size == 1 => cmdProgress :+ new ExecuteProgressAdapter(xs.head) + case xs => cmdProgress :+ new ExecuteProgressAdapter(ExecuteProgress.aggregate[Task](xs)) + }) } } // TODO - Should this pull from Global or from the project itself? diff --git a/main/src/main/scala/sbt/ExecuteProgress2.scala b/main/src/main/scala/sbt/ExecuteProgress2.scala new file mode 100644 index 000000000..41ed6e658 --- /dev/null +++ b/main/src/main/scala/sbt/ExecuteProgress2.scala @@ -0,0 +1,79 @@ +/* + * sbt + * Copyright 2023, Scala center + * Copyright 2011 - 2022, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +import sbt.internal.util.RMap + +/** + * Tracks command execution progress. In addition to ExecuteProgress, this interface + * adds command start and end events, and gives access to the sbt.State at the beginning + * and end of each command. + */ +trait ExecuteProgress2 extends ExecuteProgress[Task] { + + /** + * Called before a command starts processing. The command has not yet been parsed. + * + * @param cmd The command string + * @param state The sbt.State before the command starts executing. + */ + def beforeCommand(cmd: String, state: State): Unit + + /** + * Called after a command finished execution. + * + * @param cmd The command string. + * @param result Left in case of an error. If the command cannot be parsed, it will be + * signalled as a ParseException with a detailed message. If the command + * was cancelled by the user, as sbt.Cancelled. + */ + def afterCommand(cmd: String, result: Either[Throwable, State]): Unit +} + +class ExecuteProgressAdapter(ep: ExecuteProgress[Task]) extends ExecuteProgress2 { + override def beforeCommand(cmd: String, state: State): Unit = {} + override def afterCommand(cmd: String, result: Either[Throwable, State]): Unit = {} + override def initial(): Unit = ep.initial() + override def afterRegistered( + task: Task[_], + allDeps: Iterable[Task[_]], + pendingDeps: Iterable[Task[_]] + ): Unit = ep.afterRegistered(task, allDeps, pendingDeps) + override def afterReady(task: Task[_]): Unit = ep.afterReady(task) + override def beforeWork(task: Task[_]): Unit = ep.beforeWork(task) + override def afterWork[A](task: Task[A], result: Either[Task[A], Result[A]]): Unit = + ep.afterWork(task, result) + override def afterCompleted[A](task: Task[A], result: Result[A]): Unit = + ep.afterCompleted(task, result) + override def afterAllCompleted(results: RMap[Task, Result]): Unit = ep.afterAllCompleted(results) + override def stop(): Unit = ep.stop() +} + +object ExecuteProgress2 { + def aggregate(xs: Seq[ExecuteProgress2]): ExecuteProgress2 = new ExecuteProgress2 { + override def beforeCommand(cmd: String, state: State): Unit = + xs.foreach(_.beforeCommand(cmd, state)) + override def afterCommand(cmd: String, result: Either[Throwable, State]): Unit = + xs.foreach(_.afterCommand(cmd, result)) + override def initial(): Unit = xs.foreach(_.initial()) + override def afterRegistered( + task: Task[_], + allDeps: Iterable[Task[_]], + pendingDeps: Iterable[Task[_]] + ): Unit = xs.foreach(_.afterRegistered(task, allDeps, pendingDeps)) + override def afterReady(task: Task[_]): Unit = xs.foreach(_.afterReady(task)) + override def beforeWork(task: Task[_]): Unit = xs.foreach(_.beforeWork(task)) + override def afterWork[A](task: Task[A], result: Either[Task[A], Result[A]]): Unit = + xs.foreach(_.afterWork(task, result)) + override def afterCompleted[A](task: Task[A], result: Result[A]): Unit = + xs.foreach(_.afterCompleted(task, result)) + override def afterAllCompleted(results: RMap[Task, Result]): Unit = + xs.foreach(_.afterAllCompleted(results)) + override def stop(): Unit = xs.foreach(_.stop()) + } +} diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index e320f7147..9b24eefc1 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -599,8 +599,7 @@ object Keys { object TaskProgress { def apply(progress: ExecuteProgress[Task]): TaskProgress = new TaskProgress(progress) } - private[sbt] val currentTaskProgress = AttributeKey[TaskProgress]("current-task-progress") - private[sbt] val currentCommandProgress = AttributeKey[Seq[CommandProgress]]("current-command-progress") + private[sbt] val currentCommandProgress = AttributeKey[ExecuteProgress2]("current-command-progress") private[sbt] val taskProgress = AttributeKey[sbt.internal.TaskProgress]("active-task-progress") val useSuperShell = settingKey[Boolean]("Enables (true) or disables the super shell.") val superShellMaxTasks = settingKey[Int]("The max number of tasks to display in the supershell progress report") @@ -614,7 +613,7 @@ object Keys { private[sbt] val postProgressReports = settingKey[Unit]("Internally used to modify logger.").withRank(DTask) @deprecated("No longer used", "1.3.0") private[sbt] val executeProgress = settingKey[State => TaskProgress]("Experimental task execution listener.").withRank(DTask) - val commandProgress = settingKey[Seq[CommandProgress]]("Command progress listeners receive events when commands start and end, in addition to task progress events.") + val commandProgress = settingKey[Seq[ExecuteProgress2]]("Command progress listeners receive events when commands start and end, in addition to task progress events.") val lintUnused = inputKey[Unit]("Check for keys unused by other settings and tasks.") val lintIncludeFilter = settingKey[String => Boolean]("Filters key names that should be included in the lint check.") val lintExcludeFilter = settingKey[String => Boolean]("Filters key names that should be excluded in the lint check.") diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index cbee12e42..aaa1d98ec 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -229,20 +229,12 @@ object MainLoop { } else state } } - val progressState = getOrSet( - state, - sbt.Keys.currentTaskProgress, - extracted => - new Keys.TaskProgress( - EvaluateTask.executeProgress(extracted, extracted.structure, state) - ) - ) val cmdProgressState = getOrSet( - progressState, + state, sbt.Keys.currentCommandProgress, - _.getOpt(Keys.commandProgress).getOrElse(Seq()) + extracted => EvaluateTask.executeProgress(extracted, extracted.structure, state) ) exchange.setState(cmdProgressState) @@ -260,8 +252,8 @@ object MainLoop { } val currentCmdProgress = - cmdProgressState.get(sbt.Keys.currentCommandProgress).getOrElse(Nil) - currentCmdProgress.foreach(_.beforeCommand(exec.commandLine, progressState)) + cmdProgressState.get(sbt.Keys.currentCommandProgress) + currentCmdProgress.foreach(_.beforeCommand(exec.commandLine, cmdProgressState)) /* * FastTrackCommands.evaluate can be significantly faster than Command.process because * it avoids an expensive parsing step for internal commands that are easy to parse. @@ -310,9 +302,8 @@ object MainLoop { exchange.respondStatus(doneEvent) } exchange.setExec(None) - newState.get(sbt.Keys.currentTaskProgress).foreach(_.progress.stop()) + newState.get(sbt.Keys.currentCommandProgress).foreach(_.stop()) newState - .remove(sbt.Keys.currentTaskProgress) .remove(Keys.terminalKey) .remove(Keys.currentCommandProgress) }