From 50b062b795d7f531a812742ddd14f7b13e189fd1 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 20 Dec 2021 02:00:30 -0500 Subject: [PATCH] Port util-logging --- build.sbt | 8 +- .../scala/sbt/internal/util/LineReader.scala | 16 +- .../internal/util/complete/Completions.scala | 44 ++- .../internal/util/complete/EditDistance.scala | 5 +- .../util/complete/ExampleSource.scala | 32 ++- .../util/complete/HistoryCommands.scala | 10 +- .../util/complete/JLineCompletion.scala | 11 +- .../sbt/internal/util/complete/Parser.scala | 254 ++++++++++-------- .../sbt/internal/util/complete/Parsers.scala | 190 ++++++++----- .../internal/util/complete/SizeParser.scala | 15 +- .../internal/util/complete/TypeString.scala | 25 +- .../internal/util/complete/UpperBound.scala | 17 +- .../src/test/scala/DefaultParsersSpec.scala | 5 +- .../scala/sbt/complete/FileExamplesTest.scala | 6 +- .../sbt/complete/ParserWithExamplesTest.scala | 62 ++--- .../com/github/ghik/silencer/silent.scala | 6 +- .../scala/sbt/internal/util/BasicLogger.scala | 2 +- .../sbt/internal/util/BufferedLogger.scala | 26 +- .../sbt/internal/util/ConsoleAppender.scala | 215 +++++++++------ .../scala/sbt/internal/util/ConsoleOut.scala | 6 +- .../scala/sbt/internal/util/EscHelpers.scala | 59 ++-- .../sbt/internal/util/FilterLogger.scala | 5 +- .../sbt/internal/util/GlobalLogging.scala | 27 +- .../main/scala/sbt/internal/util/JLine3.scala | 9 +- .../sbt/internal/util/LoggerWriter.scala | 4 +- .../sbt/internal/util/ManagedLogger.scala | 23 +- .../sbt/internal/util/ProgressState.scala | 9 +- .../scala/sbt/internal/util/StackTrace.scala | 40 ++- .../scala/sbt/internal/util/Terminal.scala | 152 ++++++----- .../internal/util/WindowsInputStream.scala | 16 +- .../src/main/scala/sbt/util/Level.scala | 13 +- .../src/main/scala/sbt/util/LogExchange.scala | 12 +- .../src/main/scala/sbt/util/Logger.scala | 4 +- .../main/scala/sbt/util/LoggerContext.scala | 15 +- .../src/test/scala/LogExchangeSpec.scala | 13 +- .../src/test/scala/LogWriterTest.scala | 31 ++- .../src/test/scala/ManagedLoggerSpec.scala | 7 +- .../sbt/internal/util/UTF8DecoderSpec.scala | 2 +- .../sbt/internal/scripted/FileCommands.scala | 3 +- .../sbt/internal/scripted/ScriptedTests.scala | 3 +- project/Dependencies.scala | 9 +- .../sbt/internal/bsp/SourceItemKind.scala | 2 +- .../JsonRpcNotificationMessageFormats.scala | 4 +- .../codec/JsonRpcRequestMessageFormats.scala | 19 +- .../codec/JsonRpcResponseErrorFormats.scala | 4 +- .../codec/JsonRpcResponseMessageFormats.scala | 17 +- .../scala/sbt/protocol/Serialization.scala | 9 +- .../src/main/scala/sbt/Action.scala | 41 +-- .../src/main/scala/sbt/std/Streams.scala | 47 ++-- .../src/main/scala/sbt/std/TaskExtra.scala | 9 +- .../src/main/scala/sbt/std/Transform.scala | 2 +- tasks-standard/src/test/scala/Test.scala | 6 +- .../src/test/scala/TestRunnerSort.scala | 7 +- .../src/main/scala/sbt/util/Cache.scala | 15 +- .../src/main/scala/sbt/util/FileInfo.scala | 14 +- .../src/main/scala/sbt/util/Input.scala | 4 +- .../main/scala/sbt/util/StampedFormat.scala | 4 +- util-cache/src/test/scala/CacheSpec.scala | 70 +++-- .../src/test/scala/SingletonCacheSpec.scala | 42 ++- .../main/scala/sbt/internal/util/Util.scala | 3 +- .../main/scala/sbt/util/ChangeReport.scala | 19 +- .../main/scala/sbt/util/FileFunction.scala | 166 ++++++------ .../src/main/scala/sbt/util/Tracked.scala | 76 ++++-- .../src/test/scala/sbt/util/TrackedSpec.scala | 8 +- 64 files changed, 1115 insertions(+), 884 deletions(-) diff --git a/build.sbt b/build.sbt index 6d5ec0392..d2a84b2d5 100644 --- a/build.sbt +++ b/build.sbt @@ -181,7 +181,11 @@ val scriptedSbtReduxMimaSettings = Def.settings(mimaPreviousArtifacts := Set()) lazy val sbtRoot: Project = (project in file(".")) // .aggregate(nonRoots: _*) - .aggregate(collectionProj, coreMacrosProj) + .aggregate( + collectionProj, + coreMacrosProj, + utilLogging, + ) .settings( minimalSettings, onLoadMessage := { @@ -351,9 +355,9 @@ lazy val utilLogging = (project in file("internal") / "util-logging") log4jCore, disruptor, sjsonNewScalaJson.value, - scalaReflect.value ), libraryDependencies ++= Seq(scalacheck % "test", scalatest % "test"), + Compile / generateContrabands / contrabandCodecsDependencies := List(sjsonNewCore.value), Compile / scalacOptions ++= (scalaVersion.value match { case v if v.startsWith("2.12.") => List("-Ywarn-unused:-locals,-explicits,-privates") case _ => List() diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala b/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala index fbc86b725..41f0b9014 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala @@ -125,9 +125,11 @@ object LineReader { case _: Terminal.ConsoleTerminal => Some(Signals.register(() => terminal.write(-1))) case _ => None } - try terminal.withRawInput { - Option(mask.map(reader.readLine(prompt, _)).getOrElse(reader.readLine(prompt))) - } catch { + try + terminal.withRawInput { + Option(mask.map(reader.readLine(prompt, _)).getOrElse(reader.readLine(prompt))) + } + catch { case e: EndOfFileException => if (terminal == Terminal.console && System.console == null) None else Some("exit") @@ -195,8 +197,8 @@ abstract class JLine extends LineReader { private[this] def readLineDirect(prompt: String, mask: Option[Char]): Option[String] = if (handleCONT) - Signals.withHandler(() => resume(), signal = Signals.CONT)( - () => readLineDirectRaw(prompt, mask) + Signals.withHandler(() => resume(), signal = Signals.CONT)(() => + readLineDirectRaw(prompt, mask) ) else readLineDirectRaw(prompt, mask) @@ -253,8 +255,8 @@ private[sbt] object JLine { private[sbt] def terminal: jline.Terminal = Terminal.deprecatedTeminal /** - * For accessing the JLine Terminal object. - * This ensures synchronized access as well as re-enabling echo after getting the Terminal. + * For accessing the JLine Terminal object. This ensures synchronized access as well as + * re-enabling echo after getting the Terminal. */ @deprecated( "Don't use jline.Terminal directly. Use Terminal.get.withCanonicalIn instead.", diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/Completions.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/Completions.scala index 2d938d89a..1297784de 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/Completions.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/Completions.scala @@ -9,9 +9,8 @@ package sbt.internal.util package complete /** - * Represents a set of completions. - * It exists instead of implicitly defined operations on top of Set[Completion] - * for laziness. + * Represents a set of completions. It exists instead of implicitly defined operations on top of + * Set[Completion] for laziness. */ sealed trait Completions { def get: Set[Completion] @@ -46,49 +45,48 @@ object Completions { def strict(cs: Set[Completion]): Completions = apply(cs) /** - * No suggested completions, not even the empty Completion. - * This typically represents invalid input. + * No suggested completions, not even the empty Completion. This typically represents invalid + * input. */ val nil: Completions = strict(Set.empty) /** - * Only includes an empty Suggestion. - * This typically represents valid input that either has no completions or accepts no further input. + * Only includes an empty Suggestion. This typically represents valid input that either has no + * completions or accepts no further input. */ val empty: Completions = strict(Set.empty + Completion.empty) - /** Returns a strict Completions instance containing only the provided Completion.*/ + /** Returns a strict Completions instance containing only the provided Completion. */ def single(c: Completion): Completions = strict(Set.empty + c) } /** - * Represents a completion. - * The abstract members `display` and `append` are best explained with an example. + * Represents a completion. The abstract members `display` and `append` are best explained with an + * example. * - * Assuming space-delimited tokens, processing this: - * am is are w - * could produce these Completions: - * Completion { display = "was"; append = "as" } - * Completion { display = "were"; append = "ere" } - * to suggest the tokens "was" and "were". + * Assuming space-delimited tokens, processing this: am is are w could produce these + * Completions: Completion { display = "was"; append = "as" } Completion { display = "were"; append + * = "ere" } to suggest the tokens "was" and "were". * - * In this way, two pieces of information are preserved: - * 1) what needs to be appended to the current input if a completion is selected - * 2) the full token being completed, which is useful for presenting a user with choices to select + * In this way, two pieces of information are preserved: 1) what needs to be appended to the current + * input if a completion is selected 2) the full token being completed, which is useful for + * presenting a user with choices to select */ sealed trait Completion { - /** The proposed suffix to append to the existing input to complete the last token in the input.*/ + /** + * The proposed suffix to append to the existing input to complete the last token in the input. + */ def append: String - /** The string to present to the user to represent the full token being suggested.*/ + /** The string to present to the user to represent the full token being suggested. */ def display: String - /** True if this Completion is suggesting the empty string.*/ + /** True if this Completion is suggesting the empty string. */ def isEmpty: Boolean - /** Appends the completions in `o` with the completions in this Completion.*/ + /** Appends the completions in `o` with the completions in this Completion. */ def ++(o: Completion): Completion = Completion.concat(this, o) final def x(o: Completions): Completions = diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/EditDistance.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/EditDistance.scala index e7c710c87..8609fbe1a 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/EditDistance.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/EditDistance.scala @@ -14,9 +14,8 @@ import java.lang.Character.{ toLowerCase => lower } object EditDistance { /** - * Translated from the java version at - * http://www.merriampark.com/ld.htm - * which is declared to be public domain. + * Translated from the java version at http://www.merriampark.com/ld.htm which is declared to be + * public domain. */ def levenshtein( s: String, diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/ExampleSource.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/ExampleSource.scala index e15217524..c9b2725bf 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/ExampleSource.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/ExampleSource.scala @@ -12,22 +12,25 @@ import java.io.File import sbt.io.IO /** - * These sources of examples are used in parsers for user input completion. An example of such a source is the - * [[sbt.internal.util.complete.FileExamples]] class, which provides a list of suggested files to the user as they press the - * TAB key in the console. + * These sources of examples are used in parsers for user input completion. An example of such a + * source is the [[sbt.internal.util.complete.FileExamples]] class, which provides a list of + * suggested files to the user as they press the TAB key in the console. */ trait ExampleSource { /** - * @return a (possibly lazy) list of completion example strings. These strings are continuations of user's input. The - * user's input is incremented with calls to [[withAddedPrefix]]. + * @return + * a (possibly lazy) list of completion example strings. These strings are continuations of + * user's input. The user's input is incremented with calls to [[withAddedPrefix]]. */ def apply(): Iterable[String] /** - * @param addedPrefix a string that just typed in by the user. - * @return a new source of only those examples that start with the string typed by the user so far (with addition of - * the just added prefix). + * @param addedPrefix + * a string that just typed in by the user. + * @return + * a new source of only those examples that start with the string typed by the user so far (with + * addition of the just added prefix). */ def withAddedPrefix(addedPrefix: String): ExampleSource @@ -35,7 +38,8 @@ trait ExampleSource { /** * A convenience example source that wraps any collection of strings into a source of examples. - * @param examples the examples that will be displayed to the user when they press the TAB key. + * @param examples + * the examples that will be displayed to the user when they press the TAB key. */ sealed case class FixedSetExamples(examples: Iterable[String]) extends ExampleSource { override def withAddedPrefix(addedPrefix: String): ExampleSource = @@ -50,8 +54,10 @@ sealed case class FixedSetExamples(examples: Iterable[String]) extends ExampleSo /** * Provides path completion examples based on files in the base directory. - * @param base the directory within which this class will search for completion examples. - * @param prefix the part of the path already written by the user. + * @param base + * the directory within which this class will search for completion examples. + * @param prefix + * the part of the path already written by the user. */ class FileExamples(base: File, prefix: String = "") extends ExampleSource { override def apply(): Stream[String] = files(base).map(_ substring prefix.length) @@ -64,7 +70,9 @@ class FileExamples(base: File, prefix: String = "") extends ExampleSource { val prefixedDirectChildPaths = childPaths map { IO.relativize(base, _).get } filter { _ startsWith prefix } - val dirsToRecurseInto = childPaths filter { _.isDirectory } map { IO.relativize(base, _).get } filter { + val dirsToRecurseInto = childPaths filter { _.isDirectory } map { + IO.relativize(base, _).get + } filter { dirStartsWithPrefix } prefixedDirectChildPaths append dirsToRecurseInto.flatMap(dir => files(new File(base, dir))) diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/HistoryCommands.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/HistoryCommands.scala index 6c45f54e9..81e874e2f 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/HistoryCommands.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/HistoryCommands.scala @@ -61,14 +61,12 @@ object HistoryCommands { { printHistory(h, MaxLines, show); nil[String].some } } - lazy val execStr = flag('?') ~ token(any.+.string, "") map { - case (contains, str) => - execute(h => if (contains) h !? str else h ! str) + lazy val execStr = flag('?') ~ token(any.+.string, "") map { case (contains, str) => + execute(h => if (contains) h !? str else h ! str) } - lazy val execInt = flag('-') ~ num map { - case (neg, value) => - execute(h => if (neg) h !- value else h ! value) + lazy val execInt = flag('-') ~ num map { case (neg, value) => + execute(h => if (neg) h !- value else h ! value) } lazy val help = success((h: History) => { printHelp(); nil[String].some }) diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/JLineCompletion.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/JLineCompletion.scala index 1e9f4cfcb..a0cfb929e 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/JLineCompletion.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/JLineCompletion.scala @@ -81,10 +81,9 @@ object JLineCompletion { def convertCompletions(cs: Set[Completion]): (Seq[String], Seq[String]) = { val (insert, display) = - cs.foldLeft((Set.empty[String], Set.empty[String])) { - case (t @ (insert, display), comp) => - if (comp.isEmpty) t - else (appendNonEmpty(insert, comp.append), appendNonEmpty(display, comp.display)) + cs.foldLeft((Set.empty[String], Set.empty[String])) { case (t @ (insert, display), comp) => + if (comp.isEmpty) t + else (appendNonEmpty(insert, comp.append), appendNonEmpty(display, comp.display)) } (insert.toSeq, display.toSeq.sorted) } @@ -135,8 +134,8 @@ object JLineCompletion { } /** - * `display` is assumed to be the exact strings requested to be displayed. - * In particular, duplicates should have been removed already. + * `display` is assumed to be the exact strings requested to be displayed. In particular, + * duplicates should have been removed already. */ def showCompletions(display: Seq[String], reader: ConsoleReader): Unit = { printCompletions(display, reader) diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parser.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parser.scala index 8d66d2137..6b56ec4a5 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parser.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parser.scala @@ -13,10 +13,10 @@ import sbt.internal.util.Types.{ left, right, some } import sbt.internal.util.Util.{ makeList, separate } /** - * A String parser that provides semi-automatic tab completion. - * A successful parse results in a value of type `T`. - * The methods in this trait are what must be implemented to define a new Parser implementation, but are not typically useful for common usage. - * Instead, most useful methods for combining smaller parsers into larger parsers are implicitly added by the [[RichParser]] type. + * A String parser that provides semi-automatic tab completion. A successful parse results in a + * value of type `T`. The methods in this trait are what must be implemented to define a new Parser + * implementation, but are not typically useful for common usage. Instead, most useful methods for + * combining smaller parsers into larger parsers are implicitly added by the [[RichParser]] type. */ trait Parser[+T] { def derive(i: Char): Parser[T] @@ -31,80 +31,93 @@ trait Parser[+T] { sealed trait RichParser[A] { - /** Apply the original Parser and then apply `next` (in order). The result of both is provides as a pair. */ + /** + * Apply the original Parser and then apply `next` (in order). The result of both is provides as a + * pair. + */ def ~[B](next: Parser[B]): Parser[(A, B)] - /** Apply the original Parser one or more times and provide the non-empty sequence of results.*/ + /** Apply the original Parser one or more times and provide the non-empty sequence of results. */ def + : Parser[Seq[A]] - /** Apply the original Parser zero or more times and provide the (potentially empty) sequence of results.*/ + /** + * Apply the original Parser zero or more times and provide the (potentially empty) sequence of + * results. + */ def * : Parser[Seq[A]] - /** Apply the original Parser zero or one times, returning None if it was applied zero times or the result wrapped in Some if it was applied once.*/ + /** + * Apply the original Parser zero or one times, returning None if it was applied zero times or the + * result wrapped in Some if it was applied once. + */ def ? : Parser[Option[A]] - /** Apply either the original Parser or `b`.*/ + /** Apply either the original Parser or `b`. */ def |[B >: A](b: Parser[B]): Parser[B] - /** Apply either the original Parser or `b`.*/ + /** Apply either the original Parser or `b`. */ def ||[B](b: Parser[B]): Parser[Either[A, B]] - /** Apply the original Parser to the input and then apply `f` to the result.*/ + /** Apply the original Parser to the input and then apply `f` to the result. */ def map[B](f: A => B): Parser[B] /** - * Returns the original parser. This is useful for converting literals to Parsers. - * For example, `'c'.id` or `"asdf".id` + * Returns the original parser. This is useful for converting literals to Parsers. For example, + * `'c'.id` or `"asdf".id` */ def id: Parser[A] /** Apply the original Parser, but provide `value` as the result if it succeeds. */ def ^^^[B](value: B): Parser[B] - /** Apply the original Parser, but provide `alt` as the result if it fails.*/ + /** Apply the original Parser, but provide `alt` as the result if it fails. */ def ??[B >: A](alt: B): Parser[B] /** - * Produces a Parser that applies the original Parser and then applies `next` (in order), discarding the result of `next`. - * (The arrow point in the direction of the retained result.) + * Produces a Parser that applies the original Parser and then applies `next` (in order), + * discarding the result of `next`. (The arrow point in the direction of the retained result.) */ def <~[B](b: Parser[B]): Parser[A] /** - * Produces a Parser that applies the original Parser and then applies `next` (in order), discarding the result of the original parser. - * (The arrow point in the direction of the retained result.) + * Produces a Parser that applies the original Parser and then applies `next` (in order), + * discarding the result of the original parser. (The arrow point in the direction of the retained + * result.) */ def ~>[B](b: Parser[B]): Parser[B] - /** Uses the specified message if the original Parser fails.*/ + /** Uses the specified message if the original Parser fails. */ def !!!(msg: String): Parser[A] /** - * If an exception is thrown by the original Parser, - * capture it and fail locally instead of allowing the exception to propagate up and terminate parsing. + * If an exception is thrown by the original Parser, capture it and fail locally instead of + * allowing the exception to propagate up and terminate parsing. */ def failOnException: Parser[A] /** - * Apply the original parser, but only succeed if `o` also succeeds. - * Note that `o` does not need to consume the same amount of input to satisfy this condition. + * Apply the original parser, but only succeed if `o` also succeeds. Note that `o` does not need + * to consume the same amount of input to satisfy this condition. */ def &(o: Parser[_]): Parser[A] - /** Explicitly defines the completions for the original Parser.*/ + /** Explicitly defines the completions for the original Parser. */ def examples(s: String*): Parser[A] - /** Explicitly defines the completions for the original Parser.*/ + /** Explicitly defines the completions for the original Parser. */ def examples(s: Set[String], check: Boolean = false): Parser[A] /** - * @param exampleSource the source of examples when displaying completions to the user. - * @param maxNumberOfExamples limits the number of examples that the source of examples should return. This can - * prevent lengthy pauses and avoids bad interactive user experience. - * @param removeInvalidExamples indicates whether completion examples should be checked for validity (against the - * given parser). Invalid examples will be filtered out and only valid suggestions will - * be displayed. - * @return a new parser with a new source of completions. + * @param exampleSource + * the source of examples when displaying completions to the user. + * @param maxNumberOfExamples + * limits the number of examples that the source of examples should return. This can prevent + * lengthy pauses and avoids bad interactive user experience. + * @param removeInvalidExamples + * indicates whether completion examples should be checked for validity (against the given + * parser). Invalid examples will be filtered out and only valid suggestions will be displayed. + * @return + * a new parser with a new source of completions. */ def examples( exampleSource: ExampleSource, @@ -113,24 +126,30 @@ sealed trait RichParser[A] { ): Parser[A] /** - * @param exampleSource the source of examples when displaying completions to the user. - * @return a new parser with a new source of completions. It displays at most 25 completion examples and does not - * remove invalid examples. + * @param exampleSource + * the source of examples when displaying completions to the user. + * @return + * a new parser with a new source of completions. It displays at most 25 completion examples and + * does not remove invalid examples. */ def examples(exampleSource: ExampleSource): Parser[A] = examples(exampleSource, maxNumberOfExamples = 25, removeInvalidExamples = false) - /** Converts a Parser returning a Char sequence to a Parser returning a String.*/ + /** Converts a Parser returning a Char sequence to a Parser returning a String. */ def string(implicit ev: A <:< Seq[Char]): Parser[String] /** - * Produces a Parser that filters the original parser. - * If 'f' is not true when applied to the output of the original parser, the Parser returned by this method fails. - * The failure message is constructed by applying `msg` to the String that was successfully parsed by the original parser. + * Produces a Parser that filters the original parser. If 'f' is not true when applied to the + * output of the original parser, the Parser returned by this method fails. The failure message is + * constructed by applying `msg` to the String that was successfully parsed by the original + * parser. */ def filter(f: A => Boolean, msg: String => String): Parser[A] - /** Applies the original parser, applies `f` to the result to get the next parser, and applies that parser and uses its result for the overall result. */ + /** + * Applies the original parser, applies `f` to the result to get the next parser, and applies that + * parser and uses its result for the overall result. + */ def flatMap[B](f: A => Parser[B]): Parser[B] } @@ -315,7 +334,7 @@ object Parser extends ParserMain { trait ParserMain { - /** Provides combinators for Parsers.*/ + /** Provides combinators for Parsers. */ implicit def richParser[A](a: Parser[A]): RichParser[A] = new RichParser[A] { def ~[B](b: Parser[B]) = seqParser(a, b) def ||[B](b: Parser[B]) = choiceParser(a, b) @@ -357,29 +376,29 @@ trait ParserMain { implicit def literalRichStringParser(s: String): RichParser[String] = richParser(s) /** - * Construct a parser that is valid, but has no valid result. This is used as a way - * to provide a definitive Failure when a parser doesn't match empty input. For example, - * in `softFailure(...) | p`, if `p` doesn't match the empty sequence, the failure will come - * from the Parser constructed by the `softFailure` method. + * Construct a parser that is valid, but has no valid result. This is used as a way to provide a + * definitive Failure when a parser doesn't match empty input. For example, in `softFailure(...) | + * p`, if `p` doesn't match the empty sequence, the failure will come from the Parser constructed + * by the `softFailure` method. */ private[sbt] def softFailure(msg: => String, definitive: Boolean = false): Parser[Nothing] = SoftInvalid(mkFailures(msg :: Nil, definitive)) /** - * Defines a parser that always fails on any input with messages `msgs`. - * If `definitive` is `true`, any failures by later alternatives are discarded. + * Defines a parser that always fails on any input with messages `msgs`. If `definitive` is + * `true`, any failures by later alternatives are discarded. */ def invalid(msgs: => Seq[String], definitive: Boolean = false): Parser[Nothing] = Invalid(mkFailures(msgs, definitive)) /** - * Defines a parser that always fails on any input with message `msg`. - * If `definitive` is `true`, any failures by later alternatives are discarded. + * Defines a parser that always fails on any input with message `msg`. If `definitive` is `true`, + * any failures by later alternatives are discarded. */ def failure(msg: => String, definitive: Boolean = false): Parser[Nothing] = invalid(msg :: Nil, definitive) - /** Defines a parser that always succeeds on empty input with the result `value`.*/ + /** Defines a parser that always succeeds on empty input with the result `value`. */ def success[T](value: T): Parser[T] = new ValidParser[T] { override def result = Some(value) def resultEmpty = Value(value) @@ -388,25 +407,29 @@ trait ParserMain { override def toString = "success(" + value + ")" } - /** Presents a Char range as a Parser. A single Char is parsed only if it is in the given range.*/ + /** + * Presents a Char range as a Parser. A single Char is parsed only if it is in the given range. + */ implicit def range(r: collection.immutable.NumericRange[Char]): Parser[Char] = { val label = r.map(_.toString).toString range(r, label) } - /** Presents a Char range as a Parser. A single Char is parsed only if it is in the given range.*/ + /** + * Presents a Char range as a Parser. A single Char is parsed only if it is in the given range. + */ def range(r: collection.immutable.NumericRange[Char], label: String): Parser[Char] = charClass(r contains _, label).examples(r.map(_.toString): _*) - /** Defines a Parser that parses a single character only if it is contained in `legal`.*/ + /** Defines a Parser that parses a single character only if it is contained in `legal`. */ def chars(legal: String): Parser[Char] = { val set = legal.toSet charClass(set, "character in '" + legal + "'") examples (set.map(_.toString)) } /** - * Defines a Parser that parses a single character only if the predicate `f` returns true for that character. - * If this parser fails, `label` is used as the failure message. + * Defines a Parser that parses a single character only if the predicate `f` returns true for that + * character. If this parser fails, `label` is used as the failure message. */ def charClass(f: Char => Boolean, label: String = ""): Parser[Char] = new CharacterClass(f, label) @@ -420,18 +443,24 @@ trait ParserMain { override def toString = "'" + ch + "'" } - /** Presents a literal String `s` as a Parser that only parses that exact text and provides it as the result.*/ + /** + * Presents a literal String `s` as a Parser that only parses that exact text and provides it as + * the result. + */ implicit def literal(s: String): Parser[String] = stringLiteral(s, 0) /** See [[unapply]]. */ object ~ { - /** Convenience for destructuring a tuple that mirrors the `~` combinator.*/ + /** Convenience for destructuring a tuple that mirrors the `~` combinator. */ def unapply[A, B](t: (A, B)): Some[(A, B)] = Some(t) } - /** Parses input `str` using `parser`. If successful, the result is provided wrapped in `Right`. If unsuccessful, an error message is provided in `Left`.*/ + /** + * Parses input `str` using `parser`. If successful, the result is provided wrapped in `Right`. If + * unsuccessful, an error message is provided in `Left`. + */ def parse[T](str: String, parser: Parser[T]): Either[String, T] = Parser.result(parser, str).left.map { failures => val (msgs, pos) = failures() @@ -439,11 +468,10 @@ trait ParserMain { } /** - * Convenience method to use when developing a parser. - * `parser` is applied to the input `str`. - * If `completions` is true, the available completions for the input are displayed. - * Otherwise, the result of parsing is printed using the result's `toString` method. - * If parsing fails, the error message is displayed. + * Convenience method to use when developing a parser. `parser` is applied to the input `str`. If + * `completions` is true, the available completions for the input are displayed. Otherwise, the + * result of parsing is printed using the result's `toString` method. If parsing fails, the error + * message is displayed. * * See also [[sampleParse]] and [[sampleCompletions]]. */ @@ -451,9 +479,9 @@ trait ParserMain { if (completions) sampleCompletions(str, parser) else sampleParse(str, parser) /** - * Convenience method to use when developing a parser. - * `parser` is applied to the input `str` and the result of parsing is printed using the result's `toString` method. - * If parsing fails, the error message is displayed. + * Convenience method to use when developing a parser. `parser` is applied to the input `str` and + * the result of parsing is printed using the result's `toString` method. If parsing fails, the + * error message is displayed. */ def sampleParse(str: String, parser: Parser[_]): Unit = parse(str, parser) match { @@ -462,9 +490,9 @@ trait ParserMain { } /** - * Convenience method to use when developing a parser. - * `parser` is applied to the input `str` and the available completions are displayed on separate lines. - * If parsing fails, the error message is displayed. + * Convenience method to use when developing a parser. `parser` is applied to the input `str` and + * the available completions are displayed on separate lines. If parsing fails, the error message + * is displayed. */ def sampleCompletions(str: String, parser: Parser[_], level: Int = 1): Unit = Parser.completions(parser, str, level).get foreach println @@ -481,7 +509,8 @@ trait ParserMain { val msgs = msgs0() val nonEmpty = if (msgs.isEmpty) Seq("Unexpected end of input") else msgs (nonEmpty, ci) - } else + } + else loop(ci, a derive s(ci)) } loop(-1, p) @@ -496,10 +525,10 @@ trait ParserMain { if (p.valid) p.derive(c) else p /** - * Applies parser `p` to input `s` and returns the completions at verbosity `level`. - * The interpretation of `level` is up to parser definitions, but 0 is the default by convention, - * with increasing positive numbers corresponding to increasing verbosity. Typically no more than - * a few levels are defined. + * Applies parser `p` to input `s` and returns the completions at verbosity `level`. The + * interpretation of `level` is up to parser definitions, but 0 is the default by convention, with + * increasing positive numbers corresponding to increasing verbosity. Typically no more than a few + * levels are defined. */ def completions(p: Parser[_], s: String, level: Int): Completions = // The x Completions.empty removes any trailing token completions where append.isEmpty @@ -509,14 +538,20 @@ trait ParserMain { examples(a, new FixedSetExamples(completions), completions.size, check) /** - * @param a the parser to decorate with a source of examples. All validation and parsing is delegated to this parser, - * only [[Parser.completions]] is modified. - * @param completions the source of examples when displaying completions to the user. - * @param maxNumberOfExamples limits the number of examples that the source of examples should return. This can - * prevent lengthy pauses and avoids bad interactive user experience. - * @param removeInvalidExamples indicates whether completion examples should be checked for validity (against the given parser). An - * exception is thrown if the example source contains no valid completion suggestions. - * @tparam A the type of values that are returned by the parser. + * @param a + * the parser to decorate with a source of examples. All validation and parsing is delegated to + * this parser, only [[Parser.completions]] is modified. + * @param completions + * the source of examples when displaying completions to the user. + * @param maxNumberOfExamples + * limits the number of examples that the source of examples should return. This can prevent + * lengthy pauses and avoids bad interactive user experience. + * @param removeInvalidExamples + * indicates whether completion examples should be checked for validity (against the given + * parser). An exception is thrown if the example source contains no valid completion + * suggestions. + * @tparam A + * the type of values that are returned by the parser. * @return */ def examples[A]( @@ -548,31 +583,33 @@ trait ParserMain { } /** - * Establishes delegate parser `t` as a single token of tab completion. - * When tab completion of part of this token is requested, the completions provided by the delegate `t` or a later derivative are appended to - * the prefix String already seen by this parser. + * Establishes delegate parser `t` as a single token of tab completion. When tab completion of + * part of this token is requested, the completions provided by the delegate `t` or a later + * derivative are appended to the prefix String already seen by this parser. */ def token[T](t: Parser[T]): Parser[T] = token(t, TokenCompletions.default) /** - * Establishes delegate parser `t` as a single token of tab completion. - * When tab completion of part of this token is requested, no completions are returned if `hide` returns true for the current tab completion level. - * Otherwise, the completions provided by the delegate `t` or a later derivative are appended to the prefix String already seen by this parser. + * Establishes delegate parser `t` as a single token of tab completion. When tab completion of + * part of this token is requested, no completions are returned if `hide` returns true for the + * current tab completion level. Otherwise, the completions provided by the delegate `t` or a + * later derivative are appended to the prefix String already seen by this parser. */ def token[T](t: Parser[T], hide: Int => Boolean): Parser[T] = token(t, TokenCompletions.default.hideWhen(hide)) /** - * Establishes delegate parser `t` as a single token of tab completion. - * When tab completion of part of this token is requested, `description` is displayed for suggestions and no completions are ever performed. + * Establishes delegate parser `t` as a single token of tab completion. When tab completion of + * part of this token is requested, `description` is displayed for suggestions and no completions + * are ever performed. */ def token[T](t: Parser[T], description: String): Parser[T] = token(t, TokenCompletions.displayOnly(description)) /** - * Establishes delegate parser `t` as a single token of tab completion. - * When tab completion of part of this token is requested, `display` is used as the printed suggestion, but the completions from the delegate - * parser `t` are used to complete if unambiguous. + * Establishes delegate parser `t` as a single token of tab completion. When tab completion of + * part of this token is requested, `display` is used as the printed suggestion, but the + * completions from the delegate parser `t` are used to complete if unambiguous. */ def tokenDisplay[T](t: Parser[T], display: String): Parser[T] = token(t, TokenCompletions.overrideDisplay(display)) @@ -842,19 +879,25 @@ private final class Not(delegate: Parser[_], failMessage: String) extends ValidP } /** - * This class wraps an existing parser (the delegate), and replaces the delegate's completions with examples from - * the given example source. + * This class wraps an existing parser (the delegate), and replaces the delegate's completions with + * examples from the given example source. * - * This class asks the example source for a limited amount of examples (to prevent lengthy and expensive - * computations and large amounts of allocated data). It then passes these examples on to the UI. + * This class asks the example source for a limited amount of examples (to prevent lengthy and + * expensive computations and large amounts of allocated data). It then passes these examples on to + * the UI. * - * @param delegate the parser to decorate with completion examples (i.e., completion of user input). - * @param exampleSource the source from which this class will take examples (potentially filter them with the delegate - * parser), and pass them to the UI. - * @param maxNumberOfExamples the maximum number of completions to read from the example source and pass to the UI. This - * limit prevents lengthy example generation and allocation of large amounts of memory. - * @param removeInvalidExamples indicates whether to remove examples that are deemed invalid by the delegate parser. - * @tparam T the type of value produced by the parser. + * @param delegate + * the parser to decorate with completion examples (i.e., completion of user input). + * @param exampleSource + * the source from which this class will take examples (potentially filter them with the delegate + * parser), and pass them to the UI. + * @param maxNumberOfExamples + * the maximum number of completions to read from the example source and pass to the UI. This + * limit prevents lengthy example generation and allocation of large amounts of memory. + * @param removeInvalidExamples + * indicates whether to remove examples that are deemed invalid by the delegate parser. + * @tparam T + * the type of value produced by the parser. */ private final class ParserWithExamples[T]( delegate: Parser[T], @@ -876,8 +919,7 @@ private final class ParserWithExamples[T]( lazy val resultEmpty = delegate.resultEmpty def completions(level: Int) = { - if (exampleSource().isEmpty) - if (resultEmpty.isValid) Completions.nil else Completions.empty + if (exampleSource().isEmpty) if (resultEmpty.isValid) Completions.nil else Completions.empty else { val examplesBasedOnTheResult = filteredExamples.take(maxNumberOfExamples).toSet Completions(examplesBasedOnTheResult.map(ex => Completion.suggestion(ex))) diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parsers.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parsers.scala index 15a1f2dcb..f73122c01 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parsers.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/Parsers.scala @@ -33,10 +33,10 @@ trait Parsers { /** Parses any single character and provides that character as the result. */ lazy val any: Parser[Char] = charClass(_ => true, "any character") - /** Set that contains each digit in a String representation.*/ + /** Set that contains each digit in a String representation. */ lazy val DigitSet = Set("0", "1", "2", "3", "4", "5", "6", "7", "8", "9") - /** Parses any single digit and provides that digit as a Char as the result.*/ + /** Parses any single digit and provides that digit as a Char as the result. */ lazy val Digit = charClass(_.isDigit, "digit") examples DigitSet /** Set containing Chars for hexadecimal digits 0-9 and A-F (but not a-f). */ @@ -57,34 +57,57 @@ trait Parsers { /** Parses a single letter, according to Char.isLower, into a Char. */ lazy val Lower = charClass(_.isLower, "lower") - /** Parses the first Char in an sbt identifier, which must be a [[Letter]].*/ + /** Parses the first Char in an sbt identifier, which must be a [[Letter]]. */ def IDStart = Letter - /** Parses an identifier Char other than the first character. This includes letters, digits, dash `-`, and underscore `_`.*/ + /** + * Parses an identifier Char other than the first character. This includes letters, digits, dash + * `-`, and underscore `_`. + */ lazy val IDChar = charClass(isIDChar, "ID character") - /** Parses an identifier String, which must start with [[IDStart]] and contain zero or more [[IDChar]]s after that. */ + /** + * Parses an identifier String, which must start with [[IDStart]] and contain zero or more + * [[IDChar]]s after that. + */ lazy val ID = identifier(IDStart, IDChar) /** Parses a single operator Char, as allowed by [[isOpChar]]. */ lazy val OpChar = charClass(isOpChar, "symbol") - /** Parses a non-empty operator String, which consists only of characters allowed by [[OpChar]]. */ + /** + * Parses a non-empty operator String, which consists only of characters allowed by [[OpChar]]. + */ lazy val Op = OpChar.+.string - /** Parses either an operator String defined by [[Op]] or a non-symbolic identifier defined by [[ID]]. */ + /** + * Parses either an operator String defined by [[Op]] or a non-symbolic identifier defined by + * [[ID]]. + */ lazy val OpOrID = ID | Op - /** Parses a single, non-symbolic Scala identifier Char. Valid characters are letters, digits, and the underscore character `_`. */ + /** + * Parses a single, non-symbolic Scala identifier Char. Valid characters are letters, digits, and + * the underscore character `_`. + */ lazy val ScalaIDChar = charClass(isScalaIDChar, "Scala identifier character") - /** Parses a non-symbolic Scala-like identifier. The identifier must start with [[IDStart]] and contain zero or more [[ScalaIDChar]]s after that.*/ + /** + * Parses a non-symbolic Scala-like identifier. The identifier must start with [[IDStart]] and + * contain zero or more [[ScalaIDChar]]s after that. + */ lazy val ScalaID = identifier(IDStart, ScalaIDChar) - /** Parses a non-symbolic Scala-like identifier. The identifier must start with [[Upper]] and contain zero or more [[ScalaIDChar]]s after that.*/ + /** + * Parses a non-symbolic Scala-like identifier. The identifier must start with [[Upper]] and + * contain zero or more [[ScalaIDChar]]s after that. + */ lazy val CapitalizedID = identifier(Upper, ScalaIDChar) - /** Parses a String that starts with `start` and is followed by zero or more characters parsed by `rep`.*/ + /** + * Parses a String that starts with `start` and is followed by zero or more characters parsed by + * `rep`. + */ def identifier(start: Parser[Char], rep: Parser[Char]): Parser[String] = start ~ rep.* map { case x ~ xs => (x +: xs).mkString } @@ -102,7 +125,7 @@ trait Parsers { def isOpType(cat: Int) = cat match { case MATH_SYMBOL | OTHER_SYMBOL | DASH_PUNCTUATION | OTHER_PUNCTUATION | MODIFIER_SYMBOL | CURRENCY_SYMBOL => - true; case _ => false + true; case _ => false } /** Returns true if `c` is a dash `-`, a letter, digit, or an underscore `_`. */ @@ -118,7 +141,7 @@ trait Parsers { /** Matches a single character that is not a whitespace character. */ lazy val NotSpaceClass = charClass(!_.isWhitespace, "non-whitespace character") - /** Matches a single whitespace character, as determined by Char.isWhitespace.*/ + /** Matches a single whitespace character, as determined by Char.isWhitespace. */ lazy val SpaceClass = charClass(_.isWhitespace, "whitespace character") /** Matches a non-empty String consisting of non-whitespace characters. */ @@ -128,21 +151,23 @@ trait Parsers { lazy val OptNotSpace = NotSpaceClass.*.string /** - * Matches a non-empty String consisting of whitespace characters. - * The suggested tab completion is a single, constant space character. + * Matches a non-empty String consisting of whitespace characters. The suggested tab completion is + * a single, constant space character. */ lazy val Space: Parser[Seq[Char]] = SpaceClass.+.examples(" ") /** - * Matches a possibly empty String consisting of whitespace characters. - * The suggested tab completion is a single, constant space character. + * Matches a possibly empty String consisting of whitespace characters. The suggested tab + * completion is a single, constant space character. */ lazy val OptSpace = SpaceClass.*.examples(" ") - /** Parses a non-empty String that contains only valid URI characters, as defined by [[URIChar]].*/ + /** + * Parses a non-empty String that contains only valid URI characters, as defined by [[URIChar]]. + */ lazy val URIClass = URIChar.+.string !!! "Invalid URI" - /** Triple-quotes, as used for verbatim quoting.*/ + /** Triple-quotes, as used for verbatim quoting. */ lazy val VerbatimDQuotes = "\"\"\"" /** Double quote character. */ @@ -156,15 +181,21 @@ trait Parsers { /** Matches any character except a double quote or whitespace. */ lazy val NotDQuoteSpaceClass = - charClass({ c: Char => - (c != DQuoteChar) && !c.isWhitespace - }, "non-double-quote-space character") + charClass( + { c: Char => + (c != DQuoteChar) && !c.isWhitespace + }, + "non-double-quote-space character" + ) /** Matches any character except a double quote or backslash. */ lazy val NotDQuoteBackslashClass = - charClass({ c: Char => - (c != DQuoteChar) && (c != BackslashChar) - }, "non-double-quote-backslash character") + charClass( + { c: Char => + (c != DQuoteChar) && (c != BackslashChar) + }, + "non-double-quote-backslash character" + ) /** Matches a single character that is valid somewhere in a URI. */ lazy val URIChar = charClass(alphanum, "alphanum") | chars("_-!.~'()*,;:$&+=?/[]@%#") @@ -174,16 +205,21 @@ trait Parsers { ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') /** - * @param base the directory used for completion proposals (when the user presses the TAB key). Only paths under this - * directory will be proposed. - * @return the file that was parsed from the input string. The returned path may or may not exist. + * @param base + * the directory used for completion proposals (when the user presses the TAB key). Only paths + * under this directory will be proposed. + * @return + * the file that was parsed from the input string. The returned path may or may not exist. */ def fileParser(base: File): Parser[File] = OptSpace ~> StringBasic .examples(new FileExamples(base)) .map(new File(_)) - /** Parses a port number. Currently, this accepts any integer and presents a tab completion suggestion of ``. */ + /** + * Parses a port number. Currently, this accepts any integer and presents a tab completion + * suggestion of ``. + */ lazy val Port = token(IntBasic, "") /** Parses a signed integer. */ @@ -195,44 +231,49 @@ trait Parsers { private[this] def toInt(neg: Option[Char], digits: Seq[Char]): Int = (neg.toSeq ++ digits).mkString.toInt - /** Parses the lower-case values `true` and `false` into their corresponding Boolean values. */ + /** Parses the lower-case values `true` and `false` into their corresponding Boolean values. */ lazy val Bool = ("true" ^^^ true) | ("false" ^^^ false) /** - * Parses a potentially quoted String value. The value may be verbatim quoted ([[StringVerbatim]]), - * quoted with interpreted escapes ([[StringEscapable]]), or unquoted ([[NotQuoted]]). + * Parses a potentially quoted String value. The value may be verbatim quoted + * ([[StringVerbatim]]), quoted with interpreted escapes ([[StringEscapable]]), or unquoted + * ([[NotQuoted]]). */ lazy val StringBasic = StringVerbatim | StringEscapable | NotQuoted | NotQuotedThenQuoted /** - * Parses a verbatim quoted String value, discarding the quotes in the result. This kind of quoted text starts with triple quotes `"""` - * and ends at the next triple quotes and may contain any character in between. + * Parses a verbatim quoted String value, discarding the quotes in the result. This kind of quoted + * text starts with triple quotes `"""` and ends at the next triple quotes and may contain any + * character in between. */ lazy val StringVerbatim: Parser[String] = VerbatimDQuotes ~> any.+.string.filter(!_.contains(VerbatimDQuotes), _ => "Invalid verbatim string") <~ VerbatimDQuotes /** - * Parses a string value, interpreting escapes and discarding the surrounding quotes in the result. - * See [[EscapeSequence]] for supported escapes. + * Parses a string value, interpreting escapes and discarding the surrounding quotes in the + * result. See [[EscapeSequence]] for supported escapes. */ lazy val StringEscapable: Parser[String] = (DQuoteChar ~> (NotDQuoteBackslashClass | EscapeSequence).+.string <~ DQuoteChar | (DQuoteChar ~ DQuoteChar) ^^^ "") /** - * Parses a size unit string. For example, `128K` parsers to `128L * 1024`, and `1.25g` parses - * to `1024L * 1024 * 1024 * 5 / 4`. + * Parses a size unit string. For example, `128K` parsers to `128L * 1024`, and `1.25g` parses to + * `1024L * 1024 * 1024 * 5 / 4`. */ lazy val Size: Parser[Long] = SizeParser.value /** - * Parses a brace enclosed string and, if each opening brace is matched with a closing brace, - * it returns the entire string including the braces. + * Parses a brace enclosed string and, if each opening brace is matched with a closing brace, it + * returns the entire string including the braces. * - * @param open the opening character, e.g. '{' - * @param close the closing character, e.g. '}' - * @return a parser for the brace encloosed string. + * @param open + * the opening character, e.g. '{' + * @param close + * the closing character, e.g. '}' + * @return + * a parser for the brace encloosed string. */ private[sbt] def braces(open: Char, close: Char): Parser[String] = { val notDelim = charClass(c => c != open && c != close).*.string @@ -240,10 +281,10 @@ trait Parsers { (open ~ (notDelim ~ close).?).flatMap { case (l, Some((content, r))) => Parser.success(s"$l$content$r") case (l, None) => - ((notDelim ~ impl()).map { - case (leftPrefix, nestedBraces) => leftPrefix + nestedBraces - }.+ ~ notDelim ~ close).map { - case ((nested, suffix), r) => s"$l${nested.mkString}$suffix$r" + ((notDelim ~ impl()).map { case (leftPrefix, nestedBraces) => + leftPrefix + nestedBraces + }.+ ~ notDelim ~ close).map { case ((nested, suffix), r) => + s"$l${nested.mkString}$suffix$r" } } } @@ -251,23 +292,27 @@ trait Parsers { } /** - * Parses a single escape sequence into the represented Char. - * Escapes start with a backslash and are followed by `u` for a [[UnicodeEscape]] or by `b`, `t`, `n`, `f`, `r`, `"`, `'`, `\` for standard escapes. + * Parses a single escape sequence into the represented Char. Escapes start with a backslash and + * are followed by `u` for a [[UnicodeEscape]] or by `b`, `t`, `n`, `f`, `r`, `"`, `'`, `\` for + * standard escapes. */ lazy val EscapeSequence: Parser[Char] = BackslashChar ~> ('b' ^^^ '\b' | 't' ^^^ '\t' | 'n' ^^^ '\n' | 'f' ^^^ '\f' | 'r' ^^^ '\r' | '\"' ^^^ '\"' | '\'' ^^^ '\'' | '\\' ^^^ '\\' | UnicodeEscape) /** - * Parses a single unicode escape sequence into the represented Char. - * A unicode escape begins with a backslash, followed by a `u` and 4 hexadecimal digits representing the unicode value. + * Parses a single unicode escape sequence into the represented Char. A unicode escape begins with + * a backslash, followed by a `u` and 4 hexadecimal digits representing the unicode value. */ lazy val UnicodeEscape: Parser[Char] = ("u" ~> repeat(HexDigit, 4, 4)) map { seq => Integer.parseInt(seq.mkString, 16).toChar } - /** Parses an unquoted, non-empty String value that cannot start with a double quote and cannot contain whitespace.*/ + /** + * Parses an unquoted, non-empty String value that cannot start with a double quote and cannot + * contain whitespace. + */ lazy val NotQuoted = (NotDQuoteSpaceClass ~ OptNotSpace) map { case (c, s) => c.toString + s } /** Parses a non-empty String value that cannot start with a double quote, but includes double quotes.*/ @@ -276,27 +321,27 @@ trait Parsers { } /** - * Applies `rep` zero or more times, separated by `sep`. - * The result is the (possibly empty) sequence of results from the multiple `rep` applications. The `sep` results are discarded. + * Applies `rep` zero or more times, separated by `sep`. The result is the (possibly empty) + * sequence of results from the multiple `rep` applications. The `sep` results are discarded. */ def repsep[T](rep: Parser[T], sep: Parser[_]): Parser[Seq[T]] = rep1sep(rep, sep) ?? nilSeq[T] /** - * Applies `rep` one or more times, separated by `sep`. - * The result is the non-empty sequence of results from the multiple `rep` applications. The `sep` results are discarded. + * Applies `rep` one or more times, separated by `sep`. The result is the non-empty sequence of + * results from the multiple `rep` applications. The `sep` results are discarded. */ def rep1sep[T](rep: Parser[T], sep: Parser[_]): Parser[Seq[T]] = (rep ~ (sep ~> rep).*).map { case (x ~ xs) => x +: xs } - /** Wraps the result of `p` in `Some`.*/ + /** Wraps the result of `p` in `Some`. */ def some[T](p: Parser[T]): Parser[Option[T]] = p map { v => Some(v) } /** - * Applies `f` to the result of `p`, transforming any exception when evaluating - * `f` into a parse failure with the exception `toString` as the message. + * Applies `f` to the result of `p`, transforming any exception when evaluating `f` into a parse + * failure with the exception `toString` as the message. */ def mapOrFail[S, T](p: Parser[S])(f: S => T): Parser[T] = p flatMap { s => @@ -306,20 +351,24 @@ trait Parsers { } /** - * Parses a space-delimited, possibly empty sequence of arguments. - * The arguments may use quotes and escapes according to [[StringBasic]]. + * Parses a space-delimited, possibly empty sequence of arguments. The arguments may use quotes + * and escapes according to [[StringBasic]]. */ def spaceDelimited(display: String): Parser[Seq[String]] = (token(Space) ~> token(StringBasic, display)).* <~ SpaceClass.* - /** Applies `p` and uses `true` as the result if it succeeds and turns failure into a result of `false`. */ + /** + * Applies `p` and uses `true` as the result if it succeeds and turns failure into a result of + * `false`. + */ def flag[T](p: Parser[T]): Parser[Boolean] = (p ^^^ true) ?? false /** - * Defines a sequence parser where the parser used for each part depends on the previously parsed values. - * `p` is applied to the (possibly empty) sequence of already parsed values to obtain the next parser to use. - * The parsers obtained in this way are separated by `sep`, whose result is discarded and only the sequence - * of values from the parsers returned by `p` is used for the result. + * Defines a sequence parser where the parser used for each part depends on the previously parsed + * values. `p` is applied to the (possibly empty) sequence of already parsed values to obtain the + * next parser to use. The parsers obtained in this way are separated by `sep`, whose result is + * discarded and only the sequence of values from the parsers returned by `p` is used for the + * result. */ def repeatDep[A](p: Seq[A] => Parser[A], sep: Parser[Any]): Parser[Seq[A]] = { def loop(acc: Seq[A]): Parser[Seq[A]] = { @@ -339,21 +388,24 @@ trait Parsers { /** Parses a URI that is valid according to the single argument java.net.URI constructor. */ lazy val basicUri = mapOrFail(URIClass)(uri => new URI(uri)) - /** Parses a URI that is valid according to the single argument java.net.URI constructor, using `ex` as tab completion examples. */ + /** + * Parses a URI that is valid according to the single argument java.net.URI constructor, using + * `ex` as tab completion examples. + */ def Uri(ex: Set[URI]) = basicUri examples (ex.map(_.toString)) } /** Provides standard [[Parser]] implementations. */ object Parsers extends Parsers -/** Provides common [[Parser]] implementations and helper methods.*/ +/** Provides common [[Parser]] implementations and helper methods. */ object DefaultParsers extends Parsers with ParserMain { /** Applies parser `p` to input `s` and returns `true` if the parse was successful. */ def matches(p: Parser[_], s: String): Boolean = apply(p)(s).resultEmpty.isValid - /** Returns `true` if `s` parses successfully according to [[ID]].*/ + /** Returns `true` if `s` parses successfully according to [[ID]]. */ def validID(s: String): Boolean = { // Handwritten version of `matches(ID, s)` because validID turned up in profiling. def isIdChar(c: Char): Boolean = Character.isLetterOrDigit(c) || (c == '-') || (c == '_') diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/SizeParser.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/SizeParser.scala index 1ca63efbe..478261f1c 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/SizeParser.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/SizeParser.scala @@ -44,13 +44,12 @@ private[sbt] object SizeParser { ((numberParser <~ SpaceClass .examples(" ", "b", "B", "g", "G", "k", "K", "m", "M") .*) ~ unitParser.?) - .map { - case (number, unit) => - unit match { - case None | Some(Bytes) => multiply(number, right = 1L) - case Some(KiloBytes) => multiply(number, right = 1024L) - case Some(MegaBytes) => multiply(number, right = 1024L * 1024) - case Some(GigaBytes) => multiply(number, right = 1024L * 1024 * 1024) - } + .map { case (number, unit) => + unit match { + case None | Some(Bytes) => multiply(number, right = 1L) + case Some(KiloBytes) => multiply(number, right = 1024L) + case Some(MegaBytes) => multiply(number, right = 1024L * 1024) + case Some(GigaBytes) => multiply(number, right = 1024L * 1024 * 1024) + } } } diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/TypeString.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/TypeString.scala index 3a4e84ad2..28933c8cf 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/TypeString.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/TypeString.scala @@ -12,9 +12,9 @@ import DefaultParsers._ import TypeString._ /** - * Basic representation of types parsed from Manifest.toString. - * This can only represent the structure of parameterized types. - * All other types are represented by a TypeString with an empty `args`. + * Basic representation of types parsed from Manifest.toString. This can only represent the + * structure of parameterized types. All other types are represented by a TypeString with an empty + * `args`. */ private[sbt] final class TypeString(val base: String, val args: List[TypeString]) { override def toString = @@ -28,7 +28,7 @@ private[sbt] final class TypeString(val base: String, val args: List[TypeString] private[sbt] object TypeString { - /** Makes the string representation of a type as returned by Manifest.toString more readable.*/ + /** Makes the string representation of a type as returned by Manifest.toString more readable. */ def cleanup(typeString: String): String = parse(typeString, typeStringParser) match { case Right(ts) => ts.toString @@ -36,19 +36,19 @@ private[sbt] object TypeString { } /** - * Makes a fully qualified type name provided by Manifest.toString more readable. - * The argument should be just a name (like scala.Tuple2) and not a full type (like scala.Tuple2[Int,Boolean]) + * Makes a fully qualified type name provided by Manifest.toString more readable. The argument + * should be just a name (like scala.Tuple2) and not a full type (like scala.Tuple2[Int,Boolean]) */ def cleanupTypeName(base: String): String = dropPrefix(base).replace('$', '.') /** - * Removes prefixes from a fully qualified type name that are unnecessary in the presence of standard imports for an sbt setting. - * This does not use the compiler and is therefore a conservative approximation. + * Removes prefixes from a fully qualified type name that are unnecessary in the presence of + * standard imports for an sbt setting. This does not use the compiler and is therefore a + * conservative approximation. */ def dropPrefix(base: String): String = - if (base.startsWith(SbtPrefix)) - base.substring(SbtPrefix.length) + if (base.startsWith(SbtPrefix)) base.substring(SbtPrefix.length) else if (base.startsWith(CollectionPrefix)) { val simple = base.substring(CollectionPrefix.length) if (ShortenCollection(simple)) simple else base @@ -75,8 +75,9 @@ private[sbt] object TypeString { ) /** - * A Parser that extracts basic structure from the string representation of a type from Manifest.toString. - * This is rudimentary and essentially only decomposes the string into names and arguments for parameterized types. + * A Parser that extracts basic structure from the string representation of a type from + * Manifest.toString. This is rudimentary and essentially only decomposes the string into names + * and arguments for parameterized types. */ lazy val typeStringParser: Parser[TypeString] = { def isFullScalaIDChar(c: Char) = isScalaIDChar(c) || c == '.' || c == '$' diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/complete/UpperBound.scala b/internal/util-complete/src/main/scala/sbt/internal/util/complete/UpperBound.scala index c502f8784..7822c752a 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/complete/UpperBound.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/complete/UpperBound.scala @@ -10,22 +10,23 @@ package complete sealed trait UpperBound { - /** True if and only if the given value meets this bound.*/ + /** True if and only if the given value meets this bound. */ def >=(min: Int): Boolean - /** True if and only if this bound is one.*/ + /** True if and only if this bound is one. */ def isOne: Boolean - /** True if and only if this bound is zero.*/ + /** True if and only if this bound is zero. */ def isZero: Boolean /** - * If this bound is zero or Infinite, `decrement` returns this bound. - * Otherwise, this bound is finite and greater than zero and `decrement` returns the bound that is one less than this bound. + * If this bound is zero or Infinite, `decrement` returns this bound. Otherwise, this bound is + * finite and greater than zero and `decrement` returns the bound that is one less than this + * bound. */ def decrement: UpperBound - /** True if and only if this is unbounded.*/ + /** True if and only if this is unbounded. */ def isInfinite: Boolean } @@ -45,8 +46,8 @@ case object Infinite extends UpperBound { } /** - * Represents a finite upper bound. The maximum allowed value is 'value', inclusive. - * It must positive. + * Represents a finite upper bound. The maximum allowed value is 'value', inclusive. It must + * positive. */ final case class Finite(value: Int) extends UpperBound { assume(value >= 0, "Maximum occurrences must be nonnegative.") diff --git a/internal/util-complete/src/test/scala/DefaultParsersSpec.scala b/internal/util-complete/src/test/scala/DefaultParsersSpec.scala index b0f7bd47e..2ea81e7bf 100644 --- a/internal/util-complete/src/test/scala/DefaultParsersSpec.scala +++ b/internal/util-complete/src/test/scala/DefaultParsersSpec.scala @@ -13,9 +13,8 @@ import org.scalacheck._, Gen._, Prop._ object DefaultParsersSpec extends Properties("DefaultParsers") { import DefaultParsers.{ ID, isIDChar, matches, validID } - property("∀ s ∈ String: validID(s) == matches(ID, s)") = forAll( - (s: String) => validID(s) == matches(ID, s) - ) + property("∀ s ∈ String: validID(s) == matches(ID, s)") = + forAll((s: String) => validID(s) == matches(ID, s)) property("∀ s ∈ genID: matches(ID, s)") = forAll(genID)(s => matches(ID, s)) property("∀ s ∈ genID: validID(s)") = forAll(genID)(s => validID(s)) diff --git a/internal/util-complete/src/test/scala/sbt/complete/FileExamplesTest.scala b/internal/util-complete/src/test/scala/sbt/complete/FileExamplesTest.scala index da4662308..5b6a690a1 100644 --- a/internal/util-complete/src/test/scala/sbt/complete/FileExamplesTest.scala +++ b/internal/util-complete/src/test/scala/sbt/complete/FileExamplesTest.scala @@ -16,10 +16,10 @@ class FileExamplesTest extends UnitSpec { "listing all files in an absolute base directory" should "produce the entire base directory's contents" in { - withDirectoryStructure() { ds => - ds.fileExamples().toList should contain theSameElementsAs (ds.allRelativizedPaths) + withDirectoryStructure() { ds => + ds.fileExamples().toList should contain theSameElementsAs (ds.allRelativizedPaths) + } } - } "listing files with a prefix that matches none" should "produce an empty list" in { withDirectoryStructure(withCompletionPrefix = "z") { ds => diff --git a/internal/util-complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala b/internal/util-complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala index 93e8e4c05..840932368 100644 --- a/internal/util-complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala +++ b/internal/util-complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala @@ -14,57 +14,57 @@ class ParserWithExamplesTest extends UnitSpec { "listing a limited number of completions" should "grab only the needed number of elements from the iterable source of examples" in { - val _ = new ParserWithLazyExamples { - parserWithExamples.completions(0) - examples.size shouldEqual maxNumberOfExamples + val _ = new ParserWithLazyExamples { + parserWithExamples.completions(0) + examples.size shouldEqual maxNumberOfExamples + } } - } "listing only valid completions" should "use the delegate parser to remove invalid examples" in { - val _ = new ParserWithValidExamples { - val validCompletions = Completions( - Set( - suggestion("blue"), - suggestion("red") + val _ = new ParserWithValidExamples { + val validCompletions = Completions( + Set( + suggestion("blue"), + suggestion("red") + ) ) - ) - parserWithExamples.completions(0) shouldEqual validCompletions + parserWithExamples.completions(0) shouldEqual validCompletions + } } - } "listing valid completions in a derived parser" should "produce only valid examples that start with the character of the derivation" in { - val _ = new ParserWithValidExamples { - val derivedCompletions = Completions( - Set( - suggestion("lue") + val _ = new ParserWithValidExamples { + val derivedCompletions = Completions( + Set( + suggestion("lue") + ) ) - ) - parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions + parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions + } } - } "listing valid and invalid completions" should "produce the entire source of examples" in { - val _ = new parserWithAllExamples { - val completions = Completions(examples.map(suggestion(_)).toSet) - parserWithExamples.completions(0) shouldEqual completions + val _ = new parserWithAllExamples { + val completions = Completions(examples.map(suggestion(_)).toSet) + parserWithExamples.completions(0) shouldEqual completions + } } - } "listing valid and invalid completions in a derived parser" should "produce only examples that start with the character of the derivation" in { - val _ = new parserWithAllExamples { - val derivedCompletions = Completions( - Set( - suggestion("lue"), - suggestion("lock") + val _ = new parserWithAllExamples { + val derivedCompletions = Completions( + Set( + suggestion("lue"), + suggestion("lock") + ) ) - ) - parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions + parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions + } } - } class ParserWithLazyExamples extends ParserExample( diff --git a/internal/util-logging/src/main/scala/com/github/ghik/silencer/silent.scala b/internal/util-logging/src/main/scala/com/github/ghik/silencer/silent.scala index 0918e75aa..a8ba5d95f 100644 --- a/internal/util-logging/src/main/scala/com/github/ghik/silencer/silent.scala +++ b/internal/util-logging/src/main/scala/com/github/ghik/silencer/silent.scala @@ -10,8 +10,8 @@ package com.github.ghik.silencer import scala.annotation.Annotation /** - * When silencer compiler plugin is enabled, this annotation suppresses all warnings emitted by scalac for some portion - * of source code. It can be applied on any definition (`class`, def`, `val`, `var`, etc.) or on arbitrary expression, - * e.g. {123; 456}: @silent` + * When silencer compiler plugin is enabled, this annotation suppresses all warnings emitted by + * scalac for some portion of source code. It can be applied on any definition (`class`, def`, + * `val`, `var`, etc.) or on arbitrary expression, e.g. {123; 456}: @silent` */ class silent extends Annotation diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/BasicLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/BasicLogger.scala index 802e60a42..d61f43b3e 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/BasicLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/BasicLogger.scala @@ -9,7 +9,7 @@ package sbt.internal.util import sbt.util._ -/** Implements the level-setting methods of Logger.*/ +/** Implements the level-setting methods of Logger. */ abstract class BasicLogger extends AbstractLogger { private var traceEnabledVar: Int = java.lang.Integer.MAX_VALUE private var level: Level.Value = Level.Info diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala index 827cfa82f..b1cc338f1 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala @@ -29,11 +29,10 @@ object BufferedAppender { } /** - * An appender that can buffer the logging done on it and then can flush the buffer - * to the delegate appender provided in the constructor. Use 'record()' to - * start buffering and then 'play' to flush the buffer to the backing appender. - * The logging level set at the time a message is originally logged is used, not - * the level at the time 'play' is called. + * An appender that can buffer the logging done on it and then can flush the buffer to the delegate + * appender provided in the constructor. Use 'record()' to start buffering and then 'play' to flush + * the buffer to the backing appender. The logging level set at the time a message is originally + * logged is used, not the level at the time 'play' is called. */ class BufferedAppender(override val name: String, delegate: Appender) extends Appender { override def close(): Unit = log4j.get match { @@ -108,8 +107,8 @@ class BufferedAppender(override val name: String, delegate: Appender) extends Ap } /** - * Flushes the buffer to the delegate logger. This method calls logAll on the delegate - * so that the messages are written consecutively. The buffer is cleared in the process. + * Flushes the buffer to the delegate logger. This method calls logAll on the delegate so that the + * messages are written consecutively. The buffer is cleared in the process. */ def play(): Unit = synchronized { @@ -131,11 +130,10 @@ class BufferedAppender(override val name: String, delegate: Appender) extends Ap } /** - * A logger that can buffer the logging done on it and then can flush the buffer - * to the delegate logger provided in the constructor. Use 'startRecording' to - * start buffering and then 'play' from to flush the buffer to the backing logger. - * The logging level set at the time a message is originally logged is used, not - * the level at the time 'play' is called. + * A logger that can buffer the logging done on it and then can flush the buffer to the delegate + * logger provided in the constructor. Use 'startRecording' to start buffering and then 'play' from + * to flush the buffer to the backing logger. The logging level set at the time a message is + * originally logged is used, not the level at the time 'play' is called. * * This class assumes that it is the only client of the delegate logger. */ @@ -168,8 +166,8 @@ class BufferedLogger(delegate: AbstractLogger) extends BasicLogger { } /** - * Flushes the buffer to the delegate logger. This method calls logAll on the delegate - * so that the messages are written consecutively. The buffer is cleared in the process. + * Flushes the buffer to the delegate logger. This method calls logAll on the delegate so that the + * messages are written consecutively. The buffer is cleared in the process. */ def play(): Unit = synchronized { delegate.logAll(buffer.toList); buffer.clear() } diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala index 2b1700572..3d0268045 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala @@ -40,27 +40,36 @@ object ConsoleLogger { /** * A new `ConsoleLogger` that logs to `out`. * - * @param out Where to log the messages. - * @return A new `ConsoleLogger` that logs to `out`. + * @param out + * Where to log the messages. + * @return + * A new `ConsoleLogger` that logs to `out`. */ def apply(out: PrintStream): ConsoleLogger = apply(ConsoleOut.printStreamOut(out)) /** * A new `ConsoleLogger` that logs to `out`. * - * @param out Where to log the messages. - * @return A new `ConsoleLogger` that logs to `out`. + * @param out + * Where to log the messages. + * @return + * A new `ConsoleLogger` that logs to `out`. */ def apply(out: PrintWriter): ConsoleLogger = apply(ConsoleOut.printWriterOut(out)) /** * A new `ConsoleLogger` that logs to `out`. * - * @param out Where to log the messages. - * @param ansiCodesSupported `true` if `out` supported ansi codes, `false` otherwise. - * @param useFormat `true` to show formatting, `false` to remove it from messages. - * @param suppressedMessage How to show suppressed stack traces. - * @return A new `ConsoleLogger` that logs to `out`. + * @param out + * Where to log the messages. + * @param ansiCodesSupported + * `true` if `out` supported ansi codes, `false` otherwise. + * @param useFormat + * `true` to show formatting, `false` to remove it from messages. + * @param suppressedMessage + * How to show suppressed stack traces. + * @return + * A new `ConsoleLogger` that logs to `out`. */ def apply( out: ConsoleOut = ConsoleOut.systemOut, @@ -73,8 +82,7 @@ object ConsoleLogger { } /** - * A logger that logs to the console. On supported systems, the level labels are - * colored. + * A logger that logs to the console. On supported systems, the level labels are colored. */ class ConsoleLogger private[ConsoleLogger] ( out: ConsoleOut, @@ -144,10 +152,9 @@ object ConsoleAppender { /** * Indicates whether formatting has been disabled in environment variables. - * 1. -Dsbt.log.noformat=true means no formatting. - * 2. -Dsbt.color=always/auto/never/true/false - * 3. -Dsbt.colour=always/auto/never/true/false - * 4. -Dsbt.log.format=always/auto/never/true/false + * 1. -Dsbt.log.noformat=true means no formatting. 2. -Dsbt.color=always/auto/never/true/false + * 3. -Dsbt.colour=always/auto/never/true/false 4. + * -Dsbt.log.format=always/auto/never/true/false */ @deprecated("Use Terminal.isAnsiSupported or Terminal.isColorEnabled", "1.4.0") lazy val formatEnabledInEnv: Boolean = Terminal.isAnsiSupported @@ -163,58 +170,74 @@ object ConsoleAppender { /** * A new `ConsoleAppender` that writes to standard output. * - * @return A new `ConsoleAppender` that writes to standard output. + * @return + * A new `ConsoleAppender` that writes to standard output. */ def apply(): Appender = apply(ConsoleOut.systemOut) /** * A new `ConsoleAppender` that appends log message to `out`. * - * @param out Where to write messages. - * @return A new `ConsoleAppender`. + * @param out + * Where to write messages. + * @return + * A new `ConsoleAppender`. */ def apply(out: PrintStream): Appender = apply(ConsoleOut.printStreamOut(out)) /** * A new `ConsoleAppender` that appends log messages to `out`. * - * @param out Where to write messages. - * @return A new `ConsoleAppender`. + * @param out + * Where to write messages. + * @return + * A new `ConsoleAppender`. */ def apply(out: PrintWriter): Appender = apply(ConsoleOut.printWriterOut(out)) /** * A new `ConsoleAppender` that writes to `out`. * - * @param out Where to write messages. - * @return A new `ConsoleAppender that writes to `out`. + * @param out + * Where to write messages. + * @return + * A new `ConsoleAppender that writes to `out`. */ def apply(out: ConsoleOut): Appender = apply(generateName(), out) /** * A new `ConsoleAppender` identified by `name`, and that writes to standard output. * - * @param name An identifier for the `ConsoleAppender`. - * @return A new `ConsoleAppender` that writes to standard output. + * @param name + * An identifier for the `ConsoleAppender`. + * @return + * A new `ConsoleAppender` that writes to standard output. */ def apply(name: String): Appender = apply(name, ConsoleOut.systemOut) /** * A new `ConsoleAppender` identified by `name`, and that writes to `out`. * - * @param name An identifier for the `ConsoleAppender`. - * @param out Where to write messages. - * @return A new `ConsoleAppender` that writes to `out`. + * @param name + * An identifier for the `ConsoleAppender`. + * @param out + * Where to write messages. + * @return + * A new `ConsoleAppender` that writes to `out`. */ def apply(name: String, out: ConsoleOut): Appender = apply(name, out, Terminal.isAnsiSupported) /** * A new `ConsoleAppender` identified by `name`, and that writes to `out`. * - * @param name An identifier for the `ConsoleAppender`. - * @param out Where to write messages. - * @param suppressedMessage How to handle stack traces. - * @return A new `ConsoleAppender` that writes to `out`. + * @param name + * An identifier for the `ConsoleAppender`. + * @param out + * Where to write messages. + * @param suppressedMessage + * How to handle stack traces. + * @return + * A new `ConsoleAppender` that writes to `out`. */ def apply( name: String, @@ -228,10 +251,14 @@ object ConsoleAppender { /** * A new `ConsoleAppender` identified by `name`, and that writes to `out`. * - * @param name An identifier for the `ConsoleAppender`. - * @param out Where to write messages. - * @param useFormat `true` to enable format (color, bold, etc.), `false` to remove formatting. - * @return A new `ConsoleAppender` that writes to `out`. + * @param name + * An identifier for the `ConsoleAppender`. + * @param out + * Where to write messages. + * @param useFormat + * `true` to enable format (color, bold, etc.), `false` to remove formatting. + * @return + * A new `ConsoleAppender` that writes to `out`. */ def apply(name: String, out: ConsoleOut, useFormat: Boolean): Appender = apply(name, out, useFormat || Terminal.isAnsiSupported, useFormat, noSuppressedMessage) @@ -239,9 +266,12 @@ object ConsoleAppender { /** * A new `ConsoleAppender` identified by `name`, and that writes to `out`. * - * @param name An identifier for the `ConsoleAppender`. - * @param terminal The terminal to which this appender corresponds - * @return A new `ConsoleAppender` that writes to `out`. + * @param name + * An identifier for the `ConsoleAppender`. + * @param terminal + * The terminal to which this appender corresponds + * @return + * A new `ConsoleAppender` that writes to `out`. */ def apply(name: String, terminal: Terminal): Appender = { new ConsoleAppender(name, Properties.from(terminal), noSuppressedMessage) @@ -262,10 +292,14 @@ object ConsoleAppender { /** * A new `ConsoleAppender` identified by `name`, and that writes to `out`. * - * @param name An identifier for the `ConsoleAppender`. - * @param terminal The terminal to which this appender corresponds - * @param suppressedMessage How to handle stack traces. - * @return A new `ConsoleAppender` that writes to `out`. + * @param name + * An identifier for the `ConsoleAppender`. + * @param terminal + * The terminal to which this appender corresponds + * @param suppressedMessage + * How to handle stack traces. + * @return + * A new `ConsoleAppender` that writes to `out`. */ def apply( name: String, @@ -278,12 +312,16 @@ object ConsoleAppender { /** * A new `ConsoleAppender` identified by `name`, and that writes to `out`. * - * @param name An identifier for the `ConsoleAppender`. - * @param out Where to write messages. - * @param ansiCodesSupported `true` if the output stream supports ansi codes, `false` otherwise. - * @param useFormat `true` to enable format (color, bold, etc.), `false` to remove - * formatting. - * @return A new `ConsoleAppender` that writes to `out`. + * @param name + * An identifier for the `ConsoleAppender`. + * @param out + * Where to write messages. + * @param ansiCodesSupported + * `true` if the output stream supports ansi codes, `false` otherwise. + * @param useFormat + * `true` to enable format (color, bold, etc.), `false` to remove formatting. + * @return + * A new `ConsoleAppender` that writes to `out`. */ def apply( name: String, @@ -302,8 +340,10 @@ object ConsoleAppender { /** * Converts the Log4J `level` to the corresponding sbt level. * - * @param level A level, as represented by Log4J. - * @return The corresponding level in sbt's world. + * @param level + * A level, as represented by Log4J. + * @return + * The corresponding level in sbt's world. */ def toLevel(level: XLevel): Level.Value = level match { @@ -319,8 +359,10 @@ object ConsoleAppender { /** * Converts the sbt `level` to the corresponding Log4J level. * - * @param level A level, as represented by sbt. - * @return The corresponding level in Log4J's world. + * @param level + * A level, as represented by sbt. + * @return + * The corresponding level in Log4J's world. */ def toXLevel(level: Level.Value): XLevel = level match { @@ -341,8 +383,7 @@ object ConsoleAppender { // https://logging.apache.org/log4j/2.x/log4j-core/apidocs/index.html /** - * A logger that logs to the console. On supported systems, the level labels are - * colored. + * A logger that logs to the console. On supported systems, the level labels are colored. * * This logger is not thread-safe. */ @@ -357,12 +398,17 @@ class ConsoleAppender( log4j.synchronized { log4j.get match { case null => - val l = new Log4JConsoleAppender(name, properties, suppressedMessage, { event => - val level = ConsoleAppender.toLevel(event.getLevel) - val message = event.getMessage - try appendMessage(level, message) - catch { case _: ClosedChannelException => } - }) + val l = new Log4JConsoleAppender( + name, + properties, + suppressedMessage, + { event => + val level = ConsoleAppender.toLevel(event.getLevel) + val message = event.getMessage + try appendMessage(level, message) + catch { case _: ClosedChannelException => } + } + ) log4j.set(l) l case l => l @@ -404,11 +450,13 @@ trait Appender extends AutoCloseable { /** * Logs the stack trace of `t`, possibly shortening it. * - * The `traceLevel` parameter configures how the stack trace will be shortened. - * See `StackTrace.trimmed`. + * The `traceLevel` parameter configures how the stack trace will be shortened. See + * `StackTrace.trimmed`. * - * @param t The `Throwable` whose stack trace to log. - * @param traceLevel How to shorten the stack trace. + * @param t + * The `Throwable` whose stack trace to log. + * @param traceLevel + * How to shorten the stack trace. */ def trace(t: => Throwable, traceLevel: Int): Unit = { if (traceLevel >= 0) @@ -423,8 +471,10 @@ trait Appender extends AutoCloseable { /** * Logs a `ControlEvent` to the log. * - * @param event The kind of `ControlEvent`. - * @param message The message to log. + * @param event + * The kind of `ControlEvent`. + * @param message + * The message to log. */ def control(event: ControlEvent.Value, message: => String): Unit = appendLog(labelColor(Level.Info), Level.Info.toString, BLUE, message) @@ -432,8 +482,10 @@ trait Appender extends AutoCloseable { /** * Appends the message `message` to the to the log at level `level`. * - * @param level The importance level of the message. - * @param message The message to log. + * @param level + * The importance level of the message. + * @param message + * The message to log. */ def appendLog(level: Level.Value, message: => String): Unit = { appendLog(labelColor(level), level.toString, NO_COLOR, message) @@ -442,8 +494,10 @@ trait Appender extends AutoCloseable { /** * Select the right color for the label given `level`. * - * @param level The label to consider to select the color. - * @return The color to use to color the label. + * @param level + * The label to consider to select the color. + * @return + * The color to use to color the label. */ private def labelColor(level: Level.Value): String = level match { @@ -457,11 +511,14 @@ trait Appender extends AutoCloseable { * `labelColor` if formatting is enabled. The lines of the messages are colored with * `messageColor` if formatting is enabled. * - * @param labelColor The color to use to format the label. - * @param label The label to prefix each line with. The label is shown between square - * brackets. - * @param messageColor The color to use to format the message. - * @param message The message to write. + * @param labelColor + * The color to use to format the label. + * @param label + * The label to prefix each line with. The label is shown between square brackets. + * @param messageColor + * The color to use to format the message. + * @param message + * The message to write. */ private def appendLog( labelColor: String, @@ -535,7 +592,9 @@ trait Appender extends AutoCloseable { codec.showLines(te).toVector foreach { appendLog(Level.Error, _) } } if (traceLevel <= 2) { - suppressedMessage(new SuppressedTraceContext(traceLevel, ansiCodesSupported && useFormat)) foreach { + suppressedMessage( + new SuppressedTraceContext(traceLevel, ansiCodesSupported && useFormat) + ) foreach { appendLog(Level.Error, _) } } @@ -545,7 +604,7 @@ trait Appender extends AutoCloseable { def appendEvent(oe: ObjectEvent[_]): Unit = { val contentType = oe.contentType contentType match { - case "sbt.internal.util.TraceEvent" => appendTraceEvent(oe.message.asInstanceOf[TraceEvent]) + case "sbt.internal.util.TraceEvent" => appendTraceEvent(oe.message.asInstanceOf[TraceEvent]) case "sbt.internal.util.ProgressEvent" => case _ => LogExchange.stringCodec[AnyRef](contentType) match { @@ -597,7 +656,7 @@ private[sbt] class ConsoleAppenderFromLog4J( delegate.append(new AbstractLogEvent { override def getLevel(): XLevel = ConsoleAppender.toXLevel(level) override def getMessage(): Message = - StringFormatterMessageFactory.INSTANCE.newMessage(message.toString, Array.empty) + StringFormatterMessageFactory.INSTANCE.newMessage(message.toString, Array.empty[AnyRef]) }) } } diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleOut.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleOut.scala index 0f6a089bf..90c8654ee 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleOut.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleOut.scala @@ -51,14 +51,14 @@ object ConsoleOut { private[this] final val OverwriteLine = "\u001B[A\r\u001B[2K" /** - * ConsoleOut instance that is backed by System.out. It overwrites the previously printed line - * if the function `f(lineToWrite, previousLine)` returns true. + * ConsoleOut instance that is backed by System.out. It overwrites the previously printed line if + * the function `f(lineToWrite, previousLine)` returns true. * * The ConsoleOut returned by this method assumes that the only newlines are from println calls * and not in the String arguments. */ def systemOutOverwrite(f: (String, String) => Boolean): ConsoleOut = new ConsoleOut { - val lockObject = System.out + val lockObject: PrintStream = System.out private[this] var last: Option[String] = None private[this] var current = new java.lang.StringBuffer def print(s: String): Unit = synchronized { current.append(s); () } diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/EscHelpers.scala b/internal/util-logging/src/main/scala/sbt/internal/util/EscHelpers.scala index ee84680c6..3a43d1f4e 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/EscHelpers.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/EscHelpers.scala @@ -16,8 +16,8 @@ object EscHelpers { final val ESC = '\u001B' /** - * An escape terminator is a character in the range `@` (decimal value 64) to `~` (decimal value 126). - * It is the final character in an escape sequence. + * An escape terminator is a character in the range `@` (decimal value 64) to `~` (decimal value + * 126). It is the final character in an escape sequence. * * cf. http://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes */ @@ -29,10 +29,11 @@ object EscHelpers { * * see: http://en.wikipedia.org/wiki/ANSI_escape_code * - * The CSI (control sequence instruction) codes start with ESC + '['. This is for testing the second character. + * The CSI (control sequence instruction) codes start with ESC + '['. This is for testing the + * second character. * - * There is an additional CSI (one character) that we could test for, but is not frequnetly used, and we don't - * check for it. + * There is an additional CSI (one character) that we could test for, but is not frequnetly used, + * and we don't check for it. * * cf. http://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes */ @@ -55,13 +56,13 @@ object EscHelpers { s.indexOf(ESC) >= 0 /** - * Returns the string `s` with escape sequences removed. - * An escape sequence starts with the ESC character (decimal value 27) and ends with an escape terminator. - * @see isEscapeTerminator + * Returns the string `s` with escape sequences removed. An escape sequence starts with the ESC + * character (decimal value 27) and ends with an escape terminator. + * @see + * isEscapeTerminator */ def removeEscapeSequences(s: String): String = - if (s.isEmpty || !hasEscapeSequence(s)) - s + if (s.isEmpty || !hasEscapeSequence(s)) s else { val sb = new java.lang.StringBuilder nextESC(s, 0, sb) @@ -130,12 +131,15 @@ object EscHelpers { /** * Strips ansi escape and color codes from an input string. * - * @param bytes the input bytes - * @param stripAnsi toggles whether or not to remove general ansi escape codes - * @param stripColor toggles whether or not to remove ansi color codes - * @return a string with the escape and color codes removed depending on the input - * parameter along with the length of the output string (which may be smaller than - * the returned array) + * @param bytes + * the input bytes + * @param stripAnsi + * toggles whether or not to remove general ansi escape codes + * @param stripColor + * toggles whether or not to remove ansi color codes + * @return + * a string with the escape and color codes removed depending on the input parameter along with + * the length of the output string (which may be smaller than the returned array) */ def strip(bytes: Array[Byte], stripAnsi: Boolean, stripColor: Boolean): (Array[Byte], Int) = { val res = Array.fill[Byte](bytes.length)(0) @@ -186,15 +190,17 @@ object EscHelpers { } /** - * Removes the ansi escape sequences from a string and makes a best attempt at - * calculating any ansi moves by hand. For example, if the string contains - * a backspace character followed by a character, the output string would - * replace the character preceding the backspaces with the character proceding it. - * This is in contrast to `strip` which just removes all ansi codes entirely. + * Removes the ansi escape sequences from a string and makes a best attempt at calculating any + * ansi moves by hand. For example, if the string contains a backspace character followed by a + * character, the output string would replace the character preceding the backspaces with the + * character proceding it. This is in contrast to `strip` which just removes all ansi codes + * entirely. * - * @param s the input string - * @return a string containing the original characters of the input stream with - * the ansi escape codes removed. + * @param s + * the input string + * @return + * a string containing the original characters of the input stream with the ansi escape codes + * removed. */ def stripColorsAndMoves(s: String): String = { val bytes = s.getBytes @@ -239,7 +245,10 @@ object EscHelpers { new String(res, 0, limit) } - /** Skips the escape sequence starting at `i-1`. `i` should be positioned at the character after the ESC that starts the sequence. */ + /** + * Skips the escape sequence starting at `i-1`. `i` should be positioned at the character after + * the ESC that starts the sequence. + */ private[this] def skipESC(s: String, i: Int): Int = { if (i >= s.length) { i diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/FilterLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/FilterLogger.scala index 57cad95a9..c539823d7 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/FilterLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/FilterLogger.scala @@ -11,8 +11,9 @@ import sbt.util._ import scala.annotation.nowarn /** - * A filter logger is used to delegate messages but not the logging level to another logger. This means - * that messages are logged at the higher of the two levels set by this logger and its delegate. + * A filter logger is used to delegate messages but not the logging level to another logger. This + * means that messages are logged at the higher of the two levels set by this logger and its + * delegate. */ class FilterLogger(delegate: AbstractLogger) extends BasicLogger { @nowarn override lazy val ansiCodesSupported = delegate.ansiCodesSupported diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/GlobalLogging.scala b/internal/util-logging/src/main/scala/sbt/internal/util/GlobalLogging.scala index 00c0a67c0..9576428b2 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/GlobalLogging.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/GlobalLogging.scala @@ -13,11 +13,11 @@ import java.io.{ File, PrintWriter } /** * Provides the current global logging configuration. * - * `full` is the current global logger. It should not be set directly because it is generated as needed from `backing.newLogger`. - * `console` is where all logging from all ConsoleLoggers should go. - * `backed` is the Logger that other loggers should feed into. - * `backing` tracks the files that persist the global logging. - * `newLogger` creates a new global logging configuration from a sink and backing configuration. + * `full` is the current global logger. It should not be set directly because it is generated as + * needed from `backing.newLogger`. `console` is where all logging from all ConsoleLoggers should + * go. `backed` is the Logger that other loggers should feed into. `backing` tracks the files that + * persist the global logging. `newLogger` creates a new global logging configuration from a sink + * and backing configuration. */ final case class GlobalLogging( full: ManagedLogger, @@ -36,21 +36,24 @@ final case class GlobalLogging1( ) /** - * Tracks the files that persist the global logging. - * `file` is the current backing file. `last` is the previous backing file, if there is one. - * `newBackingFile` creates a new temporary location for the next backing file. + * Tracks the files that persist the global logging. `file` is the current backing file. `last` is + * the previous backing file, if there is one. `newBackingFile` creates a new temporary location for + * the next backing file. */ final case class GlobalLogBacking(file: File, last: Option[File], newBackingFile: () => File) { /** Shifts the current backing file to `last` and sets the current backing to `newFile`. */ def shift(newFile: File) = GlobalLogBacking(newFile, Some(file), newBackingFile) - /** Shifts the current backing file to `last` and sets the current backing to a new temporary file generated by `newBackingFile`. */ + /** + * Shifts the current backing file to `last` and sets the current backing to a new temporary file + * generated by `newBackingFile`. + */ def shiftNew() = shift(newBackingFile()) /** - * If there is a previous backing file in `last`, that becomes the current backing file and the previous backing is cleared. - * Otherwise, no changes are made. + * If there is a previous backing file in `last`, that becomes the current backing file and the + * previous backing is cleared. Otherwise, no changes are made. */ def unshift = GlobalLogBacking(last getOrElse file, None, newBackingFile) @@ -58,7 +61,7 @@ final case class GlobalLogBacking(file: File, last: Option[File], newBackingFile object GlobalLogBacking { def apply(newBackingFile: => File): GlobalLogBacking = - GlobalLogBacking(newBackingFile, None, newBackingFile _) + GlobalLogBacking(newBackingFile, None, () => newBackingFile) } object GlobalLogging { diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/JLine3.scala b/internal/util-logging/src/main/scala/sbt/internal/util/JLine3.scala index a4811a2cc..64be598eb 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/JLine3.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/JLine3.scala @@ -81,7 +81,7 @@ private[sbt] object JLine3 { val bytes = new Array[Byte](4) var i = 0 var res = -2 - do { + while (i < 4 && res == -2) { inputStream.read() match { case -1 => res = -1 case byte => @@ -94,8 +94,7 @@ private[sbt] object JLine3 { if (it.hasNext) res = it.next } catch { case _: CharacterCodingException => } } - - } while (i < 4 && res == -2) + } res } private[this] def wrapTerminal(term: Terminal): JTerminal = { @@ -210,7 +209,9 @@ private[sbt] object JLine3 { term.getBooleanCapability(cap.toString) def getAttributes(): Attributes = attributesFromMap(term.getAttributes) def getSize(): Size = new Size(term.getWidth, term.getHeight) - def setAttributes(a: Attributes): Unit = {} // don't allow the jline line reader to change attributes + def setAttributes( + a: Attributes + ): Unit = {} // don't allow the jline line reader to change attributes def setSize(size: Size): Unit = term.setSize(size.getColumns, size.getRows) override def enterRawMode(): Attributes = { diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/LoggerWriter.scala b/internal/util-logging/src/main/scala/sbt/internal/util/LoggerWriter.scala index 8c8fe34b7..e412fe879 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/LoggerWriter.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/LoggerWriter.scala @@ -10,8 +10,8 @@ package sbt.internal.util import sbt.util._ /** - * Provides a `java.io.Writer` interface to a `Logger`. Content is line-buffered and logged at `level`. - * A line is delimited by `nl`, which is by default the platform line separator. + * Provides a `java.io.Writer` interface to a `Logger`. Content is line-buffered and logged at + * `level`. A line is delimited by `nl`, which is by default the platform line separator. */ class LoggerWriter( delegate: Logger, diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala index 3f5f38489..fd611e655 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala @@ -11,6 +11,7 @@ import sbt.internal.util.codec.JsonProtocol._ import sbt.util._ import scala.reflect.runtime.universe.TypeTag import sjsonnew.JsonFormat +import sbt.internal.util.appmacro.StringTypeTag private[sbt] trait MiniLogger { def log[T](level: Level.Value, message: ObjectEvent[T]): Unit @@ -45,7 +46,7 @@ class ManagedLogger( if (terminal.fold(true)(_.isSuccessEnabled)) { infoEvent[SuccessEvent](SuccessEvent(message))( implicitly[JsonFormat[SuccessEvent]], - StringTypeTag.fast[SuccessEvent], + StringTypeTag[SuccessEvent], ) } } @@ -54,30 +55,14 @@ class ManagedLogger( LogExchange.registerStringCodec[A] } - @deprecated("Use macro-powered StringTypeTag.fast instead", "1.4.0") - final def debugEvent[A](event: => A, f: JsonFormat[A], t: TypeTag[A]): Unit = - debugEvent(event)(f, StringTypeTag.apply(t)) - @deprecated("Use macro-powered StringTypeTag.fast instead", "1.4.0") - final def infoEvent[A](event: => A, f: JsonFormat[A], t: TypeTag[A]): Unit = - infoEvent(event)(f, StringTypeTag.apply(t)) - @deprecated("Use macro-powered StringTypeTag.fast instead", "1.4.0") - final def warnEvent[A](event: => A, f: JsonFormat[A], t: TypeTag[A]): Unit = - warnEvent(event)(f, StringTypeTag.apply(t)) - @deprecated("Use macro-powered StringTypeTag.fast instead", "1.4.0") - final def errorEvent[A](event: => A, f: JsonFormat[A], t: TypeTag[A]): Unit = - errorEvent(event)(f, StringTypeTag.apply(t)) - final def debugEvent[A: JsonFormat: StringTypeTag](event: => A): Unit = logEvent(Level.Debug, event) final def infoEvent[A: JsonFormat: StringTypeTag](event: => A): Unit = logEvent(Level.Info, event) final def warnEvent[A: JsonFormat: StringTypeTag](event: => A): Unit = logEvent(Level.Warn, event) final def errorEvent[A: JsonFormat: StringTypeTag](event: => A): Unit = logEvent(Level.Error, event) - @deprecated("Use macro-powered StringTypeTag.fast instead", "1.4.0") - def logEvent[A](level: Level.Value, event: => A, f: JsonFormat[A], t: TypeTag[A]): Unit = - logEvent(level, event)(f, StringTypeTag.apply(t)) - def logEvent[A: JsonFormat](level: Level.Value, event: => A)( - implicit tag: StringTypeTag[A] + def logEvent[A: JsonFormat](level: Level.Value, event: => A)(implicit + tag: StringTypeTag[A] ): Unit = { val v: A = event // println("logEvent " + tag.key) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ProgressState.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ProgressState.scala index 817363f8d..1f4ea2e13 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ProgressState.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ProgressState.scala @@ -159,11 +159,10 @@ private[sbt] object ProgressState { private val SERVER_IS_RUNNING_LENGTH = SERVER_IS_RUNNING.length + 3 /** - * Receives a new task report and replaces the old one. In the event that the new - * report has fewer lines than the previous report, padding lines are added on top - * so that the console log lines remain contiguous. When a console line is printed - * at the info or greater level, we can decrement the padding because the console - * line will have filled in the blank line. + * Receives a new task report and replaces the old one. In the event that the new report has fewer + * lines than the previous report, padding lines are added on top so that the console log lines + * remain contiguous. When a console line is printed at the info or greater level, we can + * decrement the padding because the console line will have filled in the blank line. */ private[sbt] def updateProgressState( pe: ProgressEvent, diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala b/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala index f98c2d9ce..f8cfec7f1 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala @@ -14,19 +14,17 @@ object StackTrace { def isSbtClass(name: String) = name.startsWith("sbt.") || name.startsWith("xsbt.") /** - * Return a printable representation of the stack trace associated - * with t. Information about t and its Throwable causes is included. - * The number of lines to be included for each Throwable is configured - * via d which should be greater than or equal to 0. + * Return a printable representation of the stack trace associated with t. Information about t and + * its Throwable causes is included. The number of lines to be included for each Throwable is + * configured via d which should be greater than or equal to 0. * - * - If d is 0, then all elements are included up to (but not including) - * the first element that comes from sbt. - * - If d is greater than 0, then up to that many lines are included, - * where the line for the Throwable is counted plus one line for each stack element. - * Less lines will be included if there are not enough stack elements. + * - If d is 0, then all elements are included up to (but not including) the first element that + * comes from sbt. + * - If d is greater than 0, then up to that many lines are included, where the line for the + * Throwable is counted plus one line for each stack element. Less lines will be included if + * there are not enough stack elements. * - * See also ConsoleAppender where d <= 2 is treated specially by - * printing a prepared statement. + * See also ConsoleAppender where d <= 2 is treated specially by printing a prepared statement. */ def trimmedLines(t: Throwable, d: Int): List[String] = { require(d >= 0) @@ -35,8 +33,7 @@ object StackTrace { def appendStackTrace(t: Throwable, first: Boolean): Unit = { val include: StackTraceElement => Boolean = - if (d == 0) - element => !isSbtClass(element.getClassName) + if (d == 0) element => !isSbtClass(element.getClassName) else { var count = d - 1 (_ => { count -= 1; count >= 0 }) @@ -69,16 +66,15 @@ object StackTrace { } /** - * Return a printable representation of the stack trace associated - * with t. Information about t and its Throwable causes is included. - * The number of lines to be included for each Throwable is configured - * via d which should be greater than or equal to 0. + * Return a printable representation of the stack trace associated with t. Information about t and + * its Throwable causes is included. The number of lines to be included for each Throwable is + * configured via d which should be greater than or equal to 0. * - * - If d is 0, then all elements are included up to (but not including) - * the first element that comes from sbt. - * - If d is greater than 0, then up to that many lines are included, - * where the line for the Throwable is counted plus one line for each stack element. - * Less lines will be included if there are not enough stack elements. + * - If d is 0, then all elements are included up to (but not including) the first element that + * comes from sbt. + * - If d is greater than 0, then up to that many lines are included, where the line for the + * Throwable is counted plus one line for each stack element. Less lines will be included if + * there are not enough stack elements. */ def trimmed(t: Throwable, d: Int): String = trimmedLines(t, d).mkString(IO.Newline) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala index 27b1e29c4..22d93698d 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala @@ -26,7 +26,8 @@ trait Terminal extends AutoCloseable { * config which is updated if it has been more than a second since the last update. It is thus * possible for this value to be stale. * - * @return the terminal width. + * @return + * the terminal width. */ def getWidth: Int @@ -35,78 +36,88 @@ trait Terminal extends AutoCloseable { * config which is updated if it has been more than a second since the last update. It is thus * possible for this value to be stale. * - * @return the terminal height. + * @return + * the terminal height. */ def getHeight: Int /** - * Returns the height and width of the current line that is displayed on the terminal. If the - * most recently flushed byte is a newline, this will be `(0, 0)`. + * Returns the height and width of the current line that is displayed on the terminal. If the most + * recently flushed byte is a newline, this will be `(0, 0)`. * - * @return the (height, width) pair + * @return + * the (height, width) pair */ def getLineHeightAndWidth(line: String): (Int, Int) /** * Gets the input stream for this Terminal. This could be a wrapper around System.in for the * process or it could be a remote input stream for a network channel. - * @return the input stream. + * @return + * the input stream. */ def inputStream: InputStream /** * Gets the output stream for this Terminal. - * @return the output stream. + * @return + * the output stream. */ def outputStream: OutputStream /** * Gets the error stream for this Terminal. - * @return the error stream. + * @return + * the error stream. */ def errorStream: OutputStream /** * Returns true if the terminal supports ansi characters. * - * @return true if the terminal supports ansi escape codes. + * @return + * true if the terminal supports ansi escape codes. */ def isAnsiSupported: Boolean /** * Returns true if color is enabled for this terminal. * - * @return true if color is enabled for this terminal. + * @return + * true if color is enabled for this terminal. */ def isColorEnabled: Boolean /** * Returns true if the terminal has echo enabled. * - * @return true if the terminal has echo enabled. + * @return + * true if the terminal has echo enabled. */ def isEchoEnabled: Boolean /** - * Returns true if the terminal has success enabled, which it may not if it is for batch - * commands because the client will print the success results when received from the - * server. + * Returns true if the terminal has success enabled, which it may not if it is for batch commands + * because the client will print the success results when received from the server. * - * @return true if the terminal has success enabled + * @return + * true if the terminal has success enabled */ def isSuccessEnabled: Boolean /** * Returns true if the terminal has supershell enabled. * - * @return true if the terminal has supershell enabled. + * @return + * true if the terminal has supershell enabled. */ def isSupershellEnabled: Boolean /** * Toggles whether or not the terminal should echo characters back to stdout * - * @return the previous value of the toggle + * @return + * the previous value of the toggle */ def setEchoEnabled(toggle: Boolean): Unit @@ -118,17 +129,19 @@ trait Terminal extends AutoCloseable { /** * Returns the last line written to the terminal's output stream. - * @return the last line + * @return + * the last line */ private[sbt] def getLastLine: Option[String] /** - * Returns the buffered lines that have been written to the terminal. The - * main use case is to display the system startup log lines when a client - * connects to a booting server. This could also be used to implement a more - * tmux like experience where multiple clients connect to the same console. + * Returns the buffered lines that have been written to the terminal. The main use case is to + * display the system startup log lines when a client connects to a booting server. This could + * also be used to implement a more tmux like experience where multiple clients connect to the + * same console. * - * @return the lines + * @return + * the lines */ private[sbt] def getLines: Seq[String] @@ -143,7 +156,8 @@ trait Terminal extends AutoCloseable { private[sbt] final def withRawInput[T](f: => T): T = { enterRawMode() try f - catch { case e: InterruptedIOException => throw new InterruptedException } finally exitRawMode() + catch { case e: InterruptedIOException => throw new InterruptedException } + finally exitRawMode() } private[sbt] def enterRawMode(): Unit private[sbt] def exitRawMode(): Unit @@ -162,8 +176,10 @@ trait Terminal extends AutoCloseable { * Returns the number of lines that the input string will cover given the current width of the * terminal. * - * @param line the input line - * @return the number of lines that the line will cover on the terminal + * @param line + * the input line + * @return + * the number of lines that the line will cover on the terminal */ private[sbt] def lineCount(line: String): Int = { val lines = EscHelpers.stripColorsAndMoves(line).split('\n') @@ -249,11 +265,12 @@ object Terminal { } /** - * Returns true if System.in is attached. When sbt is run as a subprocess, like in scripted or - * as a server, System.in will not be attached and this method will return false. Otherwise - * it will return true. + * Returns true if System.in is attached. When sbt is run as a subprocess, like in scripted or as + * a server, System.in will not be attached and this method will return false. Otherwise it will + * return true. * - * @return true if System.in is attached. + * @return + * true if System.in is attached. */ def systemInIsAttached: Boolean = attached.get @@ -264,7 +281,8 @@ object Terminal { /** * Returns an InputStream that will throw a [[ClosedChannelException]] if read returns -1. - * @return the wrapped InputStream. + * @return + * the wrapped InputStream. */ private[sbt] def throwOnClosedSystemIn(in: InputStream): InputStream = new InputStream { override def available(): Int = in.available() @@ -276,11 +294,12 @@ object Terminal { } /** - * Provides a wrapper around System.in. The wrapped stream in will check if the terminal is attached - * in available and read. If a read returns -1, it will mark System.in as unattached so that - * it can be detected by [[systemInIsAttached]]. + * Provides a wrapper around System.in. The wrapped stream in will check if the terminal is + * attached in available and read. If a read returns -1, it will mark System.in as unattached so + * that it can be detected by [[systemInIsAttached]]. * - * @return the wrapped InputStream + * @return + * the wrapped InputStream */ private[sbt] def wrappedSystemIn: InputStream = WrappedSystemIn @@ -303,10 +322,9 @@ object Terminal { /** * Indicates whether formatting has been disabled in environment variables. - * 1. -Dsbt.log.noformat=true means no formatting. - * 2. -Dsbt.color=always/auto/never/true/false - * 3. -Dsbt.colour=always/auto/never/true/false - * 4. -Dsbt.log.format=always/auto/never/true/false + * 1. -Dsbt.log.noformat=true means no formatting. 2. -Dsbt.color=always/auto/never/true/false + * 3. -Dsbt.colour=always/auto/never/true/false 4. + * -Dsbt.log.format=always/auto/never/true/false */ private[this] lazy val logFormatEnabled: Option[Boolean] = { sys.props.get("sbt.log.noformat") match { @@ -342,11 +360,14 @@ object Terminal { private[sbt] def canPollSystemIn: Boolean = hasConsole && !isDumbTerminal && hasVirtualIO /** - * - * @param isServer toggles whether or not this is a server of client process - * @param f the thunk to run - * @tparam T the result type of the thunk - * @return the result of the thunk + * @param isServer + * toggles whether or not this is a server of client process + * @param f + * the thunk to run + * @tparam T + * the result type of the thunk + * @return + * the result of the thunk */ private[sbt] def withStreams[T](isServer: Boolean, isSubProcess: Boolean)(f: => T): T = { // In ci environments, don't touch the io streams unless run with -Dsbt.io.virtual=true @@ -584,34 +605,33 @@ object Terminal { /** * A wrapped instance of a jline.Terminal2 instance. It should only ever be changed when the * backgrounds sbt with ctrl+z and then foregrounds sbt which causes a call to reset. The - * Terminal.console method returns this terminal and the ConsoleChannel delegates its - * terminal method to it. + * Terminal.console method returns this terminal and the ConsoleChannel delegates its terminal + * method to it. */ private[this] val consoleTerminalHolder: AtomicReference[Terminal] = new AtomicReference(SimpleTerminal) /** - * The terminal that is currently being used by the proxyInputStream and proxyOutputStream. - * It is set through the Terminal.set method which is called by the SetTerminal command, which - * is used to change the terminal during task evaluation. This allows us to route System.in and - * System.out through the terminal's input and output streams. + * The terminal that is currently being used by the proxyInputStream and proxyOutputStream. It is + * set through the Terminal.set method which is called by the SetTerminal command, which is used + * to change the terminal during task evaluation. This allows us to route System.in and System.out + * through the terminal's input and output streams. */ private[this] val activeTerminal = new AtomicReference[Terminal](consoleTerminalHolder.get) /** - * The boot input stream allows a remote client to forward input to the sbt process while - * it is still loading. It works by updating proxyInputStream to read from the - * value of bootInputStreamHolder if it is non-null as well as from the normal process - * console io (assuming there is console io). + * The boot input stream allows a remote client to forward input to the sbt process while it is + * still loading. It works by updating proxyInputStream to read from the value of + * bootInputStreamHolder if it is non-null as well as from the normal process console io (assuming + * there is console io). */ private[this] val bootInputStreamHolder = new AtomicReference[InputStream] /** - * The boot output stream allows sbt to relay the bytes written to stdout to one or - * more remote clients while the sbt build is loading and hasn't yet loaded a server. - * The output stream of TerminalConsole is updated to write to value of - * bootOutputStreamHolder when it is non-null as well as the normal process console - * output stream. + * The boot output stream allows sbt to relay the bytes written to stdout to one or more remote + * clients while the sbt build is loading and hasn't yet loaded a server. The output stream of + * TerminalConsole is updated to write to value of bootOutputStreamHolder when it is non-null as + * well as the normal process console output stream. */ private[this] val bootOutputStreamHolder = new AtomicReference[OutputStream] private[sbt] def setBootStreams( @@ -912,7 +932,7 @@ object Terminal { val out: OutputStream, override val errorStream: OutputStream, override private[sbt] val name: String - ) extends Terminal { + ) extends Terminal { self => private[sbt] def getSizeImpl: (Int, Int) private[this] val sizeRefreshPeriod = 1.second private[this] val size = @@ -951,7 +971,7 @@ object Terminal { override val outputStream = new OutputStream { override def write(b: Int): Unit = throwIfClosed { - write(Array((b & 0xFF).toByte)) + write(Array((b & 0xff).toByte)) } override def write(b: Array[Byte]): Unit = throwIfClosed { withWriteLock(doWrite(b)) @@ -964,8 +984,12 @@ object Terminal { private def doWrite(rawBytes: Array[Byte]): Unit = withPrintStream { ps => val (toWrite, len) = if (rawBytes.contains(27.toByte)) { - if (!isAnsiSupported || !isColorEnabled) - EscHelpers.strip(rawBytes, stripAnsi = !isAnsiSupported, stripColor = !isColorEnabled) + if (!Terminal.isAnsiSupported || !Terminal.isColorEnabled) + EscHelpers.strip( + rawBytes, + stripAnsi = !Terminal.isAnsiSupported, + stripColor = !Terminal.isColorEnabled + ) else (rawBytes, rawBytes.length) } else (rawBytes, rawBytes.length) val bytes = if (len < toWrite.length) toWrite.take(len) else toWrite @@ -999,7 +1023,7 @@ object Terminal { } } private lazy val nullInputStream: InputStream = () => { - try this.synchronized(this.wait) + try this.synchronized(this.wait()) catch { case _: InterruptedException => } -1 } diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/WindowsInputStream.scala b/internal/util-logging/src/main/scala/sbt/internal/util/WindowsInputStream.scala index 830dbc2d2..26828b98c 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/WindowsInputStream.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/WindowsInputStream.scala @@ -75,8 +75,10 @@ private[util] class WindowsInputStream(term: org.jline.terminal.Terminal, in: In val isShift = (controlKeyState & SHIFT_PRESSED) > 0; if (keyEvent.keyDown) { if (keyEvent.uchar > 0) { - if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z')) - && isAlt && !isCtrl) { + if ( + ((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z')) + && isAlt && !isCtrl + ) { sb.append('\u001B') // ESC } if (isShift && keyEvent.keyCode == 9) { @@ -108,15 +110,15 @@ private[util] class WindowsInputStream(term: org.jline.terminal.Terminal, in: In case 0x77 /* VK_F8 */ => getCapability(Capability.key_f8) case 0x78 /* VK_F9 */ => getCapability(Capability.key_f9) case 0x79 /* VK_F10 */ => getCapability(Capability.key_f10) - case 0x7A /* VK_F11 */ => getCapability(Capability.key_f11) - case 0x7B /* VK_F12 */ => getCapability(Capability.key_f12) + case 0x7a /* VK_F11 */ => getCapability(Capability.key_f11) + case 0x7b /* VK_F12 */ => getCapability(Capability.key_f12) // VK_END, VK_INSERT and VK_DELETE are not in the ansi key bindings so we // have to manually apply the the sequences here and in JLine3.wrap case 0x23 /* VK_END */ => Option(getCapability(Capability.key_end)).getOrElse("\u001B[4~") - case 0x2D /* VK_INSERT */ => + case 0x2d /* VK_INSERT */ => Option(getCapability(Capability.key_ic)).getOrElse("\u001B[2~") - case 0x2E /* VK_DELETE */ => + case 0x2e /* VK_DELETE */ => Option(getCapability(Capability.key_dc)).getOrElse("\u001B[3~") case _ => null } @@ -142,7 +144,7 @@ private[util] class WindowsInputStream(term: org.jline.terminal.Terminal, in: In override def read(): Int = { buffer.poll match { case null => - readConsoleInput().foreach(b => buffer.put(b & 0xFF)) + readConsoleInput().foreach(b => buffer.put(b & 0xff)) if (!Thread.interrupted) read() else throw new InterruptedException case b => b } diff --git a/internal/util-logging/src/main/scala/sbt/util/Level.scala b/internal/util-logging/src/main/scala/sbt/util/Level.scala index b9d30dca7..6749798a6 100644 --- a/internal/util-logging/src/main/scala/sbt/util/Level.scala +++ b/internal/util-logging/src/main/scala/sbt/util/Level.scala @@ -8,8 +8,8 @@ package sbt.util /** - * An enumeration defining the levels available for logging. A level includes all of the levels - * with id larger than its own id. For example, Warn (id=3) includes Error (id=4). + * An enumeration defining the levels available for logging. A level includes all of the levels with + * id larger than its own id. For example, Warn (id=3) includes Error (id=4). */ object Level extends Enumeration { val Debug = Value(1, "debug") @@ -18,15 +18,18 @@ object Level extends Enumeration { val Error = Value(4, "error") /** - * Defines the label to use for success messages. - * Because the label for levels is defined in this module, the success label is also defined here. + * Defines the label to use for success messages. Because the label for levels is defined in this + * module, the success label is also defined here. */ val SuccessLabel = "success" def union(a: Value, b: Value) = if (a.id < b.id) a else b def unionAll(vs: Seq[Value]) = vs reduceLeft union - /** Returns the level with the given name wrapped in Some, or None if no level exists for that name. */ + /** + * Returns the level with the given name wrapped in Some, or None if no level exists for that + * name. + */ def apply(s: String) = values.find(s == _.toString) /** Same as apply, defined for use in pattern matching. */ diff --git a/internal/util-logging/src/main/scala/sbt/util/LogExchange.scala b/internal/util-logging/src/main/scala/sbt/util/LogExchange.scala index 229c12fde..507b7674a 100644 --- a/internal/util-logging/src/main/scala/sbt/util/LogExchange.scala +++ b/internal/util-logging/src/main/scala/sbt/util/LogExchange.scala @@ -11,7 +11,8 @@ import org.apache.logging.log4j.core.config.LoggerConfig import org.apache.logging.log4j.core.layout.PatternLayout import org.apache.logging.log4j.core.{ LoggerContext => XLoggerContext } import org.apache.logging.log4j.{ LogManager => XLogManager } -import sbt.internal.util._ +import sbt.internal.util.{ Appender, ManagedLogger, TraceEvent, SuccessEvent, Util } +import sbt.internal.util.appmacro.StringTypeTag import java.util.concurrent.ConcurrentHashMap import scala.collection.concurrent @@ -34,6 +35,7 @@ sealed abstract class LogExchange { def unbindLoggerAppenders(loggerName: String): Unit = { LoggerContext.globalContext.clearAppenders(loggerName) } + def bindLoggerAppenders( loggerName: String, appenders: Seq[(Appender, Level.Value)] @@ -45,9 +47,11 @@ sealed abstract class LogExchange { // Construct these StringTypeTags manually, because they're used at the very startup of sbt // and we'll try not to initialize the universe by using the StringTypeTag.apply that requires a TypeTag // A better long-term solution could be to make StringTypeTag.apply a macro. - lazy val stringTypeTagThrowable = StringTypeTag[Throwable]("scala.Throwable") - lazy val stringTypeTagTraceEvent = StringTypeTag[TraceEvent]("sbt.internal.util.TraceEvent") - lazy val stringTypeTagSuccessEvent = StringTypeTag[SuccessEvent]("sbt.internal.util.SuccessEvent") + lazy val stringTypeTagThrowable = StringTypeTag.manually[Throwable]("java.lang.Throwable") + lazy val stringTypeTagTraceEvent = + StringTypeTag.manually[TraceEvent]("sbt.internal.util.TraceEvent") + lazy val stringTypeTagSuccessEvent = + StringTypeTag.manually[SuccessEvent]("sbt.internal.util.SuccessEvent") private[sbt] def initStringCodecs(): Unit = { import sbt.internal.util.codec.SuccessEventShowLines._ diff --git a/internal/util-logging/src/main/scala/sbt/util/Logger.scala b/internal/util-logging/src/main/scala/sbt/util/Logger.scala index 135c92da4..7f2ff157d 100644 --- a/internal/util-logging/src/main/scala/sbt/util/Logger.scala +++ b/internal/util-logging/src/main/scala/sbt/util/Logger.scala @@ -17,8 +17,8 @@ import java.util.Optional import java.util.function.Supplier /** - * This is intended to be the simplest logging interface for use by code that wants to log. - * It does not include configuring the logger. + * This is intended to be the simplest logging interface for use by code that wants to log. It does + * not include configuring the logger. */ abstract class Logger extends xLogger { final def verbose(message: => String): Unit = debug(message) diff --git a/internal/util-logging/src/main/scala/sbt/util/LoggerContext.scala b/internal/util-logging/src/main/scala/sbt/util/LoggerContext.scala index 719b9b2ff..0005b4c18 100644 --- a/internal/util-logging/src/main/scala/sbt/util/LoggerContext.scala +++ b/internal/util-logging/src/main/scala/sbt/util/LoggerContext.scala @@ -14,11 +14,11 @@ import java.util.concurrent.atomic.AtomicBoolean import scala.collection.JavaConverters._ /** - * Provides a context for generating loggers during task evaluation. The logger context - * can be initialized for a single command evaluation run and all of the resources - * created (such as cached logger appenders) can be cleaned up after task evaluation. - * This trait evolved out of LogExchange when it became clear that it was very difficult - * to manage the loggers and appenders without introducing memory leaks. + * Provides a context for generating loggers during task evaluation. The logger context can be + * initialized for a single command evaluation run and all of the resources created (such as cached + * logger appenders) can be cleaned up after task evaluation. This trait evolved out of LogExchange + * when it became clear that it was very difficult to manage the loggers and appenders without + * introducing memory leaks. */ sealed trait LoggerContext extends AutoCloseable { def logger(name: String, channelName: Option[String], execId: Option[String]): ManagedLogger @@ -45,9 +45,8 @@ object LoggerContext { } } def log[T](level: Level.Value, message: ObjectEvent[T]): Unit = { - consoleAppenders.forEach { - case (a, l) => - if (level.compare(l) >= 0) a.appendObjectEvent(level, message) + consoleAppenders.forEach { case (a, l) => + if (level.compare(l) >= 0) a.appendObjectEvent(level, message) } } def addAppender(newAppender: (Appender, Level.Value)): Unit = diff --git a/internal/util-logging/src/test/scala/LogExchangeSpec.scala b/internal/util-logging/src/test/scala/LogExchangeSpec.scala index 7e3e44131..57dfbe03c 100644 --- a/internal/util-logging/src/test/scala/LogExchangeSpec.scala +++ b/internal/util-logging/src/test/scala/LogExchangeSpec.scala @@ -8,29 +8,30 @@ package sbt.util import sbt.internal.util._ - +import sbt.internal.util.appmacro.StringTypeTag import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class LogExchangeSpec extends AnyFlatSpec with Matchers { import LogExchange._ - checkTypeTag("stringTypeTagThrowable", stringTypeTagThrowable, StringTypeTag.fast[Throwable]) + checkTypeTag("stringTypeTagThrowable", stringTypeTagThrowable, StringTypeTag[Throwable]) + checkTypeTag( "stringTypeTagTraceEvent", stringTypeTagTraceEvent, - StringTypeTag.fast[TraceEvent] + StringTypeTag[TraceEvent] ) checkTypeTag( "stringTypeTagSuccessEvent", stringTypeTagSuccessEvent, - StringTypeTag.fast[SuccessEvent] + StringTypeTag[SuccessEvent] ) private def checkTypeTag[A](name: String, inc: StringTypeTag[A], exp: StringTypeTag[A]): Unit = s"LogExchange.$name" should s"match real StringTypeTag[$exp]" in { - val StringTypeTag(incomingString) = inc - val StringTypeTag(expectedString) = exp + val incomingString = inc.key + val expectedString = exp.key if ((incomingString startsWith "scala.") || (expectedString startsWith "scala.")) { // > historically [Scala] has been inconsistent whether `scala.` is included, or not // > would it be hard to make the test accept either result? diff --git a/internal/util-logging/src/test/scala/LogWriterTest.scala b/internal/util-logging/src/test/scala/LogWriterTest.scala index 0fda82264..af87420dd 100644 --- a/internal/util-logging/src/test/scala/LogWriterTest.scala +++ b/internal/util-logging/src/test/scala/LogWriterTest.scala @@ -20,7 +20,7 @@ object LogWriterTest extends Properties("Log Writer") { final val MaxSegments = 10 /* Tests that content written through a LoggerWriter is properly passed to the underlying Logger. - * Each line, determined by the specified newline separator, must be logged at the correct logging level. */ + * Each line, determined by the specified newline separator, must be logged at the correct logging level. */ property("properly logged") = forAll { (output: Output, newLine: NewLine) => import output.{ lines, level } val log = new RecordingLogger @@ -32,8 +32,8 @@ object LogWriterTest extends Properties("Log Writer") { } /** - * Displays a LogEvent in a useful format for debugging. In particular, we are only interested in `Log` types - * and non-printable characters should be escaped + * Displays a LogEvent in a useful format for debugging. In particular, we are only interested in + * `Log` types and non-printable characters should be escaped */ def show(event: LogEvent): String = event match { @@ -42,9 +42,9 @@ object LogWriterTest extends Properties("Log Writer") { } /** - * Writes the given lines to the Writer. `lines` is taken to be a list of lines, which are - * represented as separately written segments (ToLog instances). ToLog.`byCharacter` - * indicates whether to write the segment by character (true) or all at once (false) + * Writes the given lines to the Writer. `lines` is taken to be a list of lines, which are + * represented as separately written segments (ToLog instances). ToLog.`byCharacter` indicates + * whether to write the segment by character (true) or all at once (false) */ def logLines(writer: Writer, lines: List[List[ToLog]], newLine: String): Unit = { for (line <- lines; section <- line) { @@ -58,11 +58,13 @@ object LogWriterTest extends Properties("Log Writer") { writer.flush() } - /** Converts the given lines in segments to lines as Strings for checking the results of the test.*/ + /** + * Converts the given lines in segments to lines as Strings for checking the results of the test. + */ def toLines(lines: List[List[ToLog]]): List[String] = lines.map(_.map(_.contentOnly).mkString) - /** Checks that the expected `lines` were recorded as `events` at level `Lvl`.*/ + /** Checks that the expected `lines` were recorded as `events` at level `Lvl`. */ def check(lines: List[String], events: List[LogEvent], Lvl: Level.Value): Boolean = (lines zip events) forall { case (line, log: Log) => log.level == Lvl && line == log.msg @@ -102,7 +104,10 @@ object LogWriterTest extends Properties("Log Writer") { def removeNewlines(s: String) = s.replaceAll("""[\n\r]+""", "") def addNewline(l: ToLog): ToLog = - new ToLog(l.content + "\n", l.byCharacter) // \n will be replaced by a random line terminator for all lines + new ToLog( + l.content + "\n", + l.byCharacter + ) // \n will be replaced by a random line terminator for all lines def listOf[T](max: Int)(implicit content: Arbitrary[T]): Gen[List[T]] = Gen.choose(0, max) flatMap (sz => listOfN(sz, content.arbitrary)) @@ -126,10 +131,10 @@ final class ToLog(val content: String, val byCharacter: Boolean) { if (content.isEmpty) "" else "ToLog('" + Escape(contentOnly) + "', " + byCharacter + ")" } -/** Defines some utility methods for escaping unprintable characters.*/ +/** Defines some utility methods for escaping unprintable characters. */ object Escape { - /** Escapes characters with code less than 20 by printing them as unicode escapes.*/ + /** Escapes characters with code less than 20 by printing them as unicode escapes. */ def apply(s: String): String = { val builder = new StringBuilder(s.length) for (c <- s) { @@ -145,13 +150,13 @@ object Escape { if (diff <= 0) s else List.fill(diff)(extra).mkString("", "", s) } - /** Replaces a \n character at the end of a string `s` with `nl`.*/ + /** Replaces a \n character at the end of a string `s` with `nl`. */ def newline(s: String, nl: String): String = if (s.endsWith("\n")) s.substring(0, s.length - 1) + nl else s } -/** Records logging events for later retrieval.*/ +/** Records logging events for later retrieval. */ final class RecordingLogger extends BasicLogger { private var events: List[LogEvent] = Nil diff --git a/internal/util-logging/src/test/scala/ManagedLoggerSpec.scala b/internal/util-logging/src/test/scala/ManagedLoggerSpec.scala index d19d61658..b995b8621 100644 --- a/internal/util-logging/src/test/scala/ManagedLoggerSpec.scala +++ b/internal/util-logging/src/test/scala/ManagedLoggerSpec.scala @@ -10,6 +10,7 @@ package sbt.internal.util import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import sbt.util._ +import sbt.internal.util.appmacro.StringTypeTag import java.io.{ File, PrintWriter } import sbt.io.Using import scala.annotation.nowarn @@ -17,8 +18,8 @@ import scala.annotation.nowarn class ManagedLoggerSpec extends AnyFlatSpec with Matchers { val context = LoggerContext() @nowarn - //TODO create a new appender for testing purposes - 3/12/21 - val asyncStdout = ConsoleAppender("asyncStdout") + // TODO create a new appender for testing purposes - 3/12/21 + val asyncStdout = ConsoleAppender() def newLogger(name: String): ManagedLogger = context.logger(name, None, None) "ManagedLogger" should "log to console" in { val log = newLogger("foo") @@ -91,7 +92,7 @@ class ManagedLoggerSpec extends AnyFlatSpec with Matchers { } { pool.submit(new Runnable { def run(): Unit = { - val stringTypeTag = StringTypeTag.fast[List[Int]] + val stringTypeTag = StringTypeTag[List[Int]] val log = newLogger(s"foo$i") context.addAppender(s"foo$i", asyncStdout -> Level.Info) if (i % 100 == 0) { diff --git a/internal/util-logging/src/test/scala/sbt/internal/util/UTF8DecoderSpec.scala b/internal/util-logging/src/test/scala/sbt/internal/util/UTF8DecoderSpec.scala index 06c2e711b..f99ba6d9a 100644 --- a/internal/util-logging/src/test/scala/sbt/internal/util/UTF8DecoderSpec.scala +++ b/internal/util-logging/src/test/scala/sbt/internal/util/UTF8DecoderSpec.scala @@ -32,7 +32,7 @@ class UTF8DecoderSpec extends AnyFlatSpec { "emoji" should "be handled" in { val bytes = new LinkedBlockingQueue[Int] // laughing and crying emoji in utf8 - Seq(0xF0, 0x9F, 0x98, 0x82).foreach(b => bytes.put(b)) + Seq(0xf0, 0x9f, 0x98, 0x82).foreach(b => bytes.put(b)) val inputStream = new InputStream { override def read(): Int = Option(bytes.poll).getOrElse(-1) } diff --git a/internal/util-scripted/src/main/scala/sbt/internal/scripted/FileCommands.scala b/internal/util-scripted/src/main/scala/sbt/internal/scripted/FileCommands.scala index fcc6707f5..eea382007 100644 --- a/internal/util-scripted/src/main/scala/sbt/internal/scripted/FileCommands.scala +++ b/internal/util-scripted/src/main/scala/sbt/internal/scripted/FileCommands.scala @@ -89,8 +89,7 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler { } def execute(command: List[String]): Unit = execute0(command.head, command.tail) def execute0(command: String, args: List[String]): Unit = { - if (command.trim.isEmpty) - scriptError("Command was empty.") + if (command.trim.isEmpty) scriptError("Command was empty.") else { val exitValue = sys.process.Process(command :: args, baseDirectory).! if (exitValue != 0) diff --git a/internal/util-scripted/src/main/scala/sbt/internal/scripted/ScriptedTests.scala b/internal/util-scripted/src/main/scala/sbt/internal/scripted/ScriptedTests.scala index 93672518d..e606ef411 100644 --- a/internal/util-scripted/src/main/scala/sbt/internal/scripted/ScriptedTests.scala +++ b/internal/util-scripted/src/main/scala/sbt/internal/scripted/ScriptedTests.scala @@ -217,8 +217,7 @@ final class ListTests(baseDirectory: File, accept: ScriptedTest => Boolean, log: } else { val (included, skipped) = allTests.toList.partition(test => accept(ScriptedTest(groupName, test.getName))) - if (included.isEmpty) - log.warn("Test group " + groupName + " skipped.") + if (included.isEmpty) log.warn("Test group " + groupName + " skipped.") else if (skipped.nonEmpty) { log.warn("Tests skipped in group " + group.getName + ":") skipped.foreach(testName => log.warn(" " + testName.getName)) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 33faf2df9..7a3d86473 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -82,15 +82,18 @@ object Dependencies { lazy val sjsonNewVersion = "0.9.1" def sjsonNew(n: String) = Def.setting( - if (scalaBinaryVersion.value == "3") "com.eed3si9n" % (n + "_2.13") % sjsonNewVersion - else "com.eed3si9n" %% n % "0.9.1" + if (scalaBinaryVersion.value == "3") + ("com.eed3si9n" % n % sjsonNewVersion).cross(CrossVersion.for3Use2_13) + else "com.eed3si9n" %% n % sjsonNewVersion ) // contrabandSjsonNewVersion.value val sjsonNewScalaJson = sjsonNew("sjson-new-scalajson") val sjsonNewMurmurhash = sjsonNew("sjson-new-murmurhash") + val sjsonNewCore = sjsonNew("sjson-new-core") // JLine 3 version must be coordinated together with JAnsi version // and the JLine 2 fork version, which uses the same JAnsi - val jline = "org.scala-sbt.jline" % "jline" % "2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493" + val jline = + "org.scala-sbt.jline" % "jline" % "2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493" val jline3Version = "3.19.0" val jline3Terminal = "org.jline" % "jline-terminal" % jline3Version val jline3Jansi = "org.jline" % "jline-terminal-jansi" % jline3Version diff --git a/protocol/src/main/scala/sbt/internal/bsp/SourceItemKind.scala b/protocol/src/main/scala/sbt/internal/bsp/SourceItemKind.scala index f9dd7e6b3..58f68655d 100644 --- a/protocol/src/main/scala/sbt/internal/bsp/SourceItemKind.scala +++ b/protocol/src/main/scala/sbt/internal/bsp/SourceItemKind.scala @@ -11,7 +11,7 @@ package bsp object SourceItemKind { - /** The source item references a normal file. */ + /** The source item references a normal file. */ val File: Int = 1 /** The source item references a directory. */ diff --git a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcNotificationMessageFormats.scala b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcNotificationMessageFormats.scala index 07a8b1f64..46464f019 100644 --- a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcNotificationMessageFormats.scala +++ b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcNotificationMessageFormats.scala @@ -24,8 +24,8 @@ trait JsonRpcNotificationMessageFormats { unbuilder.beginObject(js) val jsonrpc = unbuilder.readField[String]("jsonrpc") val method = unbuilder.readField[String]("method") - val params = unbuilder.lookupField("params") map { - case x: JValue => x + val params = unbuilder.lookupField("params") map { case x: JValue => + x } unbuilder.endObject() sbt.internal.protocol.JsonRpcNotificationMessage(jsonrpc, method, params) diff --git a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcRequestMessageFormats.scala b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcRequestMessageFormats.scala index 829b8d2a4..eb9cb042e 100644 --- a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcRequestMessageFormats.scala +++ b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcRequestMessageFormats.scala @@ -23,17 +23,18 @@ trait JsonRpcRequestMessageFormats { case Some(js) => unbuilder.beginObject(js) val jsonrpc = unbuilder.readField[String]("jsonrpc") - val id = try { - unbuilder.readField[String]("id") - } catch { - case _: DeserializationException => { - val prefix = "\u2668" // Append prefix to show the original type was Number - prefix + unbuilder.readField[Long]("id").toString + val id = + try { + unbuilder.readField[String]("id") + } catch { + case _: DeserializationException => { + val prefix = "\u2668" // Append prefix to show the original type was Number + prefix + unbuilder.readField[Long]("id").toString + } } - } val method = unbuilder.readField[String]("method") - val params = unbuilder.lookupField("params") map { - case x: JValue => x + val params = unbuilder.lookupField("params") map { case x: JValue => + x } unbuilder.endObject() sbt.internal.protocol.JsonRpcRequestMessage(jsonrpc, id, method, params) diff --git a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseErrorFormats.scala b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseErrorFormats.scala index 6d54a55ab..5e99fdc81 100644 --- a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseErrorFormats.scala +++ b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseErrorFormats.scala @@ -24,8 +24,8 @@ trait JsonRpcResponseErrorFormats { unbuilder.beginObject(js) val code = unbuilder.readField[Long]("code") val message = unbuilder.readField[String]("message") - val data = unbuilder.lookupField("data") map { - case x: JValue => x + val data = unbuilder.lookupField("data") map { case x: JValue => + x } unbuilder.endObject() sbt.internal.protocol.JsonRpcResponseError(code, message, data) diff --git a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseMessageFormats.scala b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseMessageFormats.scala index c93b31e22..72134c492 100644 --- a/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseMessageFormats.scala +++ b/protocol/src/main/scala/sbt/internal/protocol/codec/JsonRpcResponseMessageFormats.scala @@ -31,15 +31,16 @@ trait JsonRpcResponseMessageFormats { case Some(js) => unbuilder.beginObject(js) val jsonrpc = unbuilder.readField[String]("jsonrpc") - val id = try { - unbuilder.readField[String]("id") - } catch { - case _: DeserializationException => - unbuilder.readField[Long]("id").toString - } + val id = + try { + unbuilder.readField[String]("id") + } catch { + case _: DeserializationException => + unbuilder.readField[Long]("id").toString + } - val result = unbuilder.lookupField("result") map { - case x: JValue => x + val result = unbuilder.lookupField("result") map { case x: JValue => + x } val error = diff --git a/protocol/src/main/scala/sbt/protocol/Serialization.scala b/protocol/src/main/scala/sbt/protocol/Serialization.scala index 4b8537702..1059afe00 100644 --- a/protocol/src/main/scala/sbt/protocol/Serialization.scala +++ b/protocol/src/main/scala/sbt/protocol/Serialization.scala @@ -135,7 +135,8 @@ object Serialization { } /** - * @return A command or an invalid input description + * @return + * A command or an invalid input description */ @deprecated("unused", since = "1.4.0") def deserializeCommand(bytes: Seq[Byte]): Either[String, CommandMessage] = { @@ -153,7 +154,8 @@ object Serialization { } /** - * @return A command or an invalid input description + * @return + * A command or an invalid input description */ @deprecated("unused", since = "1.4.0") def deserializeEvent(bytes: Seq[Byte]): Either[String, Any] = { @@ -190,7 +192,8 @@ object Serialization { } /** - * @return A command or an invalid input description + * @return + * A command or an invalid input description */ @deprecated("unused", since = "1.4.0") def deserializeEventMessage(bytes: Seq[Byte]): Either[String, EventMessage] = { diff --git a/tasks-standard/src/main/scala/sbt/Action.scala b/tasks-standard/src/main/scala/sbt/Action.scala index 56cd2214e..6c6889c78 100644 --- a/tasks-standard/src/main/scala/sbt/Action.scala +++ b/tasks-standard/src/main/scala/sbt/Action.scala @@ -14,42 +14,42 @@ import ConcurrentRestrictions.{ Tag, TagMap, tagsKey } // Action, Task, and Info are intentionally invariant in their type parameter. // Various natural transformations used, such as PMap, require invariant type constructors for correctness -/** Defines a task computation*/ +/** Defines a task computation */ sealed trait Action[T] { // TODO: remove after deprecated InputTask constructors are removed private[sbt] def mapTask(f: Task ~> Task): Action[T] } /** - * A direct computation of a value. - * If `inline` is true, `f` will be evaluated on the scheduler thread without the overhead of normal scheduling when possible. - * This is intended as an optimization for already evaluated values or very short pure computations. + * A direct computation of a value. If `inline` is true, `f` will be evaluated on the scheduler + * thread without the overhead of normal scheduling when possible. This is intended as an + * optimization for already evaluated values or very short pure computations. */ final case class Pure[T](f: () => T, `inline`: Boolean) extends Action[T] { private[sbt] def mapTask(f: Task ~> Task) = this } -/** Applies a function to the result of evaluating a heterogeneous list of other tasks.*/ +/** Applies a function to the result of evaluating a heterogeneous list of other tasks. */ final case class Mapped[T, K[L[x]]](in: K[Task], f: K[Result] => T, alist: AList[K]) extends Action[T] { private[sbt] def mapTask(g: Task ~> Task) = Mapped[T, K](alist.transform(in, g), f, alist) } -/** Computes another task to evaluate based on results from evaluating other tasks.*/ +/** Computes another task to evaluate based on results from evaluating other tasks. */ final case class FlatMapped[T, K[L[x]]](in: K[Task], f: K[Result] => Task[T], alist: AList[K]) extends Action[T] { private[sbt] def mapTask(g: Task ~> Task) = FlatMapped[T, K](alist.transform(in, g), g.fn[T] compose f, alist) } -/** A computation `in` that requires other tasks `deps` to be evaluated first.*/ +/** A computation `in` that requires other tasks `deps` to be evaluated first. */ final case class DependsOn[T](in: Task[T], deps: Seq[Task[_]]) extends Action[T] { private[sbt] def mapTask(g: Task ~> Task) = DependsOn[T](g(in), deps.map(t => g(t))) } /** - * A computation that operates on the results of a homogeneous list of other tasks. - * It can either return another task to be evaluated or the final value. + * A computation that operates on the results of a homogeneous list of other tasks. It can either + * return another task to be evaluated or the final value. */ final case class Join[T, U](in: Seq[Task[U]], f: Seq[Result[U]] => Either[Task[T], T]) extends Action[T] { @@ -58,8 +58,8 @@ final case class Join[T, U](in: Seq[Task[U]], f: Seq[Result[U]] => Either[Task[T } /** - * A computation that conditionally falls back to a second transformation. - * This can be used to encode `if` conditions. + * A computation that conditionally falls back to a second transformation. This can be used to + * encode `if` conditions. */ final case class Selected[A, B](fab: Task[Either[A, B]], fin: Task[A => B]) extends Action[B] { private def ml = AList.single[Either[A, B]] @@ -76,9 +76,12 @@ final case class Selected[A, B](fab: Task[Either[A, B]], fin: Task[A => B]) exte case Right(b) => std.TaskExtra.task(b) case Left(a) => std.TaskExtra.singleInputTask(fin).map(_(a)) } - FlatMapped[B, K](fab, { - f compose std.TaskExtra.successM - }, ml) + FlatMapped[B, K]( + fab, { + f compose std.TaskExtra.successM + }, + ml + ) } } @@ -99,9 +102,13 @@ final case class Task[T](info: Info[T], work: Action[T]) { } /** - * Used to provide information about a task, such as the name, description, and tags for controlling concurrent execution. - * @param attributes Arbitrary user-defined key/value pairs describing this task - * @param post a transformation that takes the result of evaluating this task and produces user-defined key/value pairs. + * Used to provide information about a task, such as the name, description, and tags for controlling + * concurrent execution. + * @param attributes + * Arbitrary user-defined key/value pairs describing this task + * @param post + * a transformation that takes the result of evaluating this task and produces user-defined + * key/value pairs. */ final case class Info[T]( attributes: AttributeMap = AttributeMap.empty, diff --git a/tasks-standard/src/main/scala/sbt/std/Streams.scala b/tasks-standard/src/main/scala/sbt/std/Streams.scala index da487fdd3..cc4b83ef3 100644 --- a/tasks-standard/src/main/scala/sbt/std/Streams.scala +++ b/tasks-standard/src/main/scala/sbt/std/Streams.scala @@ -20,9 +20,9 @@ import sbt.util._ // no longer specific to Tasks, so 'TaskStreams' should be renamed /** - * Represents a set of streams associated with a context. - * In sbt, this is a named set of streams for a particular scoped key. - * For example, logging for test:compile is by default sent to the "out" stream in the test:compile context. + * Represents a set of streams associated with a context. In sbt, this is a named set of streams for + * a particular scoped key. For example, logging for test:compile is by default sent to the "out" + * stream in the test:compile context. */ sealed trait TaskStreams[Key] { @@ -36,16 +36,16 @@ sealed trait TaskStreams[Key] { def getOutput(sid: String = default): Output /** - * Provides a reader to read text from the stream `sid` for `key`. - * It is the caller's responsibility to coordinate writing to the stream. - * That is, no synchronization or ordering is provided and so this method should only be called when writing is complete. + * Provides a reader to read text from the stream `sid` for `key`. It is the caller's + * responsibility to coordinate writing to the stream. That is, no synchronization or ordering is + * provided and so this method should only be called when writing is complete. */ def readText(key: Key, sid: String = default): BufferedReader /** - * Provides an output stream to read from the stream `sid` for `key`. - * It is the caller's responsibility to coordinate writing to the stream. - * That is, no synchronization or ordering is provided and so this method should only be called when writing is complete. + * Provides an output stream to read from the stream `sid` for `key`. It is the caller's + * responsibility to coordinate writing to the stream. That is, no synchronization or ordering is + * provided and so this method should only be called when writing is complete. */ def readBinary(a: Key, sid: String = default): BufferedInputStream @@ -61,7 +61,7 @@ sealed trait TaskStreams[Key] { /** Provides an output stream for writing to the stream with the given ID. */ def binary(sid: String = default): BufferedOutputStream - /** A cache directory that is unique to the context of this streams instance.*/ + /** A cache directory that is unique to the context of this streams instance. */ def cacheDirectory: File def cacheStoreFactory: CacheStoreFactory @@ -70,7 +70,7 @@ sealed trait TaskStreams[Key] { /** Obtains the default logger. */ final lazy val log: ManagedLogger = log(default) - /** Creates a Logger that logs to stream with ID `sid`.*/ + /** Creates a Logger that logs to stream with ID `sid`. */ def log(sid: String): ManagedLogger private[this] def getID(s: Option[String]) = s getOrElse default @@ -165,23 +165,22 @@ object Streams { make(a, sid)(f => new FileOutput(f)) def readText(a: Key, sid: String = default): BufferedReader = - make(a, sid)( - f => new BufferedReader(new InputStreamReader(new FileInputStream(f), IO.defaultCharset)) + make(a, sid)(f => + new BufferedReader(new InputStreamReader(new FileInputStream(f), IO.defaultCharset)) ) def readBinary(a: Key, sid: String = default): BufferedInputStream = make(a, sid)(f => new BufferedInputStream(new FileInputStream(f))) def text(sid: String = default): PrintWriter = - make(a, sid)( - f => - new PrintWriter( - new DeferredWriter( - new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(f), IO.defaultCharset) - ) + make(a, sid)(f => + new PrintWriter( + new DeferredWriter( + new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(f), IO.defaultCharset) ) ) + ) ) def binary(sid: String = default): BufferedOutputStream = @@ -206,9 +205,11 @@ object Streams { case null => newLock case l => l } - try lock.synchronized { - if (!file.exists) IO.touch(file, setModified = false) - } finally { + try + lock.synchronized { + if (!file.exists) IO.touch(file, setModified = false) + } + finally { streamLocks.remove(parent) () } diff --git a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala index 3d2061d2c..4b749b8f4 100644 --- a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala +++ b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala @@ -170,11 +170,10 @@ trait TaskExtra extends TaskExtra0 { def andFinally(fin: => Unit): Task[S] = mapR(x => Result.tryValue[S]({ fin; x })) def doFinally(t: Task[Unit]): Task[S] = - flatMapR( - x => - t.result.map { tx => - Result.tryValues[S](tx :: Nil, x) - } + flatMapR(x => + t.result.map { tx => + Result.tryValues[S](tx :: Nil, x) + } ) def ||[T >: S](alt: Task[T]): Task[T] = flatMapR { case Value(v) => task(v: T) diff --git a/tasks-standard/src/main/scala/sbt/std/Transform.scala b/tasks-standard/src/main/scala/sbt/std/Transform.scala index f2259f3b3..d79445f4c 100644 --- a/tasks-standard/src/main/scala/sbt/std/Transform.scala +++ b/tasks-standard/src/main/scala/sbt/std/Transform.scala @@ -35,7 +35,7 @@ object Transform { pmap } - /** Applies `map`, returning the result if defined or returning the input unchanged otherwise.*/ + /** Applies `map`, returning the result if defined or returning the input unchanged otherwise. */ implicit def getOrId(map: Task ~>| Task): Task ~> Task = λ[Task ~> Task](in => map(in).getOrElse(in)) diff --git a/tasks-standard/src/test/scala/Test.scala b/tasks-standard/src/test/scala/Test.scala index 36091c583..0a369b6e4 100644 --- a/tasks-standard/src/test/scala/Test.scala +++ b/tasks-standard/src/test/scala/Test.scala @@ -20,7 +20,7 @@ object Test extends std.TaskExtra { val b2 = task(true) val c = task("asdf") - val h1 = t3(a, b, c).map { case (aa, bb, cc) => s"$aa $bb $cc" } + val h1 = t3(a, b, c).map { case (aa, bb, cc) => s"$aa $bb $cc" } val h2 = t3(a, b2, c).map { case (aa, bb, cc) => s"$aa $bb $cc" } type Values = (Result[Int], Result[Boolean], Result[String]) @@ -28,7 +28,9 @@ object Test extends std.TaskExtra { val f: Values => Any = { case (Value(aa), Value(bb), Value(cc)) => s"$aa $bb $cc" case x => - val cs = x.productIterator.toList.collect { case Inc(x) => x } // workaround for double definition bug + val cs = x.productIterator.toList.collect { case Inc(x) => + x + } // workaround for double definition bug throw Incomplete(None, causes = cs) } val d2 = t3(a, b2, c) mapR f diff --git a/tasks-standard/src/test/scala/TestRunnerSort.scala b/tasks-standard/src/test/scala/TestRunnerSort.scala index e7c6dcbed..97e247944 100644 --- a/tasks-standard/src/test/scala/TestRunnerSort.scala +++ b/tasks-standard/src/test/scala/TestRunnerSort.scala @@ -22,8 +22,7 @@ object TaskRunnerSortTest extends Properties("TaskRunnerSort") { } } final def sortDirect(a: Seq[Int]): Seq[Int] = { - if (a.length < 2) - a + if (a.length < 2) a else { val pivot = a(0) val (lt, gte) = a.view.drop(1).partition(_ < pivot) @@ -37,8 +36,8 @@ object TaskRunnerSortTest extends Properties("TaskRunnerSort") { task(a) flatMap { a => val pivot = a(0) val (lt, gte) = a.view.drop(1).partition(_ < pivot) - sbt.Test.t2(sort(lt.toSeq), sort(gte.toSeq)) map { - case (l, g) => l ++ List(pivot) ++ g + sbt.Test.t2(sort(lt.toSeq), sort(gte.toSeq)) map { case (l, g) => + l ++ List(pivot) ++ g } } } diff --git a/util-cache/src/main/scala/sbt/util/Cache.scala b/util-cache/src/main/scala/sbt/util/Cache.scala index c0cbd9a8e..8b152a327 100644 --- a/util-cache/src/main/scala/sbt/util/Cache.scala +++ b/util-cache/src/main/scala/sbt/util/Cache.scala @@ -16,8 +16,7 @@ sealed trait CacheResult[K] case class Hit[O](value: O) extends CacheResult[O] /** - * A cache miss. - * `update` associates the missing key with `O` in the cache. + * A cache miss. `update` associates the missing key with `O` in the cache. */ case class Miss[O](update: O => Unit) extends CacheResult[O] @@ -42,8 +41,10 @@ object Cache { /** * Returns a function that represents a cache that inserts on miss. * - * @param cacheFile The store that backs this cache. - * @param default A function that computes a default value to insert on + * @param cacheFile + * The store that backs this cache. + * @param default + * A function that computes a default value to insert on */ def cached[I, O](cacheFile: File)(default: I => O)(implicit cache: Cache[I, O]): I => O = cached(CacheStore(cacheFile))(default) @@ -51,8 +52,10 @@ object Cache { /** * Returns a function that represents a cache that inserts on miss. * - * @param store The store that backs this cache. - * @param default A function that computes a default value to insert on + * @param store + * The store that backs this cache. + * @param default + * A function that computes a default value to insert on */ def cached[I, O](store: CacheStore)(default: I => O)(implicit cache: Cache[I, O]): I => O = key => diff --git a/util-cache/src/main/scala/sbt/util/FileInfo.scala b/util-cache/src/main/scala/sbt/util/FileInfo.scala index b9d0e646d..d99ed8ce9 100644 --- a/util-cache/src/main/scala/sbt/util/FileInfo.scala +++ b/util-cache/src/main/scala/sbt/util/FileInfo.scala @@ -213,13 +213,15 @@ object FileInfo { FileModified(file.getAbsoluteFile, lastModified) /** - * Returns an instance of [[FileModified]] where, for any directory, the maximum last - * modified time taken from its contents is used rather than the last modified time of the - * directory itself. The specific motivation was to prevent the doc task from re-running when - * the modified time changed for a directory classpath but none of the classfiles had changed. + * Returns an instance of [[FileModified]] where, for any directory, the maximum last modified + * time taken from its contents is used rather than the last modified time of the directory + * itself. The specific motivation was to prevent the doc task from re-running when the modified + * time changed for a directory classpath but none of the classfiles had changed. * - * @param file the file or directory - * @return the [[FileModified]] + * @param file + * the file or directory + * @return + * the [[FileModified]] */ private[sbt] def fileOrDirectoryMax(file: File): ModifiedFileInfo = { val maxLastModified = diff --git a/util-cache/src/main/scala/sbt/util/Input.scala b/util-cache/src/main/scala/sbt/util/Input.scala index a79b84822..acaeeb708 100644 --- a/util-cache/src/main/scala/sbt/util/Input.scala +++ b/util-cache/src/main/scala/sbt/util/Input.scala @@ -30,7 +30,9 @@ class PlainInput[J: IsoString](input: InputStream, converter: SupportConverter[J val bufferSize = 1024 val buffer = new Array[Char](bufferSize) var read = 0 - while ({ read = reader.read(buffer, 0, bufferSize); read != -1 }) { + while + ({ read = reader.read(buffer, 0, bufferSize); read != -1 + }) { builder.appendAll(buffer, 0, read) } builder.toString() diff --git a/util-cache/src/main/scala/sbt/util/StampedFormat.scala b/util-cache/src/main/scala/sbt/util/StampedFormat.scala index eccb0f5bb..5b2177a8e 100644 --- a/util-cache/src/main/scala/sbt/util/StampedFormat.scala +++ b/util-cache/src/main/scala/sbt/util/StampedFormat.scala @@ -17,8 +17,8 @@ object StampedFormat extends BasicJsonProtocol { withStamp(stamp(format))(format) } - def withStamp[T, S](stamp: S)(format: JsonFormat[T])( - implicit formatStamp: JsonFormat[S], + def withStamp[T, S](stamp: S)(format: JsonFormat[T])(implicit + formatStamp: JsonFormat[S], equivStamp: Equiv[S] ): JsonFormat[T] = new JsonFormat[T] { diff --git a/util-cache/src/test/scala/CacheSpec.scala b/util-cache/src/test/scala/CacheSpec.scala index 6eab4cdaa..5d4064910 100644 --- a/util-cache/src/test/scala/CacheSpec.scala +++ b/util-cache/src/test/scala/CacheSpec.scala @@ -17,60 +17,56 @@ import org.scalatest.flatspec.AnyFlatSpec class CacheSpec extends AnyFlatSpec { "A cache" should "NOT throw an exception if read without being written previously" in { - testCache[String, Int] { - case (cache, store) => - cache(store)("missing") match { - case Hit(_) => fail() - case Miss(_) => () - } + testCache[String, Int] { case (cache, store) => + cache(store)("missing") match { + case Hit(_) => fail() + case Miss(_) => () + } } } it should "write a very simple value" in { - testCache[String, Int] { - case (cache, store) => - cache(store)("missing") match { - case Hit(_) => fail() - case Miss(update) => update(5) - } + testCache[String, Int] { case (cache, store) => + cache(store)("missing") match { + case Hit(_) => fail() + case Miss(update) => update(5) + } } } it should "be updatable" in { - testCache[String, Int] { - case (cache, store) => - val value = 5 - cache(store)("someKey") match { - case Hit(_) => fail() - case Miss(update) => update(value) - } + testCache[String, Int] { case (cache, store) => + val value = 5 + cache(store)("someKey") match { + case Hit(_) => fail() + case Miss(update) => update(value) + } - cache(store)("someKey") match { - case Hit(read) => assert(read === value); () - case Miss(_) => fail() - } + cache(store)("someKey") match { + case Hit(read) => assert(read === value); () + case Miss(_) => fail() + } } } it should "return the value that has been previously written" in { - testCache[String, Int] { - case (cache, store) => - val key = "someKey" - val value = 5 - cache(store)(key) match { - case Hit(_) => fail() - case Miss(update) => update(value) - } + testCache[String, Int] { case (cache, store) => + val key = "someKey" + val value = 5 + cache(store)(key) match { + case Hit(_) => fail() + case Miss(update) => update(value) + } - cache(store)(key) match { - case Hit(read) => assert(read === value); () - case Miss(_) => fail() - } + cache(store)(key) match { + case Hit(read) => assert(read === value); () + case Miss(_) => fail() + } } } - private def testCache[K, V](f: (Cache[K, V], CacheStore) => Unit)( - implicit cache: Cache[K, V] + private def testCache[K, V](f: (Cache[K, V], CacheStore) => Unit)(implicit + cache: Cache[K, V] ): Unit = IO.withTemporaryDirectory { tmp => val store = new FileBasedStore(tmp / "cache-store") diff --git a/util-cache/src/test/scala/SingletonCacheSpec.scala b/util-cache/src/test/scala/SingletonCacheSpec.scala index ab6de3adb..9c47a6c86 100644 --- a/util-cache/src/test/scala/SingletonCacheSpec.scala +++ b/util-cache/src/test/scala/SingletonCacheSpec.scala @@ -47,46 +47,42 @@ class SingletonCacheSpec extends AnyFlatSpec { } "A singleton cache" should "throw an exception if read without being written previously" in { - testCache[Int] { - case (cache, store) => - intercept[Exception] { - cache.read(store) - } - () + testCache[Int] { case (cache, store) => + intercept[Exception] { + cache.read(store) + } + () } } it should "write a very simple value" in { - testCache[Int] { - case (cache, store) => - cache.write(store, 5) + testCache[Int] { case (cache, store) => + cache.write(store, 5) } } it should "return the simple value that has been previously written" in { - testCache[Int] { - case (cache, store) => - val value = 5 - cache.write(store, value) - val read = cache.read(store) + testCache[Int] { case (cache, store) => + val value = 5 + cache.write(store, value) + val read = cache.read(store) - assert(read === value); () + assert(read === value); () } } it should "write a complex value" in { - testCache[ComplexType] { - case (cache, store) => - val value = ComplexType(1, "hello, world!", (1 to 10 by 3).toList) - cache.write(store, value) - val read = cache.read(store) + testCache[ComplexType] { case (cache, store) => + val value = ComplexType(1, "hello, world!", (1 to 10 by 3).toList) + cache.write(store, value) + val read = cache.read(store) - assert(read === value); () + assert(read === value); () } } - private def testCache[T](f: (SingletonCache[T], CacheStore) => Unit)( - implicit cache: SingletonCache[T] + private def testCache[T](f: (SingletonCache[T], CacheStore) => Unit)(implicit + cache: SingletonCache[T] ): Unit = IO.withTemporaryDirectory { tmp => val store = new FileBasedStore(tmp / "cache-store") diff --git a/util-collection/src/main/scala/sbt/internal/util/Util.scala b/util-collection/src/main/scala/sbt/internal/util/Util.scala index 1f03c0258..643f52ea7 100644 --- a/util-collection/src/main/scala/sbt/internal/util/Util.scala +++ b/util-collection/src/main/scala/sbt/internal/util/Util.scala @@ -45,7 +45,8 @@ object Util { def quoteIfKeyword(s: String): String = if (ScalaKeywords.values(s)) s"`${s}`" else s - // def ignoreResult[T](f: => T): Unit = macro Macro.ignore + def ignoreResult[A](f: => A): Unit = + f; () lazy val isMac: Boolean = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("mac") diff --git a/util-tracking/src/main/scala/sbt/util/ChangeReport.scala b/util-tracking/src/main/scala/sbt/util/ChangeReport.scala index abbb3ac06..9ebe7da84 100644 --- a/util-tracking/src/main/scala/sbt/util/ChangeReport.scala +++ b/util-tracking/src/main/scala/sbt/util/ChangeReport.scala @@ -22,31 +22,32 @@ object ChangeReport { } } -/** The result of comparing some current set of objects against a previous set of objects.*/ +/** The result of comparing some current set of objects against a previous set of objects. */ trait ChangeReport[T] { - /** The set of all of the objects in the current set.*/ + /** The set of all of the objects in the current set. */ def checked: Set[T] - /** All of the objects that are in the same state in the current and reference sets.*/ + /** All of the objects that are in the same state in the current and reference sets. */ def unmodified: Set[T] /** - * All checked objects that are not in the same state as the reference. This includes objects that are in both - * sets but have changed and files that are only in one set. + * All checked objects that are not in the same state as the reference. This includes objects that + * are in both sets but have changed and files that are only in one set. */ def modified: Set[T] // all changes, including added - /** All objects that are only in the current set.*/ + /** All objects that are only in the current set. */ def added: Set[T] - /** All objects only in the previous set*/ + /** All objects only in the previous set */ def removed: Set[T] def +++(other: ChangeReport[T]): ChangeReport[T] = new CompoundChangeReport(this, other) /** - * Generate a new report with this report's unmodified set included in the new report's modified set. The new report's - * unmodified set is empty. The new report's added, removed, and checked sets are the same as in this report. + * Generate a new report with this report's unmodified set included in the new report's modified + * set. The new report's unmodified set is empty. The new report's added, removed, and checked + * sets are the same as in this report. */ def markAllModified: ChangeReport[T] = new ChangeReport[T] { diff --git a/util-tracking/src/main/scala/sbt/util/FileFunction.scala b/util-tracking/src/main/scala/sbt/util/FileFunction.scala index 8ffea2008..3a5b06d7f 100644 --- a/util-tracking/src/main/scala/sbt/util/FileFunction.scala +++ b/util-tracking/src/main/scala/sbt/util/FileFunction.scala @@ -15,40 +15,41 @@ object FileFunction { private val defaultOutStyle = FileInfo.exists /** - * Generic change-detection helper used to help build / artifact generation / - * etc. steps detect whether or not they need to run. Returns a function whose - * input is a Set of input files, and subsequently executes the action function - * (which does the actual work: compiles, generates resources, etc.), returning - * a Set of output files that it generated. + * Generic change-detection helper used to help build / artifact generation / etc. steps detect + * whether or not they need to run. Returns a function whose input is a Set of input files, and + * subsequently executes the action function (which does the actual work: compiles, generates + * resources, etc.), returning a Set of output files that it generated. * - * The input file and resulting output file state is cached in stores issued by - * `storeFactory`. On each invocation, the state of the input and output - * files from the previous run is compared against the cache, as is the set of - * input files. If a change in file state / input files set is detected, the - * action function is re-executed. + * The input file and resulting output file state is cached in stores issued by `storeFactory`. On + * each invocation, the state of the input and output files from the previous run is compared + * against the cache, as is the set of input files. If a change in file state / input files set is + * detected, the action function is re-executed. * - * @param cacheBaseDirectory The folder in which to store - * @param action The work function, which receives a list of input files and returns a list of output files + * @param cacheBaseDirectory + * The folder in which to store + * @param action + * The work function, which receives a list of input files and returns a list of output files */ def cached(cacheBaseDirectory: File)(action: Set[File] => Set[File]): Set[File] => Set[File] = cached(cacheBaseDirectory, inStyle = defaultInStyle, outStyle = defaultOutStyle)(action) /** - * Generic change-detection helper used to help build / artifact generation / - * etc. steps detect whether or not they need to run. Returns a function whose - * input is a Set of input files, and subsequently executes the action function - * (which does the actual work: compiles, generates resources, etc.), returning - * a Set of output files that it generated. + * Generic change-detection helper used to help build / artifact generation / etc. steps detect + * whether or not they need to run. Returns a function whose input is a Set of input files, and + * subsequently executes the action function (which does the actual work: compiles, generates + * resources, etc.), returning a Set of output files that it generated. * - * The input file and resulting output file state is cached in stores issued by - * `storeFactory`. On each invocation, the state of the input and output - * files from the previous run is compared against the cache, as is the set of - * input files. If a change in file state / input files set is detected, the - * action function is re-executed. + * The input file and resulting output file state is cached in stores issued by `storeFactory`. On + * each invocation, the state of the input and output files from the previous run is compared + * against the cache, as is the set of input files. If a change in file state / input files set is + * detected, the action function is re-executed. * - * @param cacheBaseDirectory The folder in which to store - * @param inStyle The strategy by which to detect state change in the input files from the previous run - * @param action The work function, which receives a list of input files and returns a list of output files + * @param cacheBaseDirectory + * The folder in which to store + * @param inStyle + * The strategy by which to detect state change in the input files from the previous run + * @param action + * The work function, which receives a list of input files and returns a list of output files */ def cached(cacheBaseDirectory: File, inStyle: FileInfo.Style)( action: Set[File] => Set[File] @@ -56,65 +57,68 @@ object FileFunction { cached(cacheBaseDirectory, inStyle = inStyle, outStyle = defaultOutStyle)(action) /** - * Generic change-detection helper used to help build / artifact generation / - * etc. steps detect whether or not they need to run. Returns a function whose - * input is a Set of input files, and subsequently executes the action function - * (which does the actual work: compiles, generates resources, etc.), returning - * a Set of output files that it generated. + * Generic change-detection helper used to help build / artifact generation / etc. steps detect + * whether or not they need to run. Returns a function whose input is a Set of input files, and + * subsequently executes the action function (which does the actual work: compiles, generates + * resources, etc.), returning a Set of output files that it generated. * - * The input file and resulting output file state is cached in stores issued by - * `storeFactory`. On each invocation, the state of the input and output - * files from the previous run is compared against the cache, as is the set of - * input files. If a change in file state / input files set is detected, the - * action function is re-executed. + * The input file and resulting output file state is cached in stores issued by `storeFactory`. On + * each invocation, the state of the input and output files from the previous run is compared + * against the cache, as is the set of input files. If a change in file state / input files set is + * detected, the action function is re-executed. * - * @param cacheBaseDirectory The folder in which to store - * @param inStyle The strategy by which to detect state change in the input files from the previous run - * @param outStyle The strategy by which to detect state change in the output files from the previous run - * @param action The work function, which receives a list of input files and returns a list of output files + * @param cacheBaseDirectory + * The folder in which to store + * @param inStyle + * The strategy by which to detect state change in the input files from the previous run + * @param outStyle + * The strategy by which to detect state change in the output files from the previous run + * @param action + * The work function, which receives a list of input files and returns a list of output files */ def cached(cacheBaseDirectory: File, inStyle: FileInfo.Style, outStyle: FileInfo.Style)( action: Set[File] => Set[File] ): Set[File] => Set[File] = - cached(CacheStoreFactory(cacheBaseDirectory), inStyle, outStyle)( - (in, out) => action(in.checked) + cached(CacheStoreFactory(cacheBaseDirectory), inStyle, outStyle)((in, out) => + action(in.checked) ) /** - * Generic change-detection helper used to help build / artifact generation / - * etc. steps detect whether or not they need to run. Returns a function whose - * input is a Set of input files, and subsequently executes the action function - * (which does the actual work: compiles, generates resources, etc.), returning - * a Set of output files that it generated. + * Generic change-detection helper used to help build / artifact generation / etc. steps detect + * whether or not they need to run. Returns a function whose input is a Set of input files, and + * subsequently executes the action function (which does the actual work: compiles, generates + * resources, etc.), returning a Set of output files that it generated. * - * The input file and resulting output file state is cached in stores issued by - * `storeFactory`. On each invocation, the state of the input and output - * files from the previous run is compared against the cache, as is the set of - * input files. If a change in file state / input files set is detected, the - * action function is re-executed. + * The input file and resulting output file state is cached in stores issued by `storeFactory`. On + * each invocation, the state of the input and output files from the previous run is compared + * against the cache, as is the set of input files. If a change in file state / input files set is + * detected, the action function is re-executed. * - * @param storeFactory The factory to use to get stores for the input and output files. - * @param action The work function, which receives a list of input files and returns a list of output files + * @param storeFactory + * The factory to use to get stores for the input and output files. + * @param action + * The work function, which receives a list of input files and returns a list of output files */ def cached(storeFactory: CacheStoreFactory)(action: UpdateFunction): Set[File] => Set[File] = cached(storeFactory, inStyle = defaultInStyle, outStyle = defaultOutStyle)(action) /** - * Generic change-detection helper used to help build / artifact generation / - * etc. steps detect whether or not they need to run. Returns a function whose - * input is a Set of input files, and subsequently executes the action function - * (which does the actual work: compiles, generates resources, etc.), returning - * a Set of output files that it generated. + * Generic change-detection helper used to help build / artifact generation / etc. steps detect + * whether or not they need to run. Returns a function whose input is a Set of input files, and + * subsequently executes the action function (which does the actual work: compiles, generates + * resources, etc.), returning a Set of output files that it generated. * - * The input file and resulting output file state is cached in stores issued by - * `storeFactory`. On each invocation, the state of the input and output - * files from the previous run is compared against the cache, as is the set of - * input files. If a change in file state / input files set is detected, the - * action function is re-executed. + * The input file and resulting output file state is cached in stores issued by `storeFactory`. On + * each invocation, the state of the input and output files from the previous run is compared + * against the cache, as is the set of input files. If a change in file state / input files set is + * detected, the action function is re-executed. * - * @param storeFactory The factory to use to get stores for the input and output files. - * @param inStyle The strategy by which to detect state change in the input files from the previous run - * @param action The work function, which receives a list of input files and returns a list of output files + * @param storeFactory + * The factory to use to get stores for the input and output files. + * @param inStyle + * The strategy by which to detect state change in the input files from the previous run + * @param action + * The work function, which receives a list of input files and returns a list of output files */ def cached(storeFactory: CacheStoreFactory, inStyle: FileInfo.Style)( action: UpdateFunction @@ -122,22 +126,24 @@ object FileFunction { cached(storeFactory, inStyle = inStyle, outStyle = defaultOutStyle)(action) /** - * Generic change-detection helper used to help build / artifact generation / - * etc. steps detect whether or not they need to run. Returns a function whose - * input is a Set of input files, and subsequently executes the action function - * (which does the actual work: compiles, generates resources, etc.), returning - * a Set of output files that it generated. + * Generic change-detection helper used to help build / artifact generation / etc. steps detect + * whether or not they need to run. Returns a function whose input is a Set of input files, and + * subsequently executes the action function (which does the actual work: compiles, generates + * resources, etc.), returning a Set of output files that it generated. * - * The input file and resulting output file state is cached in stores issued by - * `storeFactory`. On each invocation, the state of the input and output - * files from the previous run is compared against the cache, as is the set of - * input files. If a change in file state / input files set is detected, the - * action function is re-executed. + * The input file and resulting output file state is cached in stores issued by `storeFactory`. On + * each invocation, the state of the input and output files from the previous run is compared + * against the cache, as is the set of input files. If a change in file state / input files set is + * detected, the action function is re-executed. * - * @param storeFactory The factory to use to get stores for the input and output files. - * @param inStyle The strategy by which to detect state change in the input files from the previous run - * @param outStyle The strategy by which to detect state change in the output files from the previous run - * @param action The work function, which receives a list of input files and returns a list of output files + * @param storeFactory + * The factory to use to get stores for the input and output files. + * @param inStyle + * The strategy by which to detect state change in the input files from the previous run + * @param outStyle + * The strategy by which to detect state change in the output files from the previous run + * @param action + * The work function, which receives a list of input files and returns a list of output files */ def cached(storeFactory: CacheStoreFactory, inStyle: FileInfo.Style, outStyle: FileInfo.Style)( action: UpdateFunction diff --git a/util-tracking/src/main/scala/sbt/util/Tracked.scala b/util-tracking/src/main/scala/sbt/util/Tracked.scala index b4bc765c1..ad83802df 100644 --- a/util-tracking/src/main/scala/sbt/util/Tracked.scala +++ b/util-tracking/src/main/scala/sbt/util/Tracked.scala @@ -20,22 +20,22 @@ import sjsonnew.support.murmurhash.Hasher object Tracked { /** - * Creates a tracker that provides the last time it was evaluated. - * If the function throws an exception. + * Creates a tracker that provides the last time it was evaluated. If the function throws an + * exception. */ def tstamp(store: CacheStore): Timestamp = tstamp(store, true) /** - * Creates a tracker that provides the last time it was evaluated. - * If the function throws an exception. + * Creates a tracker that provides the last time it was evaluated. If the function throws an + * exception. */ def tstamp(cacheFile: File): Timestamp = tstamp(CacheStore(cacheFile)) /** - * Creates a tracker that provides the last time it was evaluated. - * If 'useStartTime' is true, the recorded time is the start of the evaluated function. - * If 'useStartTime' is false, the recorded time is when the evaluated function completes. - * In both cases, the timestamp is not updated if the function throws an exception. + * Creates a tracker that provides the last time it was evaluated. If 'useStartTime' is true, the + * recorded time is the start of the evaluated function. If 'useStartTime' is false, the recorded + * time is when the evaluated function completes. In both cases, the timestamp is not updated if + * the function throws an exception. */ def tstamp(store: CacheStore, useStartTime: Boolean): Timestamp = { import CacheImplicits.LongJsonFormat @@ -43,27 +43,39 @@ object Tracked { } /** - * Creates a tracker that provides the last time it was evaluated. - * If 'useStartTime' is true, the recorded time is the start of the evaluated function. - * If 'useStartTime' is false, the recorded time is when the evaluated function completes. - * In both cases, the timestamp is not updated if the function throws an exception. + * Creates a tracker that provides the last time it was evaluated. If 'useStartTime' is true, the + * recorded time is the start of the evaluated function. If 'useStartTime' is false, the recorded + * time is when the evaluated function completes. In both cases, the timestamp is not updated if + * the function throws an exception. */ def tstamp(cacheFile: File, useStartTime: Boolean): Timestamp = tstamp(CacheStore(cacheFile), useStartTime) - /** Creates a tracker that provides the difference between a set of input files for successive invocations.*/ + /** + * Creates a tracker that provides the difference between a set of input files for successive + * invocations. + */ def diffInputs(store: CacheStore, style: FileInfo.Style): Difference = Difference.inputs(store, style) - /** Creates a tracker that provides the difference between a set of input files for successive invocations.*/ + /** + * Creates a tracker that provides the difference between a set of input files for successive + * invocations. + */ def diffInputs(cacheFile: File, style: FileInfo.Style): Difference = diffInputs(CacheStore(cacheFile), style) - /** Creates a tracker that provides the difference between a set of output files for successive invocations.*/ + /** + * Creates a tracker that provides the difference between a set of output files for successive + * invocations. + */ def diffOutputs(store: CacheStore, style: FileInfo.Style): Difference = Difference.outputs(store, style) - /** Creates a tracker that provides the difference between a set of output files for successive invocations.*/ + /** + * Creates a tracker that provides the difference between a set of output files for successive + * invocations. + */ def diffOutputs(cacheFile: File, style: FileInfo.Style): Difference = diffOutputs(CacheStore(cacheFile), style) @@ -113,7 +125,8 @@ object Tracked { * cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet)) * }}} * - * This is a variant of `outputChanged` that takes `A1: JsonWriter` as opposed to `A1: JsonFormat`. + * This is a variant of `outputChanged` that takes `A1: JsonWriter` as opposed to `A1: + * JsonFormat`. */ def outputChangedW[A1: JsonWriter, A2](store: CacheStore)( f: (Boolean, A1) => A2 @@ -163,7 +176,8 @@ object Tracked { * cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet)) * }}} * - * This is a variant of `outputChanged` that takes `A1: JsonWriter` as opposed to `A1: JsonFormat`. + * This is a variant of `outputChanged` that takes `A1: JsonWriter` as opposed to `A1: + * JsonFormat`. */ def outputChangedW[A1: JsonWriter, A2]( cacheFile: File @@ -298,7 +312,7 @@ object Tracked { trait Tracked { - /** Cleans outputs and clears the cache.*/ + /** Cleans outputs and clears the cache. */ def clean(): Unit } @@ -308,8 +322,8 @@ class Timestamp(val store: CacheStore, useStartTime: Boolean)(implicit format: J def clean() = store.delete() /** - * Reads the previous timestamp, evaluates the provided function, - * and then updates the timestamp if the function completes normally. + * Reads the previous timestamp, evaluates the provided function, and then updates the timestamp + * if the function completes normally. */ def apply[T](f: Long => T): T = { val start = now() @@ -329,8 +343,7 @@ class Changed[O: Equiv: JsonFormat](val store: CacheStore) extends Tracked { def clean() = store.delete() def apply[O2](ifChanged: O => O2, ifUnchanged: O => O2): O => O2 = value => { - if (uptodate(value)) - ifUnchanged(value) + if (uptodate(value)) ifUnchanged(value) else { update(value) ifChanged(value) @@ -338,7 +351,9 @@ class Changed[O: Equiv: JsonFormat](val store: CacheStore) extends Tracked { } def update(value: O): Unit = - store.write(value) //Using.fileOutputStream(false)(cacheFile)(stream => format.writes(stream, value)) + store.write( + value + ) // Using.fileOutputStream(false)(cacheFile)(stream => format.writes(stream, value)) def uptodate(value: O): Boolean = { val equiv: Equiv[O] = implicitly @@ -354,9 +369,10 @@ object Difference { (store, style) => new Difference(store, style, defineClean, filesAreOutputs) /** - * Provides a constructor for a Difference that removes the files from the previous run on a call to 'clean' and saves the - * hash/last modified time of the files as they are after running the function. This means that this information must be evaluated twice: - * before and after running the function. + * Provides a constructor for a Difference that removes the files from the previous run on a call + * to 'clean' and saves the hash/last modified time of the files as they are after running the + * function. This means that this information must be evaluated twice: before and after running + * the function. */ val outputs = constructor(true, true) @@ -405,8 +421,10 @@ class Difference( val report = new ChangeReport[File] { lazy val checked = currentFiles - lazy val removed = lastFiles -- checked // all files that were included previously but not this time. This is independent of whether the files exist. - lazy val added = checked -- lastFiles // all files included now but not previously. This is independent of whether the files exist. + lazy val removed = + lastFiles -- checked // all files that were included previously but not this time. This is independent of whether the files exist. + lazy val added = + checked -- lastFiles // all files included now but not previously. This is independent of whether the files exist. lazy val modified = raw(lastFilesInfo -- currentFilesInfo.files) ++ added lazy val unmodified = checked -- modified } diff --git a/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala b/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala index 6c640a818..8d8a69337 100644 --- a/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala +++ b/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala @@ -67,8 +67,8 @@ class TrackedSpec extends AnyFlatSpec { withStore { store => val input0 = Input(1) - val cachedFun = Tracked.inputChangedW[Input, Int](store) { - case (_, in) => in.v + val cachedFun = Tracked.inputChangedW[Input, Int](store) { case (_, in) => + in.v } val res0 = cachedFun(input0) @@ -145,8 +145,8 @@ class TrackedSpec extends AnyFlatSpec { withStore { store => val input0 = Input(1) - val cachedFun = Tracked.outputChangedW[Input, Int](store) { - case (_, in) => in.v + val cachedFun = Tracked.outputChangedW[Input, Int](store) { case (_, in) => + in.v } val res0 = cachedFun(() => input0)