From 00eba85d98c854527125ae1655b5332c19b5afd8 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 6 Dec 2021 02:06:26 -0500 Subject: [PATCH] Cats-like typeclasses --- .scalafmt.conf | 9 +- build.sbt | 41 ++------- .../internal/util/appmacro/ContextUtil.scala | 92 +++++++++++-------- .../sbt/internal/util/appmacro/Instance.scala | 67 +++++++------- .../internal/util/appmacro/KListBuilder.scala | 8 +- .../internal/util/appmacro/MixedBuilder.scala | 5 +- .../internal/util/appmacro/TupleBuilder.scala | 46 ++++++---- .../util/appmacro/TupleNBuilder.scala | 8 +- .../scala/sbt/internal/util/Classes.scala | 42 --------- .../sbt/internal/util/ErrorHandling.scala | 3 +- .../scala/sbt/internal/util/ExitHook.scala | 7 +- .../internal/util/MessageOnlyException.scala | 11 ++- .../sbt/internal/util/RunningProcesses.scala | 5 +- .../scala/sbt/internal/util/logic/Logic.scala | 86 +++++++++-------- .../scala/sbt/internal/util/Relation.scala | 52 ++++++----- .../src/test/scala/RelationTest.scala | 26 +++--- project/Dependencies.scala | 12 ++- project/HouseRulesPlugin.scala | 5 +- .../main/scala/sbt/CompletionService.scala | 34 +++---- .../scala/sbt/ConcurrentRestrictions.scala | 85 ++++++++++------- tasks/src/main/scala/sbt/Execute.scala | 38 ++++---- .../src/main/scala/sbt/ExecuteProgress.scala | 44 ++++----- tasks/src/main/scala/sbt/Incomplete.scala | 16 +++- tasks/src/main/scala/sbt/Node.scala | 6 +- tasks/src/main/scala/sbt/Result.scala | 6 +- .../NOTICE | 0 .../scala-2.12/sbt/internal/util/Par.scala | 0 .../sbt/internal/util/WrappedMap.scala | 0 .../scala-2.13/sbt/internal/util/Par.scala | 0 .../sbt/internal/util/WrappedMap.scala | 0 .../scala-2}/sbt/internal/util/AList.scala | 0 .../scala-2}/sbt/internal/util/HList.scala | 0 .../sbt/internal/util/HListFormats.scala | 0 .../scala-2}/sbt/internal/util/INode.scala | 2 + .../scala-2}/sbt/internal/util/KList.scala | 0 .../scala-2}/sbt/internal/util/PMap.scala | 0 .../scala-2}/sbt/internal/util/Settings.scala | 0 .../scala/sbt/internal/util/Attributes.scala | 76 ++++++++------- .../main/scala/sbt/internal/util/Dag.scala | 15 ++- .../main/scala/sbt/internal/util/IDSet.scala | 2 +- .../main/scala/sbt/internal/util/Signal.scala | 7 +- .../sbt/internal/util/TypeFunctions.scala | 4 + .../main/scala/sbt/internal/util/Types.scala | 8 +- .../main/scala/sbt/internal/util/Util.scala | 12 +-- .../src/main/scala/sbt/util/Applicative.scala | 19 ++++ .../src/main/scala/sbt/util/Apply.scala | 19 ++++ .../src/main/scala/sbt/util/FlatMap.scala | 22 +++++ .../src/main/scala/sbt/util/Functor.scala | 16 ++++ .../main/scala/sbt/util/ListInstances.scala | 23 +++++ .../src/main/scala/sbt/util/Monad.scala | 19 ++++ .../main/scala/sbt/util/OptJsonWriter.scala | 0 .../main/scala/sbt/util/OptionInstances.scala | 21 +++++ .../src/main/scala/sbt/util/Selective.scala | 12 +++ .../src/main/scala/sbt/util/Show.scala | 9 +- .../src/test/scala-2}/DagSpecification.scala | 0 .../src/test/scala-2}/HListFormatSpec.scala | 0 .../src/test/scala-2}/KeyTest.scala | 0 .../src/test/scala-2}/PMapTest.scala | 0 .../src/test/scala-2}/SettingsExample.scala | 0 .../src/test/scala-2}/SettingsTest.scala | 0 .../src/test/scala-2}/UnitSpec.scala | 0 .../src/test/scala/FunctorTest.scala | 40 ++++++++ 62 files changed, 639 insertions(+), 441 deletions(-) delete mode 100644 internal/util-collection/src/main/scala/sbt/internal/util/Classes.scala rename {internal/util-collection => util-collection}/NOTICE (100%) rename {internal/util-collection => util-collection}/src/main/scala-2.12/sbt/internal/util/Par.scala (100%) rename {internal/util-collection => util-collection}/src/main/scala-2.12/sbt/internal/util/WrappedMap.scala (100%) rename {internal/util-collection => util-collection}/src/main/scala-2.13/sbt/internal/util/Par.scala (100%) rename {internal/util-collection => util-collection}/src/main/scala-2.13/sbt/internal/util/WrappedMap.scala (100%) rename {internal/util-collection/src/main/scala => util-collection/src/main/scala-2}/sbt/internal/util/AList.scala (100%) rename {internal/util-collection/src/main/scala => util-collection/src/main/scala-2}/sbt/internal/util/HList.scala (100%) rename {internal/util-collection/src/main/scala => util-collection/src/main/scala-2}/sbt/internal/util/HListFormats.scala (100%) rename {internal/util-collection/src/main/scala => util-collection/src/main/scala-2}/sbt/internal/util/INode.scala (99%) rename {internal/util-collection/src/main/scala => util-collection/src/main/scala-2}/sbt/internal/util/KList.scala (100%) rename {internal/util-collection/src/main/scala => util-collection/src/main/scala-2}/sbt/internal/util/PMap.scala (100%) rename {internal/util-collection/src/main/scala => util-collection/src/main/scala-2}/sbt/internal/util/Settings.scala (100%) rename {internal/util-collection => util-collection}/src/main/scala/sbt/internal/util/Attributes.scala (76%) rename {internal/util-collection => util-collection}/src/main/scala/sbt/internal/util/Dag.scala (90%) rename {internal/util-collection => util-collection}/src/main/scala/sbt/internal/util/IDSet.scala (98%) rename {internal/util-collection => util-collection}/src/main/scala/sbt/internal/util/Signal.scala (93%) rename {internal/util-collection => util-collection}/src/main/scala/sbt/internal/util/TypeFunctions.scala (99%) rename {internal/util-collection => util-collection}/src/main/scala/sbt/internal/util/Types.scala (61%) rename {internal/util-collection => util-collection}/src/main/scala/sbt/internal/util/Util.scala (87%) create mode 100644 util-collection/src/main/scala/sbt/util/Applicative.scala create mode 100644 util-collection/src/main/scala/sbt/util/Apply.scala create mode 100644 util-collection/src/main/scala/sbt/util/FlatMap.scala create mode 100644 util-collection/src/main/scala/sbt/util/Functor.scala create mode 100644 util-collection/src/main/scala/sbt/util/ListInstances.scala create mode 100644 util-collection/src/main/scala/sbt/util/Monad.scala rename {internal/util-collection => util-collection}/src/main/scala/sbt/util/OptJsonWriter.scala (100%) create mode 100644 util-collection/src/main/scala/sbt/util/OptionInstances.scala create mode 100644 util-collection/src/main/scala/sbt/util/Selective.scala rename {internal/util-collection => util-collection}/src/main/scala/sbt/util/Show.scala (85%) rename {internal/util-collection/src/test/scala => util-collection/src/test/scala-2}/DagSpecification.scala (100%) rename {internal/util-collection/src/test/scala => util-collection/src/test/scala-2}/HListFormatSpec.scala (100%) rename {internal/util-collection/src/test/scala => util-collection/src/test/scala-2}/KeyTest.scala (100%) rename {internal/util-collection/src/test/scala => util-collection/src/test/scala-2}/PMapTest.scala (100%) rename {internal/util-collection/src/test/scala => util-collection/src/test/scala-2}/SettingsExample.scala (100%) rename {internal/util-collection/src/test/scala => util-collection/src/test/scala-2}/SettingsTest.scala (100%) rename {internal/util-collection/src/test/scala => util-collection/src/test/scala-2}/UnitSpec.scala (100%) create mode 100644 util-collection/src/test/scala/FunctorTest.scala diff --git a/.scalafmt.conf b/.scalafmt.conf index 06a114f59..36a16786c 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,5 +1,6 @@ -version = 2.3.2 -edition = 2019-10 +version = 3.2.1 +runner.dialect = scala3 + maxColumn = 100 project.git = true project.excludeFilters = [ "\\Wsbt-test\\W", "\\Winput_sources\\W", "\\Wcontraband-scala\\W" ] @@ -7,7 +8,7 @@ lineEndings = preserve # https://docs.scala-lang.org/style/scaladoc.html recommends the JavaDoc style. # scala/scala is written that way too https://github.com/scala/scala/blob/v2.12.2/src/library/scala/Predef.scala -docstrings = JavaDoc +docstrings.style = Asterisk # This also seems more idiomatic to include whitespace in import x.{ yyy } spaces.inImportCurlyBraces = true @@ -18,7 +19,7 @@ align.openParenCallSite = false align.openParenDefnSite = false # For better code clarity -danglingParentheses = true +danglingParentheses.preset = true trailingCommas = preserve diff --git a/build.sbt b/build.sbt index 46681bca6..deba99856 100644 --- a/build.sbt +++ b/build.sbt @@ -180,8 +180,8 @@ def mimaSettingsSince(versions: Seq[String]): Seq[Def.Setting[_]] = Def settings val scriptedSbtReduxMimaSettings = Def.settings(mimaPreviousArtifacts := Set()) lazy val sbtRoot: Project = (project in file(".")) -// .enablePlugins(ScriptedPlugin) - .aggregate(nonRoots: _*) +// .aggregate(nonRoots: _*) + .aggregate(collectionProj) .settings( minimalSettings, onLoadMessage := { @@ -256,49 +256,20 @@ lazy val bundledLauncherProj = /* ** subproject declarations ** */ -val collectionProj = (project in file("internal") / "util-collection") +val collectionProj = (project in file("util-collection")) + .dependsOn(utilPosition) .settings( + name := "Collections", testedBaseSettings, utilCommonSettings, Util.keywordsSettings, - name := "Collections", libraryDependencies ++= Seq(sjsonNewScalaJson.value), libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((2, major)) if major <= 12 => Seq() - case _ => Seq("org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0") + case _ => Seq(scalaPar) }), mimaSettings, - mimaBinaryIssueFilters ++= Seq( - // Added private[sbt] method to capture State attributes. - exclude[ReversedMissingMethodProblem]("sbt.internal.util.AttributeMap.setCond"), - // Dropped in favour of kind-projector's inline type lambda syntax - exclude[MissingClassProblem]("sbt.internal.util.TypeFunctions$P1of2"), - // Dropped in favour of kind-projector's polymorphic lambda literals - exclude[MissingClassProblem]("sbt.internal.util.Param"), - exclude[MissingClassProblem]("sbt.internal.util.Param$"), - // Dropped in favour of plain scala.Function, and its compose method - exclude[MissingClassProblem]("sbt.internal.util.Fn1"), - exclude[DirectMissingMethodProblem]("sbt.internal.util.TypeFunctions.toFn1"), - exclude[DirectMissingMethodProblem]("sbt.internal.util.Types.toFn1"), - // Instead of defining foldr in KList & overriding in KCons, - // it's now abstract in KList and defined in both KCons & KNil. - exclude[FinalMethodProblem]("sbt.internal.util.KNil.foldr"), - exclude[DirectAbstractMethodProblem]("sbt.internal.util.KList.foldr"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.Init*.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.Settings0.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.EvaluateSettings#INode.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.TypeFunctions.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.EvaluateSettings.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.Settings.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.EvaluateSettings#MixedNode.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.EvaluateSettings#BindNode.this"), - exclude[IncompatibleSignatureProblem]( - "sbt.internal.util.EvaluateSettings#BindNode.dependsOn" - ), - exclude[IncompatibleSignatureProblem]("sbt.internal.util.Types.some") - ), ) - .dependsOn(utilPosition) // Command line-related utilities. val completeProj = (project in file("internal") / "util-complete") diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala index e87b13a21..17d8672cb 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala @@ -18,16 +18,17 @@ object ContextUtil { /** * Constructs an object with utility methods for operating in the provided macro context `c`. - * Callers should explicitly specify the type parameter as `c.type` in order to preserve the path dependent types. + * Callers should explicitly specify the type parameter as `c.type` in order to preserve the path + * dependent types. */ def apply[C <: blackbox.Context with Singleton](c: C): ContextUtil[C] = new ContextUtil(c: C) /** - * Helper for implementing a no-argument macro that is introduced via an implicit. - * This method removes the implicit conversion and evaluates the function `f` on the target of the conversion. + * Helper for implementing a no-argument macro that is introduced via an implicit. This method + * removes the implicit conversion and evaluates the function `f` on the target of the conversion. * - * Given `myImplicitConversion(someValue).extensionMethod`, where `extensionMethod` is a macro that uses this - * method, the result of this method is `f()`. + * Given `myImplicitConversion(someValue).extensionMethod`, where `extensionMethod` is a macro + * that uses this method, the result of this method is `f()`. */ def selectMacroImpl[T: c.WeakTypeTag]( c: blackbox.Context @@ -46,10 +47,9 @@ object ContextUtil { } /** - * Utility methods for macros. Several methods assume that the context's universe is a full compiler - * (`scala.tools.nsc.Global`). - * This is not thread safe due to the underlying Context and related data structures not being thread safe. - * Use `ContextUtil[c.type](c)` to construct. + * Utility methods for macros. Several methods assume that the context's universe is a full compiler + * (`scala.tools.nsc.Global`). This is not thread safe due to the underlying Context and related + * data structures not being thread safe. Use `ContextUtil[c.type](c)` to construct. */ final class ContextUtil[C <: blackbox.Context](val ctx: C) { import ctx.universe.{ Apply => ApplyTree, _ } @@ -64,20 +64,20 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { lazy val alist: Symbol = alistType.typeSymbol.companion lazy val alistTC: Type = alistType.typeConstructor - /** Modifiers for a local val.*/ + /** Modifiers for a local val. */ lazy val localModifiers = Modifiers(NoFlags) def getPos(sym: Symbol) = if (sym eq null) NoPosition else sym.pos /** - * Constructs a unique term name with the given prefix within this Context. - * (The current implementation uses Context.freshName, which increments + * Constructs a unique term name with the given prefix within this Context. (The current + * implementation uses Context.freshName, which increments */ def freshTermName(prefix: String) = TermName(ctx.freshName("$" + prefix)) /** - * Constructs a new, synthetic, local ValDef Type `tpe`, a unique name, - * Position `pos`, an empty implementation (no rhs), and owned by `owner`. + * Constructs a new, synthetic, local ValDef Type `tpe`, a unique name, Position `pos`, an empty + * implementation (no rhs), and owned by `owner`. */ def freshValDef(tpe: Type, pos: Position, owner: Symbol): ValDef = { val SYNTHETIC = (1 << 21).toLong.asInstanceOf[FlagSet] @@ -91,8 +91,8 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { lazy val parameterModifiers = Modifiers(Flag.PARAM) /** - * Collects all definitions in the tree for use in checkReferences. - * This excludes definitions in wrapped expressions because checkReferences won't allow nested dereferencing anyway. + * Collects all definitions in the tree for use in checkReferences. This excludes definitions in + * wrapped expressions because checkReferences won't allow nested dereferencing anyway. */ def collectDefs( tree: Tree, @@ -119,8 +119,8 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { } /** - * A reference is illegal if it is to an M instance defined within the scope of the macro call. - * As an approximation, disallow referenced to any local definitions `defs`. + * A reference is illegal if it is to an M instance defined within the scope of the macro call. As + * an approximation, disallow referenced to any local definitions `defs`. */ def illegalReference(defs: collection.Set[Symbol], sym: Symbol, mType: Type): Boolean = sym != null && sym != NoSymbol && defs.contains(sym) && { @@ -131,8 +131,8 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { } /** - * A reference is illegal if it is to an M instance defined within the scope of the macro call. - * As an approximation, disallow referenced to any local definitions `defs`. + * A reference is illegal if it is to an M instance defined within the scope of the macro call. As + * an approximation, disallow referenced to any local definitions `defs`. */ def illegalReference(defs: collection.Set[Symbol], sym: Symbol): Boolean = illegalReference(defs, sym, weakTypeOf[Any]) @@ -141,7 +141,7 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { /** * A function that checks the provided tree for illegal references to M instances defined in the - * expression passed to the macro and for illegal dereferencing of M instances. + * expression passed to the macro and for illegal dereferencing of M instances. */ def checkReferences( defs: collection.Set[Symbol], @@ -160,12 +160,15 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { @deprecated("Use that variant that specifies the M instance types to exclude", since = "1.3.0") /** * A function that checks the provided tree for illegal references to M instances defined in the - * expression passed to the macro and for illegal dereferencing of M instances. + * expression passed to the macro and for illegal dereferencing of M instances. */ def checkReferences(defs: collection.Set[Symbol], isWrapper: PropertyChecker): Tree => Unit = checkReferences(defs, isWrapper, weakTypeOf[Any]) - /** Constructs a ValDef with a parameter modifier, a unique name, with the provided Type and with an empty rhs. */ + /** + * Constructs a ValDef with a parameter modifier, a unique name, with the provided Type and with + * an empty rhs. + */ def freshMethodParameter(tpe: Type): ValDef = ValDef(parameterModifiers, freshTermName("p"), TypeTree(tpe), EmptyTree) @@ -173,7 +176,7 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { def localValDef(tpt: Tree, rhs: Tree): ValDef = ValDef(localModifiers, freshTermName("q"), tpt, rhs) - /** Constructs a tuple value of the right TupleN type from the provided inputs.*/ + /** Constructs a tuple value of the right TupleN type from the provided inputs. */ def mkTuple(args: List[Tree]): Tree = global.gen.mkTuple(args.asInstanceOf[List[global.Tree]]).asInstanceOf[ctx.universe.Tree] @@ -202,7 +205,10 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { /** A Type that references the given type variable. */ def refVar(variable: TypeSymbol): Type = variable.toTypeConstructor - /** Constructs a new, synthetic type variable that is a type constructor. For example, in type Y[L[x]], L is such a type variable. */ + /** + * Constructs a new, synthetic type variable that is a type constructor. For example, in type + * Y[L[x]], L is such a type variable. + */ def newTCVariable(owner: Symbol): TypeSymbol = { val tc = newTypeVariable(owner) val arg = newTypeVariable(tc, "x"); @@ -226,11 +232,17 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { tpe.asInstanceOf[Type] } - /** Create a Tree that references the `val` represented by `vd`, copying attributes from `replaced`. */ + /** + * Create a Tree that references the `val` represented by `vd`, copying attributes from + * `replaced`. + */ def refVal(replaced: Tree, vd: ValDef): Tree = treeCopy.Ident(replaced, vd.name).setSymbol(vd.symbol) - /** Creates a Function tree using `functionSym` as the Symbol and changing `initialOwner` to `functionSym` in `body`.*/ + /** + * Creates a Function tree using `functionSym` as the Symbol and changing `initialOwner` to + * `functionSym` in `body`. + */ def createFunction(params: List[ValDef], body: Tree, functionSym: Symbol): Tree = { changeOwner(body, initialOwner, functionSym) val f = Function(params, body) @@ -262,7 +274,7 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { def singleton[T <: AnyRef with Singleton](i: T)(implicit it: ctx.TypeTag[i.type]): Symbol = it.tpe match { case SingleType(_, sym) if !sym.isFreeTerm && sym.isStatic => sym - case x => sys.error("Instance must be static (was " + x + ").") + case x => sys.error("Instance must be static (was " + x + ").") } def select(t: Tree, name: String): Tree = Select(t, TermName(name)) @@ -275,12 +287,12 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { } /** - * Returns a Type representing the type constructor tcp.. For example, given - * `object Demo { type M[x] = List[x] }`, the call `extractTC(Demo, "M")` will return a type representing - * the type constructor `[x] List[x]`. + * Returns a Type representing the type constructor tcp.. For example, given `object Demo { + * type M[x] = List[x] }`, the call `extractTC(Demo, "M")` will return a type representing the + * type constructor `[x] List[x]`. */ - def extractTC(tcp: AnyRef with Singleton, name: String)( - implicit it: ctx.TypeTag[tcp.type] + def extractTC(tcp: AnyRef with Singleton, name: String)(implicit + it: ctx.TypeTag[tcp.type] ): ctx.Type = { val itTpe = it.tpe.asInstanceOf[global.Type] val m = itTpe.nonPrivateMember(global.newTypeName(name)) @@ -290,10 +302,10 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { } /** - * Substitutes wrappers in tree `t` with the result of `subWrapper`. - * A wrapper is a Tree of the form `f[T](v)` for which isWrapper(, , .target) returns true. - * Typically, `f` is a `Select` or `Ident`. - * The wrapper is replaced with the result of `subWrapper(, , )` + * Substitutes wrappers in tree `t` with the result of `subWrapper`. A wrapper is a Tree of the + * form `f[T](v)` for which isWrapper(, , .target) returns true. + * Typically, `f` is a `Select` or `Ident`. The wrapper is replaced with the result of + * `subWrapper(, , )` */ def transformWrappers( t: Tree, @@ -307,7 +319,11 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) { case ApplyTree(TypeApply(Select(_, nme), targ :: Nil), qual :: Nil) => subWrapper(nme.decodedName.toString, targ.tpe, qual, tree) match { case Converted.Success(t, finalTx) => - changeOwner(qual, currentOwner, initialOwner) // Fixes https://github.com/sbt/sbt/issues/1150 + changeOwner( + qual, + currentOwner, + initialOwner + ) // Fixes https://github.com/sbt/sbt/issues/1150 finalTx(t) case Converted.Failure(p, m) => ctx.abort(p, m) case _: Converted.NotApplicable[_] => super.transform(tree) diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/Instance.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/Instance.scala index 35e2d7dc6..96b282f5f 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/Instance.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/Instance.scala @@ -14,8 +14,8 @@ import sbt.internal.util.Types.Id /** * The separate hierarchy from Applicative/Monad is for two reasons. * - * 1. The type constructor is represented as an abstract type because a TypeTag cannot represent a type constructor directly. - * 2. The applicative interface is uncurried. + * 1. The type constructor is represented as an abstract type because a TypeTag cannot represent a + * type constructor directly. 2. The applicative interface is uncurried. */ trait Instance { type M[x] @@ -51,40 +51,41 @@ object Instance { def idTransform[C <: blackbox.Context with Singleton]: Transform[C, Id] = in => in /** - * Implementation of a macro that provides a direct syntax for applicative functors and monads. - * It is intended to be used in conjunction with another macro that conditions the inputs. + * Implementation of a macro that provides a direct syntax for applicative functors and monads. It + * is intended to be used in conjunction with another macro that conditions the inputs. * - * This method processes the Tree `t` to find inputs of the form `wrap[T]( input )` - * This form is typically constructed by another macro that pretends to be able to get a value of type `T` - * from a value convertible to `M[T]`. This `wrap(input)` form has two main purposes. - * First, it identifies the inputs that should be transformed. - * Second, it allows the input trees to be wrapped for later conversion into the appropriate `M[T]` type by `convert`. - * This wrapping is necessary because applying the first macro must preserve the original type, - * but it is useful to delay conversion until the outer, second macro is called. The `wrap` method accomplishes this by - * allowing the original `Tree` and `Type` to be hidden behind the raw `T` type. This method will remove the call to `wrap` - * so that it is not actually called at runtime. + * This method processes the Tree `t` to find inputs of the form `wrap[T]( input )` This form is + * typically constructed by another macro that pretends to be able to get a value of type `T` from + * a value convertible to `M[T]`. This `wrap(input)` form has two main purposes. First, it + * identifies the inputs that should be transformed. Second, it allows the input trees to be + * wrapped for later conversion into the appropriate `M[T]` type by `convert`. This wrapping is + * necessary because applying the first macro must preserve the original type, but it is useful to + * delay conversion until the outer, second macro is called. The `wrap` method accomplishes this + * by allowing the original `Tree` and `Type` to be hidden behind the raw `T` type. This method + * will remove the call to `wrap` so that it is not actually called at runtime. * * Each `input` in each expression of the form `wrap[T]( input )` is transformed by `convert`. - * This transformation converts the input Tree to a Tree of type `M[T]`. - * The original wrapped expression `wrap(input)` is replaced by a reference to a new local `val x: T`, where `x` is a fresh name. - * These converted inputs are passed to `builder` as well as the list of these synthetic `ValDef`s. - * The `TupleBuilder` instance constructs a tuple (Tree) from the inputs and defines the right hand side of the vals - * that unpacks the tuple containing the results of the inputs. + * This transformation converts the input Tree to a Tree of type `M[T]`. The original wrapped + * expression `wrap(input)` is replaced by a reference to a new local `val x: T`, where `x` is a + * fresh name. These converted inputs are passed to `builder` as well as the list of these + * synthetic `ValDef`s. The `TupleBuilder` instance constructs a tuple (Tree) from the inputs and + * defines the right hand side of the vals that unpacks the tuple containing the results of the + * inputs. * - * The constructed tuple of inputs and the code that unpacks the results of the inputs are then passed to the `i`, - * which is an implementation of `Instance` that is statically accessible. - * An Instance defines a applicative functor associated with a specific type constructor and, if it implements MonadInstance as well, a monad. - * Typically, it will be either a top-level module or a stable member of a top-level module (such as a val or a nested module). - * The `with Singleton` part of the type verifies some cases at macro compilation time, - * while the full check for static accessibility is done at macro expansion time. - * Note: Ideally, the types would verify that `i: MonadInstance` when `t.isRight`. - * With the various dependent types involved, this is not worth it. + * The constructed tuple of inputs and the code that unpacks the results of the inputs are then + * passed to the `i`, which is an implementation of `Instance` that is statically accessible. An + * Instance defines a applicative functor associated with a specific type constructor and, if it + * implements MonadInstance as well, a monad. Typically, it will be either a top-level module or a + * stable member of a top-level module (such as a val or a nested module). The `with Singleton` + * part of the type verifies some cases at macro compilation time, while the full check for static + * accessibility is done at macro expansion time. Note: Ideally, the types would verify that `i: + * MonadInstance` when `t.isRight`. With the various dependent types involved, this is not worth + * it. * - * The `t` argument is the argument of the macro that will be transformed as described above. - * If the macro that calls this method is for a multi-input map (app followed by map), - * `t` should be the argument wrapped in Left. - * If this is for multi-input flatMap (app followed by flatMap), - * this should be the argument wrapped in Right. + * The `t` argument is the argument of the macro that will be transformed as described above. If + * the macro that calls this method is for a multi-input map (app followed by map), `t` should be + * the argument wrapped in Left. If this is for multi-input flatMap (app followed by flatMap), + * this should be the argument wrapped in Right. */ def contImpl[T, N[_]]( c: blackbox.Context, @@ -95,8 +96,8 @@ object Instance { )( t: Either[c.Expr[T], c.Expr[i.M[T]]], inner: Transform[c.type, N] - )( - implicit tt: c.WeakTypeTag[T], + )(implicit + tt: c.WeakTypeTag[T], nt: c.WeakTypeTag[N[T]], it: c.TypeTag[i.type] ): c.Expr[i.M[N[T]]] = { diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/KListBuilder.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/KListBuilder.scala index 6d2ae0a50..067b05601 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/KListBuilder.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/KListBuilder.scala @@ -11,7 +11,7 @@ package appmacro import scala.reflect._ import macros._ -/** A `TupleBuilder` that uses a KList as the tuple representation.*/ +/** A `TupleBuilder` that uses a KList as the tuple representation. */ object KListBuilder extends TupleBuilder { def make( c: blackbox.Context @@ -29,7 +29,7 @@ object KListBuilder extends TupleBuilder { val mTC: Type = mt.asInstanceOf[c.universe.Type] val kconsTC: Type = kconsTpe.typeConstructor - /** This is the L in the type function [L[x]] ... */ + /** This is the L in the type function [L[x]] ... */ val tcVariable: TypeSymbol = newTCVariable(util.initialOwner) /** Instantiates KCons[h, t <: KList[L], L], where L is the type constructor variable */ @@ -70,8 +70,8 @@ object KListBuilder extends TupleBuilder { val klist = makeKList(inputs.reverse, knil, knilType) /** - * The input types combined in a KList type. The main concern is tracking the heterogeneous types. - * The type constructor is tcVariable, so that it can be applied to [X] X or M later. + * The input types combined in a KList type. The main concern is tracking the heterogeneous + * types. The type constructor is tcVariable, so that it can be applied to [X] X or M later. * When applied to `M`, this type gives the type of the `input` KList. */ val klistType: Type = inputs.foldRight(knilType)((in, klist) => kconsType(in.tpe, klist)) diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/MixedBuilder.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/MixedBuilder.scala index abcde7c80..efc7f2596 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/MixedBuilder.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/MixedBuilder.scala @@ -12,8 +12,9 @@ import scala.reflect._ import macros._ /** - * A builder that uses `TupleN` as the representation for small numbers of inputs (up to `TupleNBuilder.MaxInputs`) - * and `KList` for larger numbers of inputs. This builder cannot handle fewer than 2 inputs. + * A builder that uses `TupleN` as the representation for small numbers of inputs (up to + * `TupleNBuilder.MaxInputs`) and `KList` for larger numbers of inputs. This builder cannot handle + * fewer than 2 inputs. */ object MixedBuilder extends TupleBuilder { def make( diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleBuilder.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleBuilder.scala index 14afc4eb4..7ecdddc01 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleBuilder.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleBuilder.scala @@ -12,22 +12,25 @@ import scala.reflect._ import macros._ /** - * A `TupleBuilder` abstracts the work of constructing a tuple data structure such as a `TupleN` or `KList` - * and extracting values from it. The `Instance` macro implementation will (roughly) traverse the tree of its argument - * and ultimately obtain a list of expressions with type `M[T]` for different types `T`. - * The macro constructs an `Input` value for each of these expressions that contains the `Type` for `T`, - * the `Tree` for the expression, and a `ValDef` that will hold the value for the input. + * A `TupleBuilder` abstracts the work of constructing a tuple data structure such as a `TupleN` or + * `KList` and extracting values from it. The `Instance` macro implementation will (roughly) + * traverse the tree of its argument and ultimately obtain a list of expressions with type `M[T]` + * for different types `T`. The macro constructs an `Input` value for each of these expressions that + * contains the `Type` for `T`, the `Tree` for the expression, and a `ValDef` that will hold the + * value for the input. * - * `TupleBuilder.apply` is provided with the list of `Input`s and is expected to provide three values in the returned BuilderResult. - * First, it returns the constructed tuple data structure Tree in `input`. - * Next, it provides the type constructor `representationC` that, when applied to M, gives the type of tuple data structure. - * For example, a builder that constructs a `Tuple3` for inputs `M[Int]`, `M[Boolean]`, and `M[String]` - * would provide a Type representing `[L[x]] (L[Int], L[Boolean], L[String])`. The `input` method - * would return a value whose type is that type constructor applied to M, or `(M[Int], M[Boolean], M[String])`. + * `TupleBuilder.apply` is provided with the list of `Input`s and is expected to provide three + * values in the returned BuilderResult. First, it returns the constructed tuple data structure Tree + * in `input`. Next, it provides the type constructor `representationC` that, when applied to M, + * gives the type of tuple data structure. For example, a builder that constructs a `Tuple3` for + * inputs `M[Int]`, `M[Boolean]`, and `M[String]` would provide a Type representing `[L[x]] (L[Int], + * L[Boolean], L[String])`. The `input` method would return a value whose type is that type + * constructor applied to M, or `(M[Int], M[Boolean], M[String])`. * - * Finally, the `extract` method provides a list of vals that extract information from the applied input. - * The type of the applied input is the type constructor applied to `Id` (`[X] X`). - * The returned list of ValDefs should be the ValDefs from `inputs`, but with non-empty right-hand sides. + * Finally, the `extract` method provides a list of vals that extract information from the applied + * input. The type of the applied input is the type constructor applied to `Id` (`[X] X`). The + * returned list of ValDefs should be the ValDefs from `inputs`, but with non-empty right-hand + * sides. */ trait TupleBuilder { @@ -45,20 +48,23 @@ trait BuilderResult[C <: blackbox.Context with Singleton] { import ctx.universe._ /** - * Represents the higher-order type constructor `[L[x]] ...` where `...` is the - * type of the data structure containing the added expressions, - * except that it is abstracted over the type constructor applied to each heterogeneous part of the type . + * Represents the higher-order type constructor `[L[x]] ...` where `...` is the type of the data + * structure containing the added expressions, except that it is abstracted over the type + * constructor applied to each heterogeneous part of the type . */ def representationC: PolyType - /** The instance of AList for the input. For a `representationC` of `[L[x]]`, this `Tree` should have a `Type` of `AList[L]`*/ + /** + * The instance of AList for the input. For a `representationC` of `[L[x]]`, this `Tree` should + * have a `Type` of `AList[L]` + */ def alistInstance: Tree /** Returns the completed value containing all expressions added to the builder. */ def input: Tree /* The list of definitions that extract values from a value of type `$representationC[Id]`. - * The returned value should be identical to the `ValDef`s provided to the `TupleBuilder.make` method but with - * non-empty right hand sides. Each `ValDef` may refer to `param` and previous `ValDef`s in the list.*/ + * The returned value should be identical to the `ValDef`s provided to the `TupleBuilder.make` method but with + * non-empty right hand sides. Each `ValDef` may refer to `param` and previous `ValDef`s in the list.*/ def extract(param: ValDef): List[ValDef] } diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleNBuilder.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleNBuilder.scala index e47e06b11..349e90065 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleNBuilder.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/TupleNBuilder.scala @@ -13,8 +13,8 @@ import scala.reflect._ import macros._ /** - * A builder that uses a TupleN as the tuple representation. - * It is limited to tuples of size 2 to `MaxInputs`. + * A builder that uses a TupleN as the tuple representation. It is limited to tuples of size 2 to + * `MaxInputs`. */ object TupleNBuilder extends TupleBuilder { @@ -35,8 +35,8 @@ object TupleNBuilder extends TupleBuilder { val ctx: c.type = c val representationC: PolyType = { val tcVariable: Symbol = newTCVariable(util.initialOwner) - val tupleTypeArgs = inputs.map( - in => internal.typeRef(NoPrefix, tcVariable, in.tpe :: Nil).asInstanceOf[global.Type] + val tupleTypeArgs = inputs.map(in => + internal.typeRef(NoPrefix, tcVariable, in.tpe :: Nil).asInstanceOf[global.Type] ) val tuple = global.definitions.tupleType(tupleTypeArgs) internal.polyType(tcVariable :: Nil, tuple.asInstanceOf[Type]) diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Classes.scala b/internal/util-collection/src/main/scala/sbt/internal/util/Classes.scala deleted file mode 100644 index 2d7c7aeac..000000000 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Classes.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* - * sbt - * Copyright 2011 - 2018, Lightbend, Inc. - * Copyright 2008 - 2010, Mark Harrah - * Licensed under Apache License 2.0 (see LICENSE) - */ - -package sbt.internal.util - -object Classes { - trait Applicative[M[_]] { - def apply[S, T](f: M[S => T], v: M[S]): M[T] - def pure[S](s: => S): M[S] - def map[S, T](f: S => T, v: M[S]): M[T] - } - - trait Selective[M[_]] extends Applicative[M] { - def select[A, B](fab: M[Either[A, B]])(fn: M[A => B]): M[B] - } - - trait Monad[M[_]] extends Applicative[M] { - def flatten[T](m: M[M[T]]): M[T] - } - - implicit val optionMonad: Monad[Option] = new Monad[Option] { - def apply[S, T](f: Option[S => T], v: Option[S]) = (f, v) match { - case (Some(fv), Some(vv)) => Some(fv(vv)) - case _ => None - } - - def pure[S](s: => S) = Some(s) - def map[S, T](f: S => T, v: Option[S]) = v map f - def flatten[T](m: Option[Option[T]]): Option[T] = m.flatten - } - - implicit val listMonad: Monad[List] = new Monad[List] { - def apply[S, T](f: List[S => T], v: List[S]) = for (fv <- f; vv <- v) yield fv(vv) - def pure[S](s: => S) = s :: Nil - def map[S, T](f: S => T, v: List[S]) = v map f - def flatten[T](m: List[List[T]]): List[T] = m.flatten - } -} diff --git a/internal/util-control/src/main/scala/sbt/internal/util/ErrorHandling.scala b/internal/util-control/src/main/scala/sbt/internal/util/ErrorHandling.scala index 7b2a86994..c8579b695 100644 --- a/internal/util-control/src/main/scala/sbt/internal/util/ErrorHandling.scala +++ b/internal/util-control/src/main/scala/sbt/internal/util/ErrorHandling.scala @@ -36,8 +36,7 @@ object ErrorHandling { if (e.getClass == classOf[RuntimeException]) { val msg = e.getMessage if (msg == null || msg.isEmpty) e.toString else msg - } else - e.toString + } else e.toString } sealed class TranslatedException private[sbt] (msg: String, cause: Throwable) diff --git a/internal/util-control/src/main/scala/sbt/internal/util/ExitHook.scala b/internal/util-control/src/main/scala/sbt/internal/util/ExitHook.scala index 677b780fd..76d059741 100644 --- a/internal/util-control/src/main/scala/sbt/internal/util/ExitHook.scala +++ b/internal/util-control/src/main/scala/sbt/internal/util/ExitHook.scala @@ -7,7 +7,7 @@ package sbt.internal.util -/** Defines a function to call as sbt exits.*/ +/** Defines a function to call as sbt exits. */ trait ExitHook { /** Subclasses should implement this method, which is called when this hook is executed. */ @@ -21,7 +21,10 @@ object ExitHook { object ExitHooks { - /** Calls each registered exit hook, trapping any exceptions so that each hook is given a chance to run. */ + /** + * Calls each registered exit hook, trapping any exceptions so that each hook is given a chance to + * run. + */ def runExitHooks(exitHooks: Seq[ExitHook]): Seq[Throwable] = exitHooks.flatMap(hook => ErrorHandling.wideConvert(hook.runBeforeExiting()).left.toOption) diff --git a/internal/util-control/src/main/scala/sbt/internal/util/MessageOnlyException.scala b/internal/util-control/src/main/scala/sbt/internal/util/MessageOnlyException.scala index 094d4999c..f629c1bcf 100644 --- a/internal/util-control/src/main/scala/sbt/internal/util/MessageOnlyException.scala +++ b/internal/util-control/src/main/scala/sbt/internal/util/MessageOnlyException.scala @@ -10,19 +10,20 @@ package sbt.internal.util final class MessageOnlyException(override val toString: String) extends RuntimeException(toString) /** - * A dummy exception for the top-level exception handler to know that an exception - * has been handled, but is being passed further up to indicate general failure. + * A dummy exception for the top-level exception handler to know that an exception has been handled, + * but is being passed further up to indicate general failure. */ final class AlreadyHandledException(val underlying: Throwable) extends RuntimeException /** - * A marker trait for a top-level exception handler to know that this exception - * doesn't make sense to display. + * A marker trait for a top-level exception handler to know that this exception doesn't make sense + * to display. */ trait UnprintableException extends Throwable /** * A marker trait that refines UnprintableException to indicate to a top-level exception handler - * that the code throwing this exception has already provided feedback to the user about the error condition. + * that the code throwing this exception has already provided feedback to the user about the error + * condition. */ trait FeedbackProvidedException extends UnprintableException diff --git a/internal/util-control/src/main/scala/sbt/internal/util/RunningProcesses.scala b/internal/util-control/src/main/scala/sbt/internal/util/RunningProcesses.scala index 47da42d34..d99bd94ad 100644 --- a/internal/util-control/src/main/scala/sbt/internal/util/RunningProcesses.scala +++ b/internal/util-control/src/main/scala/sbt/internal/util/RunningProcesses.scala @@ -11,9 +11,8 @@ import java.util.concurrent.ConcurrentHashMap import scala.sys.process.Process /** - * Manages forked processes created by sbt. Any process registered - * with RunningProcesses can be killed with the killAll method. In - * particular, this can be used in a signal handler to kill these + * Manages forked processes created by sbt. Any process registered with RunningProcesses can be + * killed with the killAll method. In particular, this can be used in a signal handler to kill these * processes when the user inputs ctrl+c. */ private[sbt] object RunningProcesses { diff --git a/internal/util-logic/src/main/scala/sbt/internal/util/logic/Logic.scala b/internal/util-logic/src/main/scala/sbt/internal/util/logic/Logic.scala index e508022bb..0ca045630 100644 --- a/internal/util-logic/src/main/scala/sbt/internal/util/logic/Logic.scala +++ b/internal/util-logic/src/main/scala/sbt/internal/util/logic/Logic.scala @@ -50,7 +50,7 @@ sealed abstract class Literal extends Formula { /** The underlying (positive) atom. */ def atom: Atom - /** Negates this literal.*/ + /** Negates this literal. */ def unary_! : Literal } @@ -62,24 +62,24 @@ final case class Atom(label: String) extends Literal { } /** - * A negated atom, in the sense of negation as failure, not logical negation. - * That is, it is true if `atom` is not known/defined. + * A negated atom, in the sense of negation as failure, not logical negation. That is, it is true if + * `atom` is not known/defined. */ final case class Negated(atom: Atom) extends Literal { def unary_! : Atom = atom } /** - * A formula consists of variables, negation, and conjunction (and). - * (Disjunction is not currently included- it is modeled at the level of a sequence of clauses. - * This is less convenient when defining clauses, but is not less powerful.) + * A formula consists of variables, negation, and conjunction (and). (Disjunction is not currently + * included- it is modeled at the level of a sequence of clauses. This is less convenient when + * defining clauses, but is not less powerful.) */ sealed abstract class Formula { /** Constructs a clause that proves `atoms` when this formula is true. */ def proves(atom: Atom, atoms: Atom*): Clause = Clause(this, (atom +: atoms).toSet) - /** Constructs a formula that is true iff this formula and `f` are both true.*/ + /** Constructs a formula that is true iff this formula and `f` are both true. */ def &&(f: Formula): Formula = (this, f) match { case (True, x) => x case (x, True) => x @@ -111,9 +111,9 @@ object Logic { /** * Computes the variables in the unique stable model for the program represented by `clauses` and - * `initialFacts`. `clause` may not have any negative feedback (that is, negation is acyclic) - * and `initialFacts` cannot be in the head of any clauses in `clause`. - * These restrictions ensure that the logic program has a unique minimal model. + * `initialFacts`. `clause` may not have any negative feedback (that is, negation is acyclic) and + * `initialFacts` cannot be in the head of any clauses in `clause`. These restrictions ensure that + * the logic program has a unique minimal model. */ def reduce(clauses: Clauses, initialFacts: Set[Literal]): Either[LogicException, Matched] = { val (posSeq, negSeq) = separate(initialFacts.toSeq) @@ -130,10 +130,9 @@ object Logic { } /** - * Verifies `initialFacts` are not in the head of any `clauses`. - * This avoids the situation where an atom is proved but no clauses prove it. - * This isn't necessarily a problem, but the main sbt use cases expects - * a proven atom to have at least one clause satisfied. + * Verifies `initialFacts` are not in the head of any `clauses`. This avoids the situation where + * an atom is proved but no clauses prove it. This isn't necessarily a problem, but the main sbt + * use cases expects a proven atom to have at least one clause satisfied. */ private[this] def checkOverlap( clauses: Clauses, @@ -179,12 +178,11 @@ object Logic { } private[this] def dependencyMap(clauses: Clauses): Map[Atom, Set[Literal]] = - clauses.clauses.foldLeft(Map.empty[Atom, Set[Literal]]) { - case (m, Clause(formula, heads)) => - val deps = literals(formula) - heads.foldLeft(m) { (n, head) => - n.updated(head, n.getOrElse(head, Set.empty) ++ deps) - } + clauses.clauses.foldLeft(Map.empty[Atom, Set[Literal]]) { case (m, Clause(formula, heads)) => + val deps = literals(formula) + heads.foldLeft(m) { (n, head) => + n.updated(head, n.getOrElse(head, Set.empty) ++ deps) + } } sealed abstract class LogicException(override val toString: String) @@ -229,8 +227,8 @@ object Logic { } /** - * Finds clauses that have no body and thus prove their head. - * Returns `(, )`. + * Finds clauses that have no body and thus prove their head. Returns `(, )`. */ private[this] def findProven(c: Clauses): (Set[Atom], List[Clause]) = { val (proven, unproven) = c.clauses.partition(_.body == True) @@ -253,8 +251,7 @@ object Logic { val processedFacts = state add keepPositive(factsToProcess) val newlyProven = proven -- processedFacts.provenSet val newState = processedFacts add newlyProven - if (unprovenClauses.isEmpty) - newState // no remaining clauses, done. + if (unprovenClauses.isEmpty) newState // no remaining clauses, done. else { val unproven = Clauses(unprovenClauses) val nextFacts: Set[Literal] = @@ -265,8 +262,8 @@ object Logic { } /** - * Finds negated atoms under the negation as failure rule and returns them. - * This should be called only after there are no more known atoms to be substituted. + * Finds negated atoms under the negation as failure rule and returns them. This should be called + * only after there are no more known atoms to be substituted. */ private[this] def inferFailure(clauses: Clauses): Set[Literal] = { /* At this point, there is at least one clause and one of the following is the case as the @@ -281,8 +278,7 @@ object Logic { */ val allAtoms = atoms(clauses) val newFacts: Set[Literal] = negated(allAtoms.triviallyFalse) - if (newFacts.nonEmpty) - newFacts + if (newFacts.nonEmpty) newFacts else { val possiblyTrue = hasNegatedDependency(clauses.clauses, Relation.empty, Relation.empty) val newlyFalse: Set[Literal] = negated(allAtoms.inHead -- possiblyTrue) @@ -296,10 +292,9 @@ object Logic { private[this] def negated(atoms: Set[Atom]): Set[Literal] = atoms.map(a => (Negated(a): Literal)) /** - * Computes the set of atoms in `clauses` that directly or transitively take a negated atom as input. - * For example, for the following clauses, this method would return `List(a, d)` : - * a :- b, not c - * d :- a + * Computes the set of atoms in `clauses` that directly or transitively take a negated atom as + * input. For example, for the following clauses, this method would return `List(a, d)` : a :- b, + * not c d :- a */ @tailrec def hasNegatedDependency( @@ -315,9 +310,8 @@ object Logic { case Clause(formula, head) +: tail => // collect direct positive and negative literals and track them in separate graphs val (pos, neg) = directDeps(formula) - val (newPos, newNeg) = head.foldLeft((posDeps, negDeps)) { - case ((pdeps, ndeps), d) => - (pdeps.+(d, pos), ndeps.+(d, neg)) + val (newPos, newNeg) = head.foldLeft((posDeps, negDeps)) { case ((pdeps, ndeps), d) => + (pdeps.+(d, pos), ndeps.+(d, neg)) } hasNegatedDependency(tail, newPos, newNeg) } @@ -346,7 +340,9 @@ object Logic { case True => Set() } - /** Represents the set of atoms in the heads of clauses and in the bodies (formulas) of clauses. */ + /** + * Represents the set of atoms in the heads of clauses and in the bodies (formulas) of clauses. + */ final case class Atoms(inHead: Set[Atom], inFormula: Set[Atom]) { /** Concatenates this with `as`. */ @@ -359,16 +355,16 @@ object Logic { /** * Applies known facts to `clause`s, deriving a new, possibly empty list of clauses. - * 1. If a fact is in the body of a clause, the derived clause has that fact removed from the body. - * 2. If the negation of a fact is in a body of a clause, that clause fails and is removed. - * 3. If a fact or its negation is in the head of a clause, the derived clause has that fact (or its negation) removed from the head. - * 4. If a head is empty, the clause proves nothing and is removed. + * 1. If a fact is in the body of a clause, the derived clause has that fact removed from the + * body. 2. If the negation of a fact is in a body of a clause, that clause fails and is + * removed. 3. If a fact or its negation is in the head of a clause, the derived clause has + * that fact (or its negation) removed from the head. 4. If a head is empty, the clause + * proves nothing and is removed. * - * NOTE: empty bodies do not cause a clause to succeed yet. - * All known facts must be applied before this can be done in order to avoid inconsistencies. - * Precondition: no contradictions in `facts` - * Postcondition: no atom in `facts` is present in the result - * Postcondition: No clauses have an empty head + * NOTE: empty bodies do not cause a clause to succeed yet. All known facts must be applied before + * this can be done in order to avoid inconsistencies. Precondition: no contradictions in `facts` + * Postcondition: no atom in `facts` is present in the result Postcondition: No clauses have an + * empty head */ def applyAll(cs: Clauses, facts: Set[Literal]): Option[Clauses] = { val newClauses = diff --git a/internal/util-relation/src/main/scala/sbt/internal/util/Relation.scala b/internal/util-relation/src/main/scala/sbt/internal/util/Relation.scala index ce644ac13..0172bf507 100644 --- a/internal/util-relation/src/main/scala/sbt/internal/util/Relation.scala +++ b/internal/util-relation/src/main/scala/sbt/internal/util/Relation.scala @@ -15,17 +15,21 @@ object Relation { def empty[A, B]: Relation[A, B] = make(Map.empty, Map.empty) /** - * Constructs a [[Relation]] from underlying `forward` and `reverse` representations, without checking that they are consistent. - * This is a low-level constructor and the alternatives [[empty]] and [[reconstruct]] should be preferred. + * Constructs a [[Relation]] from underlying `forward` and `reverse` representations, without + * checking that they are consistent. This is a low-level constructor and the alternatives + * [[empty]] and [[reconstruct]] should be preferred. */ def make[A, B](forward: Map[A, Set[B]], reverse: Map[B, Set[A]]): Relation[A, B] = new MRelation(forward, reverse) - /** Constructs a relation such that for every entry `_1 -> _2s` in `forward` and every `_2` in `_2s`, `(_1, _2)` is in the relation. */ + /** + * Constructs a relation such that for every entry `_1 -> _2s` in `forward` and every `_2` in + * `_2s`, `(_1, _2)` is in the relation. + */ def reconstruct[A, B](forward: Map[A, Set[B]]): Relation[A, B] = { val reversePairs = for ((a, bs) <- forward.view; b <- bs.view) yield (b, a) - val reverse = reversePairs.foldLeft(Map.empty[B, Set[A]]) { - case (m, (b, a)) => add(m, b, a :: Nil) + val reverse = reversePairs.foldLeft(Map.empty[B, Set[A]]) { case (m, (b, a)) => + add(m, b, a :: Nil) } make(forward filter { case (a, bs) => bs.nonEmpty }, reverse) } @@ -53,19 +57,17 @@ object Relation { /** when both parameters taken by relation are the same type, switch calls a function on them. */ private[sbt] def switch[X, Y](relation: Relation[X, X], f: X => Y): Relation[Y, Y] = { - val forward = relation.forwardMap.map { - case (first, second) => - f(first) -> second.map(f) + val forward = relation.forwardMap.map { case (first, second) => + f(first) -> second.map(f) } - val reverse = relation.reverseMap.map { - case (first, second) => - f(first) -> second.map(f) + val reverse = relation.reverseMap.map { case (first, second) => + f(first) -> second.map(f) } make(forward, reverse) } } -/** Binary relation between A and B. It is a set of pairs (_1, _2) for _1 in A, _2 in B. */ +/** Binary relation between A and B. It is a set of pairs (_1, _2) for _1 in A, _2 in B. */ trait Relation[A, B] { /** Returns the set of all `_2`s such that `(_1, _2)` is in this relation. */ @@ -113,37 +115,41 @@ trait Relation[A, B] { /** Returns the number of pairs in this relation */ def size: Int - /** Returns true iff `(a,b)` is in this relation*/ + /** Returns true iff `(a,b)` is in this relation */ def contains(a: A, b: B): Boolean - /** Returns a relation with only pairs `(a,b)` for which `f(a,b)` is true.*/ + /** Returns a relation with only pairs `(a,b)` for which `f(a,b)` is true. */ def filter(f: (A, B) => Boolean): Relation[A, B] /** - * Returns a pair of relations: the first contains only pairs `(a,b)` for which `f(a,b)` is true and - * the other only pairs `(a,b)` for which `f(a,b)` is false. + * Returns a pair of relations: the first contains only pairs `(a,b)` for which `f(a,b)` is true + * and the other only pairs `(a,b)` for which `f(a,b)` is false. */ def partition(f: (A, B) => Boolean): (Relation[A, B], Relation[A, B]) /** Partitions this relation into a map of relations according to some discriminator function. */ def groupBy[K](discriminator: ((A, B)) => K): Map[K, Relation[A, B]] - /** Returns all pairs in this relation.*/ + /** Returns all pairs in this relation. */ def all: Traversable[(A, B)] /** - * Represents this relation as a `Map` from a `_1` to the set of `_2`s such that `(_1, _2)` is in this relation. + * Represents this relation as a `Map` from a `_1` to the set of `_2`s such that `(_1, _2)` is in + * this relation. * - * Specifically, there is one entry for each `_1` such that `(_1, _2)` is in this relation for some `_2`. - * The value associated with a given `_1` is the set of all `_2`s such that `(_1, _2)` is in this relation. + * Specifically, there is one entry for each `_1` such that `(_1, _2)` is in this relation for + * some `_2`. The value associated with a given `_1` is the set of all `_2`s such that `(_1, _2)` + * is in this relation. */ def forwardMap: Map[A, Set[B]] /** - * Represents this relation as a `Map` from a `_2` to the set of `_1`s such that `(_1, _2)` is in this relation. + * Represents this relation as a `Map` from a `_2` to the set of `_1`s such that `(_1, _2)` is in + * this relation. * - * Specifically, there is one entry for each `_2` such that `(_1, _2)` is in this relation for some `_1`. - * The value associated with a given `_2` is the set of all `_1`s such that `(_1, _2)` is in this relation. + * Specifically, there is one entry for each `_2` such that `(_1, _2)` is in this relation for + * some `_1`. The value associated with a given `_2` is the set of all `_1`s such that `(_1, _2)` + * is in this relation. */ def reverseMap: Map[B, Set[A]] } diff --git a/internal/util-relation/src/test/scala/RelationTest.scala b/internal/util-relation/src/test/scala/RelationTest.scala index 1ee742d73..912b63696 100644 --- a/internal/util-relation/src/test/scala/RelationTest.scala +++ b/internal/util-relation/src/test/scala/RelationTest.scala @@ -21,12 +21,11 @@ object RelationTest extends Properties("Relation") { r._1s == _1s && r.forwardMap.keySet == _1s && r._2s == _2s && r.reverseMap.keySet == _2s && - pairs.forall { - case (a, b) => - (r.forward(a) contains b) && - (r.reverse(b) contains a) && - (r.forwardMap(a) contains b) && - (r.reverseMap(b) contains a) + pairs.forall { case (a, b) => + (r.forward(a) contains b) && + (r.reverse(b) contains a) && + (r.forwardMap(a) contains b) && + (r.reverseMap(b) contains a) } } @@ -46,12 +45,11 @@ object RelationTest extends Properties("Relation") { ("Forward map does not contain removed" |: !r.forwardMap.contains(rem)) && ("Removed is not a value in reverse map" |: !r.reverseMap.values.toSet.contains(rem)) } && - all(removeFine) { - case (a, b) => - ("Forward does not contain removed" |: (!r.forward(a).contains(b))) && - ("Reverse does not contain removed" |: (!r.reverse(b).contains(a))) && - ("Forward map does not contain removed" |: (notIn(r.forwardMap, a, b))) && - ("Reverse map does not contain removed" |: (notIn(r.reverseMap, b, a))) + all(removeFine) { case (a, b) => + ("Forward does not contain removed" |: (!r.forward(a).contains(b))) && + ("Reverse does not contain removed" |: (!r.reverse(b).contains(a))) && + ("Forward map does not contain removed" |: (notIn(r.forwardMap, a, b))) && + ("Reverse map does not contain removed" |: (notIn(r.reverseMap, b, a))) } } @@ -59,8 +57,8 @@ object RelationTest extends Properties("Relation") { val splitInto = math.abs(randomInt) % 10 + 1 // Split into 1-10 groups. val rel = Relation.empty[Int, Double] ++ entries val grouped = rel groupBy (_._1 % splitInto) - all(grouped.toSeq) { - case (k, rel_k) => rel_k._1s forall { _ % splitInto == k } + all(grouped.toSeq) { case (k, rel_k) => + rel_k._1s forall { _ % splitInto == k } } } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 33941806c..33faf2df9 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -6,8 +6,9 @@ object Dependencies { // WARNING: Please Scala update versions in PluginCross.scala too val scala212 = "2.12.17" val scala213 = "2.13.8" + val scala3 = "3.1.0" val checkPluginCross = settingKey[Unit]("Make sure scalaVersion match up") - val baseScalaVersion = scala212 + val baseScalaVersion = scala3 def nightlyVersion: Option[String] = sys.env.get("BUILD_VERSION") orElse sys.props.get("sbt.build.version") @@ -79,8 +80,11 @@ object Dependencies { val lmCoursierShaded = "io.get-coursier" %% "lm-coursier-shaded" % "2.0.13" - def sjsonNew(n: String) = - Def.setting("com.eed3si9n" %% n % "0.9.1") // contrabandSjsonNewVersion.value + 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" + ) // contrabandSjsonNewVersion.value val sjsonNewScalaJson = sjsonNew("sjson-new-scalajson") val sjsonNewMurmurhash = sjsonNew("sjson-new-murmurhash") @@ -121,7 +125,7 @@ object Dependencies { "org.scala-lang" % "scala-reflect" % scalaVersion.value } ) - val scalaPar = "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.0" + val scalaPar = "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4" // specify all of log4j modules to prevent misalignment def log4jModule = (n: String) => "org.apache.logging.log4j" % n % "2.17.1" diff --git a/project/HouseRulesPlugin.scala b/project/HouseRulesPlugin.scala index f1532dd8c..609c4ade0 100644 --- a/project/HouseRulesPlugin.scala +++ b/project/HouseRulesPlugin.scala @@ -24,14 +24,15 @@ object HouseRulesPlugin extends AutoPlugin { .value .toList, scalacOptions ++= "-Ykind-projector".ifScala3.value.toList, + scalacOptions ++= "-Ysemanticdb".ifScala3.value.toList, scalacOptions ++= "-Yinline-warnings".ifScala211OrMinus.value.toList, scalacOptions ++= "-Yno-adapted-args".ifScala212OrMinus.value.toList, scalacOptions += "-Ywarn-dead-code", scalacOptions += "-Ywarn-numeric-widen", scalacOptions += "-Ywarn-value-discard", scalacOptions ++= "-Ywarn-unused-import".ifScala(v => 11 <= v && v <= 12).value.toList - ) ++ Seq(Compile, Test).flatMap( - c => (c / console / scalacOptions) --= Seq("-Ywarn-unused-import", "-Xlint") + ) ++ Seq(Compile, Test).flatMap(c => + (c / console / scalacOptions) --= Seq("-Ywarn-unused-import", "-Xlint") ) private def scalaPartV = Def setting (CrossVersion partialVersion scalaVersion.value) diff --git a/tasks/src/main/scala/sbt/CompletionService.scala b/tasks/src/main/scala/sbt/CompletionService.scala index f9586a5da..d42d042e0 100644 --- a/tasks/src/main/scala/sbt/CompletionService.scala +++ b/tasks/src/main/scala/sbt/CompletionService.scala @@ -10,14 +10,13 @@ package sbt trait CompletionService[A, R] { /** - * Submits a work node A with work that returns R. - * In Execute this is used for tasks returning sbt.Completed. + * Submits a work node A with work that returns R. In Execute this is used for tasks returning + * sbt.Completed. */ def submit(node: A, work: () => R): Unit /** - * Retrieves and removes the result from the next completed task, - * waiting if none are yet present. + * Retrieves and removes the result from the next completed task, waiting if none are yet present. * In Execute this is used for tasks returning sbt.Completed. */ def take(): R @@ -57,20 +56,21 @@ object CompletionService { () => future.get } private[sbt] def submitFuture[A](work: () => A, completion: JCompletionService[A]): JFuture[A] = { - val future = try completion.submit { - new Callable[A] { - def call = - try { - work() - } catch { - case _: InterruptedException => - throw Incomplete(None, message = Some("cancelled")) - } + val future = + try completion.submit { + new Callable[A] { + def call = + try { + work() + } catch { + case _: InterruptedException => + throw Incomplete(None, message = Some("cancelled")) + } + } + } catch { + case _: RejectedExecutionException => + throw Incomplete(None, message = Some("cancelled")) } - } catch { - case _: RejectedExecutionException => - throw Incomplete(None, message = Some("cancelled")) - } future } def manage[A, T]( diff --git a/tasks/src/main/scala/sbt/ConcurrentRestrictions.scala b/tasks/src/main/scala/sbt/ConcurrentRestrictions.scala index dadb4fa6c..0b6e6fb83 100644 --- a/tasks/src/main/scala/sbt/ConcurrentRestrictions.scala +++ b/tasks/src/main/scala/sbt/ConcurrentRestrictions.scala @@ -17,31 +17,30 @@ import scala.collection.mutable /** * Describes restrictions on concurrent execution for a set of tasks. * - * @tparam A the type of a task + * @tparam A + * the type of a task */ trait ConcurrentRestrictions[A] { /** Internal state type used to describe a set of tasks. */ type G - /** Representation of zero tasks.*/ + /** Representation of zero tasks. */ def empty: G - /** Updates the description `g` to include a new task `a`.*/ + /** Updates the description `g` to include a new task `a`. */ def add(g: G, a: A): G - /** Updates the description `g` to remove a previously added task `a`.*/ + /** Updates the description `g` to remove a previously added task `a`. */ def remove(g: G, a: A): G /** - * Returns true if the tasks described by `g` are allowed to execute concurrently. - * The methods in this class must obey the following laws: + * Returns true if the tasks described by `g` are allowed to execute concurrently. The methods in + * this class must obey the following laws: * - * 1. forall g: G, a: A; valid(g) => valid(remove(g,a)) - * 2. forall a: A; valid(add(empty, a)) - * 3. forall g: G, a: A; valid(g) <=> valid(remove(add(g, a), a)) - * 4. (implied by 1,2,3) valid(empty) - * 5. forall g: G, a: A, b: A; !valid(add(g,a)) => !valid(add(add(g,b), a)) + * 1. forall g: G, a: A; valid(g) => valid(remove(g,a)) 2. forall a: A; valid(add(empty, a)) 3. + * forall g: G, a: A; valid(g) <=> valid(remove(add(g, a), a)) 4. (implied by 1,2,3) + * valid(empty) 5. forall g: G, a: A, b: A; !valid(add(g,a)) => !valid(add(add(g,b), a)) */ def valid(g: G): Boolean } @@ -69,7 +68,8 @@ object ConcurrentRestrictions { /** * A ConcurrentRestrictions instance that places no restrictions on concurrently executing tasks. - * @param zero the constant placeholder used for t + * @param zero + * the constant placeholder used for t */ def unrestricted[A]: ConcurrentRestrictions[A] = new ConcurrentRestrictions[A] { @@ -91,13 +91,13 @@ object ConcurrentRestrictions { } } - /** A key object used for associating information with a task.*/ + /** A key object used for associating information with a task. */ final case class Tag(name: String) val tagsKey = AttributeKey[TagMap]("tags", "Attributes restricting concurrent execution of tasks.") - /** A standard tag describing the number of tasks that do not otherwise have any tags.*/ + /** A standard tag describing the number of tasks that do not otherwise have any tags. */ val Untagged = Tag("untagged") /** A standard tag describing the total number of tasks. */ @@ -108,9 +108,12 @@ object ConcurrentRestrictions { /** * Implements concurrency restrictions on tasks based on Tags. - * @tparam A type of a task - * @param get extracts tags from a task - * @param validF defines whether a set of tasks are allowed to execute concurrently based on their merged tags + * @tparam A + * type of a task + * @param get + * extracts tags from a task + * @param validF + * defines whether a set of tasks are allowed to execute concurrently based on their merged tags */ def tagged[A](get: A => TagMap, validF: TagMap => Boolean): ConcurrentRestrictions[A] = new ConcurrentRestrictions[A] { @@ -142,10 +145,14 @@ object ConcurrentRestrictions { private[this] val poolID = new AtomicInteger(1) /** - * Constructs a CompletionService suitable for backing task execution based on the provided restrictions on concurrent task execution. - * @return a pair, with _1 being the CompletionService and _2 a function to shutdown the service. - * @tparam A the task type - * @tparam R the type of data that will be computed by the CompletionService. + * Constructs a CompletionService suitable for backing task execution based on the provided + * restrictions on concurrent task execution. + * @return + * a pair, with _1 being the CompletionService and _2 a function to shutdown the service. + * @tparam A + * the task type + * @tparam R + * the type of data that will be computed by the CompletionService. */ def completionService[A, R]( tags: ConcurrentRestrictions[A], @@ -167,10 +174,13 @@ object ConcurrentRestrictions { ): (CompletionService[A, R], () => Unit) = { val pool = Executors.newCachedThreadPool() val service = completionService[A, R](pool, tags, warn, isSentinel) - (service, () => { - pool.shutdownNow() - () - }) + ( + service, + () => { + pool.shutdownNow() + () + } + ) } def cancellableCompletionService[A, R]( @@ -180,11 +190,14 @@ object ConcurrentRestrictions { ): (CompletionService[A, R], Boolean => Unit) = { val pool = Executors.newCachedThreadPool() val service = completionService[A, R](pool, tags, warn, isSentinel) - (service, force => { - if (force) service.close() - pool.shutdownNow() - () - }) + ( + service, + force => { + if (force) service.close() + pool.shutdownNow() + () + } + ) } def completionService[A, R]( @@ -196,8 +209,9 @@ object ConcurrentRestrictions { } /** - * Constructs a CompletionService suitable for backing task execution based on the provided restrictions on concurrent task execution - * and using the provided Executor to manage execution on threads. + * Constructs a CompletionService suitable for backing task execution based on the provided + * restrictions on concurrent task execution and using the provided Executor to manage execution + * on threads. */ def completionService[A, R]( backing: Executor, @@ -220,13 +234,16 @@ object ConcurrentRestrictions { /** Backing service used to manage execution on threads once all constraints are satisfied. */ private[this] val jservice = new ExecutorCompletionService[R](backing) - /** The description of the currently running tasks, used by `tags` to manage restrictions.*/ + /** The description of the currently running tasks, used by `tags` to manage restrictions. */ private[this] var tagState = tags.empty /** The number of running tasks. */ private[this] var running = 0 - /** Tasks that cannot be run yet because they cannot execute concurrently with the currently running tasks.*/ + /** + * Tasks that cannot be run yet because they cannot execute concurrently with the currently + * running tasks. + */ private[this] val pending = new LinkedList[Enqueue] private[this] val sentinels: mutable.ListBuffer[JFuture[_]] = mutable.ListBuffer.empty diff --git a/tasks/src/main/scala/sbt/Execute.scala b/tasks/src/main/scala/sbt/Execute.scala index de2100154..8474b8778 100644 --- a/tasks/src/main/scala/sbt/Execute.scala +++ b/tasks/src/main/scala/sbt/Execute.scala @@ -65,12 +65,11 @@ private[sbt] final class Execute[F[_] <: AnyRef]( private[this] val viewCache = pMap[F, Node[F, *]] private[this] val results = pMap[F, Result] - private[this] val getResult: F ~> Result = λ[F ~> Result]( - a => - view.inline(a) match { - case Some(v) => Value(v()) - case None => results(a) - } + private[this] val getResult: F ~> Result = λ[F ~> Result](a => + view.inline(a) match { + case Some(v) => Value(v()) + case None => results(a) + } ) private[this] type State = State.Value private[this] object State extends Enumeration { @@ -149,8 +148,7 @@ private[sbt] final class Execute[F[_] <: AnyRef]( } post { - if (done(target)) - assert(done(node)) + if (done(target)) assert(done(node)) else { assert(calling(node)) assert(callers(target) contains node) @@ -203,9 +201,9 @@ private[sbt] final class Execute[F[_] <: AnyRef]( } /** - * Ensures the given node has been added to the system. - * Once added, a node is pending until its inputs and dependencies have completed. - * Its computation is then evaluated and made available for nodes that have it as an input. + * Ensures the given node has been added to the system. Once added, a node is pending until its + * inputs and dependencies have completed. Its computation is then evaluated and made available + * for nodes that have it as an input. */ def addChecked[A](node: F[A])(implicit strategy: Strategy): Unit = { if (!added(node)) addNew(node) @@ -214,9 +212,9 @@ private[sbt] final class Execute[F[_] <: AnyRef]( } /** - * Adds a node that has not yet been registered with the system. - * If all of the node's dependencies have finished, the node's computation is scheduled to run. - * The node's dependencies will be added (transitively) if they are not already registered. + * Adds a node that has not yet been registered with the system. If all of the node's dependencies + * have finished, the node's computation is scheduled to run. The node's dependencies will be + * added (transitively) if they are not already registered. */ def addNew[A](node: F[A])(implicit strategy: Strategy): Unit = { pre { newPre(node) } @@ -231,8 +229,7 @@ private[sbt] final class Execute[F[_] <: AnyRef]( /* active is mutable, so take a snapshot */ ) - if (active.isEmpty) - ready(node) + if (active.isEmpty) ready(node) else { forward(node) = active for (a <- active) { @@ -249,7 +246,10 @@ private[sbt] final class Execute[F[_] <: AnyRef]( } } - /** Called when a pending 'node' becomes runnable. All of its dependencies must be done. This schedules the node's computation with 'strategy'.*/ + /** + * Called when a pending 'node' becomes runnable. All of its dependencies must be done. This + * schedules the node's computation with 'strategy'. + */ def ready[A](node: F[A])(implicit strategy: Strategy): Unit = { pre { assert(pending(node)) @@ -283,8 +283,8 @@ private[sbt] final class Execute[F[_] <: AnyRef]( } /** - * Evaluates the computation 'f' for 'node'. - * This returns a Completed instance, which contains the post-processing to perform after the result is retrieved from the Strategy. + * Evaluates the computation 'f' for 'node'. This returns a Completed instance, which contains the + * post-processing to perform after the result is retrieved from the Strategy. */ def work[A](node: F[A], f: => Either[F[A], A])(implicit strategy: Strategy): Completed = { progress.beforeWork(node) diff --git a/tasks/src/main/scala/sbt/ExecuteProgress.scala b/tasks/src/main/scala/sbt/ExecuteProgress.scala index e52b743fd..c05b3d113 100644 --- a/tasks/src/main/scala/sbt/ExecuteProgress.scala +++ b/tasks/src/main/scala/sbt/ExecuteProgress.scala @@ -10,48 +10,46 @@ package sbt import sbt.internal.util.RMap /** - * Processes progress events during task execution. - * All methods are called from the same thread except `started` and `finished`, - * which is called from the executing task's thread. - * All methods should return quickly to avoid task execution overhead. + * Processes progress events during task execution. All methods are called from the same thread + * except `started` and `finished`, which is called from the executing task's thread. All methods + * should return quickly to avoid task execution overhead. */ trait ExecuteProgress[F[_]] { def initial(): Unit /** - * Notifies that a `task` has been registered in the system for execution. - * The dependencies of `task` are `allDeps` and the subset of those dependencies that - * have not completed are `pendingDeps`. + * Notifies that a `task` has been registered in the system for execution. The dependencies of + * `task` are `allDeps` and the subset of those dependencies that have not completed are + * `pendingDeps`. */ def afterRegistered(task: F[_], allDeps: Iterable[F[_]], pendingDeps: Iterable[F[_]]): Unit /** - * Notifies that all of the dependencies of `task` have completed and `task` is therefore - * ready to run. The task has not been scheduled on a thread yet. + * Notifies that all of the dependencies of `task` have completed and `task` is therefore ready to + * run. The task has not been scheduled on a thread yet. */ def afterReady(task: F[_]): Unit /** - * Notifies that the work for `task` is starting after this call returns. - * This is called from the thread the task executes on, unlike most other methods in this callback. - * It is called immediately before the task's work starts with minimal intervening executor overhead. + * Notifies that the work for `task` is starting after this call returns. This is called from the + * thread the task executes on, unlike most other methods in this callback. It is called + * immediately before the task's work starts with minimal intervening executor overhead. */ def beforeWork(task: F[_]): Unit /** - * Notifies that the work for `task` work has finished. The task may have computed the next task to - * run, in which case `result` contains that next task wrapped in Left. If the task produced a value - * or terminated abnormally, `result` provides that outcome wrapped in Right. The ultimate result of - * a task is provided to the `completed` method. - * This is called from the thread the task executes on, unlike most other methods in this callback. - * It is immediately called after the task's work is complete with minimal intervening executor overhead. + * Notifies that the work for `task` work has finished. The task may have computed the next task + * to run, in which case `result` contains that next task wrapped in Left. If the task produced a + * value or terminated abnormally, `result` provides that outcome wrapped in Right. The ultimate + * result of a task is provided to the `completed` method. This is called from the thread the task + * executes on, unlike most other methods in this callback. It is immediately called after the + * task's work is complete with minimal intervening executor overhead. */ def afterWork[A](task: F[A], result: Either[F[A], Result[A]]): Unit /** - * Notifies that `task` has completed. - * The task's work is done with a final `result`. - * Any tasks called by `task` have completed. + * Notifies that `task` has completed. The task's work is done with a final `result`. Any tasks + * called by `task` have completed. */ def afterCompleted[A](task: F[A], result: Result[A]): Unit @@ -62,7 +60,9 @@ trait ExecuteProgress[F[_]] { def stop(): Unit } -/** This module is experimental and subject to binary and source incompatible changes at any time. */ +/** + * This module is experimental and subject to binary and source incompatible changes at any time. + */ object ExecuteProgress { def empty[F[_]]: ExecuteProgress[F] = new ExecuteProgress[F] { override def initial(): Unit = () diff --git a/tasks/src/main/scala/sbt/Incomplete.scala b/tasks/src/main/scala/sbt/Incomplete.scala index 59232f24a..1cbbec4a2 100644 --- a/tasks/src/main/scala/sbt/Incomplete.scala +++ b/tasks/src/main/scala/sbt/Incomplete.scala @@ -15,11 +15,17 @@ import Incomplete.{ Error, Value => IValue } /** * Describes why a task did not complete. * - * @param node the task that did not complete that is described by this Incomplete instance - * @param tpe whether the task was incomplete because of an error or because it was skipped. Only Error is actually used and Skipped may be removed in the future. - * @param message an optional error message describing this incompletion - * @param causes a list of incompletions that prevented `node` from completing - * @param directCause the exception that caused `node` to not complete + * @param node + * the task that did not complete that is described by this Incomplete instance + * @param tpe + * whether the task was incomplete because of an error or because it was skipped. Only Error is + * actually used and Skipped may be removed in the future. + * @param message + * an optional error message describing this incompletion + * @param causes + * a list of incompletions that prevented `node` from completing + * @param directCause + * the exception that caused `node` to not complete */ final case class Incomplete( node: Option[AnyRef], diff --git a/tasks/src/main/scala/sbt/Node.scala b/tasks/src/main/scala/sbt/Node.scala index fac5cff58..3baba7be1 100644 --- a/tasks/src/main/scala/sbt/Node.scala +++ b/tasks/src/main/scala/sbt/Node.scala @@ -12,8 +12,10 @@ import sbt.internal.util.AList /** * Represents a task node in a format understood by the task evaluation engine Execute. * - * @tparam A the task type constructor - * @tparam T the type computed by this node + * @tparam A + * the task type constructor + * @tparam T + * the type computed by this node */ trait Node[A[_], T] { type K[L[x]] diff --git a/tasks/src/main/scala/sbt/Result.scala b/tasks/src/main/scala/sbt/Result.scala index 973e9d559..e608786a8 100644 --- a/tasks/src/main/scala/sbt/Result.scala +++ b/tasks/src/main/scala/sbt/Result.scala @@ -11,17 +11,17 @@ import sbt.internal.util.~> // used instead of Either[Incomplete, T] for type inference -/** Result of completely evaluating a task.*/ +/** Result of completely evaluating a task. */ sealed trait Result[+T] { def toEither: Either[Incomplete, T] } -/** Indicates the task did not complete normally and so it does not have a value.*/ +/** Indicates the task did not complete normally and so it does not have a value. */ final case class Inc(cause: Incomplete) extends Result[Nothing] { def toEither: Either[Incomplete, Nothing] = Left(cause) } -/** Indicates the task completed normally and produced the given `value`.*/ +/** Indicates the task completed normally and produced the given `value`. */ final case class Value[+T](value: T) extends Result[T] { def toEither: Either[Incomplete, T] = Right(value) } diff --git a/internal/util-collection/NOTICE b/util-collection/NOTICE similarity index 100% rename from internal/util-collection/NOTICE rename to util-collection/NOTICE diff --git a/internal/util-collection/src/main/scala-2.12/sbt/internal/util/Par.scala b/util-collection/src/main/scala-2.12/sbt/internal/util/Par.scala similarity index 100% rename from internal/util-collection/src/main/scala-2.12/sbt/internal/util/Par.scala rename to util-collection/src/main/scala-2.12/sbt/internal/util/Par.scala diff --git a/internal/util-collection/src/main/scala-2.12/sbt/internal/util/WrappedMap.scala b/util-collection/src/main/scala-2.12/sbt/internal/util/WrappedMap.scala similarity index 100% rename from internal/util-collection/src/main/scala-2.12/sbt/internal/util/WrappedMap.scala rename to util-collection/src/main/scala-2.12/sbt/internal/util/WrappedMap.scala diff --git a/internal/util-collection/src/main/scala-2.13/sbt/internal/util/Par.scala b/util-collection/src/main/scala-2.13/sbt/internal/util/Par.scala similarity index 100% rename from internal/util-collection/src/main/scala-2.13/sbt/internal/util/Par.scala rename to util-collection/src/main/scala-2.13/sbt/internal/util/Par.scala diff --git a/internal/util-collection/src/main/scala-2.13/sbt/internal/util/WrappedMap.scala b/util-collection/src/main/scala-2.13/sbt/internal/util/WrappedMap.scala similarity index 100% rename from internal/util-collection/src/main/scala-2.13/sbt/internal/util/WrappedMap.scala rename to util-collection/src/main/scala-2.13/sbt/internal/util/WrappedMap.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/AList.scala b/util-collection/src/main/scala-2/sbt/internal/util/AList.scala similarity index 100% rename from internal/util-collection/src/main/scala/sbt/internal/util/AList.scala rename to util-collection/src/main/scala-2/sbt/internal/util/AList.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/HList.scala b/util-collection/src/main/scala-2/sbt/internal/util/HList.scala similarity index 100% rename from internal/util-collection/src/main/scala/sbt/internal/util/HList.scala rename to util-collection/src/main/scala-2/sbt/internal/util/HList.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/HListFormats.scala b/util-collection/src/main/scala-2/sbt/internal/util/HListFormats.scala similarity index 100% rename from internal/util-collection/src/main/scala/sbt/internal/util/HListFormats.scala rename to util-collection/src/main/scala-2/sbt/internal/util/HListFormats.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/INode.scala b/util-collection/src/main/scala-2/sbt/internal/util/INode.scala similarity index 99% rename from internal/util-collection/src/main/scala/sbt/internal/util/INode.scala rename to util-collection/src/main/scala-2/sbt/internal/util/INode.scala index 3d7c86646..a10a52870 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/INode.scala +++ b/util-collection/src/main/scala-2/sbt/internal/util/INode.scala @@ -16,6 +16,7 @@ object EvaluationState extends Enumeration { val New, Blocked, Ready, Calling, Evaluated = Value } +/* abstract class EvaluateSettings[ScopeType] { protected val init: Init[ScopeType] import init._ @@ -228,3 +229,4 @@ abstract class EvaluateSettings[ScopeType] { protected def evaluate0(): Unit = setValue(f(alist.transform(in, getValue))) } } + */ diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/KList.scala b/util-collection/src/main/scala-2/sbt/internal/util/KList.scala similarity index 100% rename from internal/util-collection/src/main/scala/sbt/internal/util/KList.scala rename to util-collection/src/main/scala-2/sbt/internal/util/KList.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/PMap.scala b/util-collection/src/main/scala-2/sbt/internal/util/PMap.scala similarity index 100% rename from internal/util-collection/src/main/scala/sbt/internal/util/PMap.scala rename to util-collection/src/main/scala-2/sbt/internal/util/PMap.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Settings.scala b/util-collection/src/main/scala-2/sbt/internal/util/Settings.scala similarity index 100% rename from internal/util-collection/src/main/scala/sbt/internal/util/Settings.scala rename to util-collection/src/main/scala-2/sbt/internal/util/Settings.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala b/util-collection/src/main/scala/sbt/internal/util/Attributes.scala similarity index 76% rename from internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala rename to util-collection/src/main/scala/sbt/internal/util/Attributes.scala index 0c1d2cf2c..bbe44e300 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala +++ b/util-collection/src/main/scala/sbt/internal/util/Attributes.scala @@ -16,8 +16,8 @@ import sbt.util.OptJsonWriter // a single AttributeKey instance cannot conform to AttributeKey[T] for different Ts /** - * A key in an [[AttributeMap]] that constrains its associated value to be of type `T`. - * The key is uniquely defined by its `label` and type `T`, represented at runtime by `manifest`. + * A key in an [[AttributeMap]] that constrains its associated value to be of type `T`. The key is + * uniquely defined by its `label` and type `T`, represented at runtime by `manifest`. */ sealed trait AttributeKey[T] { @@ -32,18 +32,19 @@ sealed trait AttributeKey[T] { /** * In environments that support delegation, looking up this key when it has no associated value - * will delegate to the values associated with these keys. - * The delegation proceeds in order the keys are returned here. + * will delegate to the values associated with these keys. The delegation proceeds in order the + * keys are returned here. */ def extend: Seq[AttributeKey[_]] /** - * Specifies whether this key is a local, anonymous key (`true`) or not (`false`). - * This is typically only used for programmatic, intermediate keys that should not be referenced outside of a specific scope. + * Specifies whether this key is a local, anonymous key (`true`) or not (`false`). This is + * typically only used for programmatic, intermediate keys that should not be referenced outside + * of a specific scope. */ def isLocal: Boolean - /** Identifies the relative importance of a key among other keys.*/ + /** Identifies the relative importance of a key among other keys. */ def rank: Int def optJsonWriter: OptJsonWriter[T] @@ -133,60 +134,73 @@ object AttributeKey { } /** - * An immutable map where a key is the tuple `(String,T)` for a fixed type `T` and can only be associated with values of type `T`. - * It is therefore possible for this map to contain mappings for keys with the same label but different types. - * Excluding this possibility is the responsibility of the client if desired. + * An immutable map where a key is the tuple `(String,T)` for a fixed type `T` and can only be + * associated with values of type `T`. It is therefore possible for this map to contain mappings for + * keys with the same label but different types. Excluding this possibility is the responsibility of + * the client if desired. */ trait AttributeMap { /** - * Gets the value of type `T` associated with the key `k`. - * If a key with the same label but different type is defined, this method will fail. + * Gets the value of type `T` associated with the key `k`. If a key with the same label but + * different type is defined, this method will fail. */ def apply[T](k: AttributeKey[T]): T /** - * Gets the value of type `T` associated with the key `k` or `None` if no value is associated. - * If a key with the same label but a different type is defined, this method will return `None`. + * Gets the value of type `T` associated with the key `k` or `None` if no value is associated. If + * a key with the same label but a different type is defined, this method will return `None`. */ def get[T](k: AttributeKey[T]): Option[T] /** - * Returns this map without the mapping for `k`. - * This method will not remove a mapping for a key with the same label but a different type. + * Returns this map without the mapping for `k`. This method will not remove a mapping for a key + * with the same label but a different type. */ def remove[T](k: AttributeKey[T]): AttributeMap /** - * Returns true if this map contains a mapping for `k`. - * If a key with the same label but a different type is defined in this map, this method will return `false`. + * Returns true if this map contains a mapping for `k`. If a key with the same label but a + * different type is defined in this map, this method will return `false`. */ def contains[T](k: AttributeKey[T]): Boolean /** - * Adds the mapping `k -> value` to this map, replacing any existing mapping for `k`. - * Any mappings for keys with the same label but different types are unaffected. + * Adds the mapping `k -> value` to this map, replacing any existing mapping for `k`. Any mappings + * for keys with the same label but different types are unaffected. */ def put[T](k: AttributeKey[T], value: T): AttributeMap - /** All keys with defined mappings. There may be multiple keys with the same `label`, but different types. */ + /** + * All keys with defined mappings. There may be multiple keys with the same `label`, but different + * types. + */ def keys: Iterable[AttributeKey[_]] - /** Adds the mappings in `o` to this map, with mappings in `o` taking precedence over existing mappings.*/ + /** + * Adds the mappings in `o` to this map, with mappings in `o` taking precedence over existing + * mappings. + */ def ++(o: Iterable[AttributeEntry[_]]): AttributeMap - /** Combines the mappings in `o` with the mappings in this map, with mappings in `o` taking precedence over existing mappings.*/ + /** + * Combines the mappings in `o` with the mappings in this map, with mappings in `o` taking + * precedence over existing mappings. + */ def ++(o: AttributeMap): AttributeMap - /** All mappings in this map. The [[AttributeEntry]] type preserves the typesafety of mappings, although the specific types are unknown.*/ + /** + * All mappings in this map. The [[AttributeEntry]] type preserves the typesafety of mappings, + * although the specific types are unknown. + */ def entries: Iterable[AttributeEntry[_]] /** `true` if there are no mappings in this map, `false` if there are. */ def isEmpty: Boolean /** - * Adds the mapping `k -> opt.get` if opt is Some. - * Otherwise, it returns this map without the mapping for `k`. + * Adds the mapping `k -> opt.get` if opt is Some. Otherwise, it returns this map without the + * mapping for `k`. */ private[sbt] def setCond[T](k: AttributeKey[T], opt: Option[T]): AttributeMap } @@ -199,11 +213,11 @@ object AttributeMap { /** Constructs an [[AttributeMap]] containing the given `entries`. */ def apply(entries: Iterable[AttributeEntry[_]]): AttributeMap = empty ++ entries - /** Constructs an [[AttributeMap]] containing the given `entries`.*/ + /** Constructs an [[AttributeMap]] containing the given `entries`. */ def apply(entries: AttributeEntry[_]*): AttributeMap = empty ++ entries /** Presents an `AttributeMap` as a natural transformation. */ - implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = λ[AttributeKey ~> Id](map(_)) + // implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = λ[AttributeKey ~> Id](map(_)) } private class BasicAttributeMap(private val backing: Map[AttributeKey[_], Any]) @@ -230,8 +244,8 @@ private class BasicAttributeMap(private val backing: Map[AttributeKey[_], Any]) } def entries: Iterable[AttributeEntry[_]] = - backing.collect { - case (k: AttributeKey[kt], v) => AttributeEntry(k, v.asInstanceOf[kt]) + backing.collect { case (k: AttributeKey[kt], v) => + AttributeEntry(k, v.asInstanceOf[kt]) } private[sbt] def setCond[T](k: AttributeKey[T], opt: Option[T]): AttributeMap = @@ -269,7 +283,7 @@ object Attributed { /** Extracts the underlying data from the sequence `in`. */ def data[T](in: Seq[Attributed[T]]): Seq[T] = in.map(_.data) - /** Associates empty metadata maps with each entry of `in`.*/ + /** Associates empty metadata maps with each entry of `in`. */ def blankSeq[T](in: Seq[T]): Seq[Attributed[T]] = in map blank /** Associates an empty metadata map with `data`. */ diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Dag.scala b/util-collection/src/main/scala/sbt/internal/util/Dag.scala similarity index 90% rename from internal/util-collection/src/main/scala/sbt/internal/util/Dag.scala rename to util-collection/src/main/scala/sbt/internal/util/Dag.scala index f5f584290..ed3854a6b 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Dag.scala +++ b/util-collection/src/main/scala/sbt/internal/util/Dag.scala @@ -83,8 +83,8 @@ object Dag { private[sbt] trait DirectedSignedGraph[Node] { /** - * Directed edge type that tracks the sign and target (head) vertex. - * The sign can be obtained via [[isNegative]] and the target vertex via [[head]]. + * Directed edge type that tracks the sign and target (head) vertex. The sign can be obtained + * via [[isNegative]] and the target vertex via [[head]]. */ type Arrow @@ -103,10 +103,10 @@ object Dag { } /** - * Traverses a directed graph defined by `graph` looking for a cycle that includes a "negative" edge. - * The directed edges are weighted by the caller as "positive" or "negative". - * If a cycle containing a "negative" edge is detected, its member edges are returned in order. - * Otherwise, the empty list is returned. + * Traverses a directed graph defined by `graph` looking for a cycle that includes a "negative" + * edge. The directed edges are weighted by the caller as "positive" or "negative". If a cycle + * containing a "negative" edge is detected, its member edges are returned in order. Otherwise, + * the empty list is returned. */ private[sbt] def findNegativeCycle[Node](graph: DirectedSignedGraph[Node]): List[graph.Arrow] = { import graph._ @@ -132,8 +132,7 @@ object Dag { between else visit(tail, stack) - } else - visit(tail, stack) + } else visit(tail, stack) } visit(graph.nodes, Nil) diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/IDSet.scala b/util-collection/src/main/scala/sbt/internal/util/IDSet.scala similarity index 98% rename from internal/util-collection/src/main/scala/sbt/internal/util/IDSet.scala rename to util-collection/src/main/scala/sbt/internal/util/IDSet.scala index b3cacdfe1..e0ad1e616 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/IDSet.scala +++ b/util-collection/src/main/scala/sbt/internal/util/IDSet.scala @@ -9,7 +9,7 @@ package sbt.internal.util import scala.collection.JavaConverters._ -/** A mutable set interface that uses object identity to test for set membership.*/ +/** A mutable set interface that uses object identity to test for set membership. */ trait IDSet[T] { def apply(t: T): Boolean def contains(t: T): Boolean diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Signal.scala b/util-collection/src/main/scala/sbt/internal/util/Signal.scala similarity index 93% rename from internal/util-collection/src/main/scala/sbt/internal/util/Signal.scala rename to util-collection/src/main/scala/sbt/internal/util/Signal.scala index b0e862410..13442c9ec 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Signal.scala +++ b/util-collection/src/main/scala/sbt/internal/util/Signal.scala @@ -32,8 +32,8 @@ object Signals { } /** - * Register a signal handler that can be removed later. - * NOTE: Does not stack with other signal handlers!!!! + * Register a signal handler that can be removed later. NOTE: Does not stack with other signal + * handlers!!!! */ def register(handler: () => Unit, signal: String = INT): Registration = // TODO - Maybe we can just ignore things if not is-supported. @@ -90,7 +90,8 @@ private final class Signals0 { val oldHandler = Signal.handle(intSignal, newHandler) try Right(action()) - catch { case e: LinkageError => Left(e) } finally { + catch { case e: LinkageError => Left(e) } + finally { Signal.handle(intSignal, oldHandler); () } } diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/TypeFunctions.scala b/util-collection/src/main/scala/sbt/internal/util/TypeFunctions.scala similarity index 99% rename from internal/util-collection/src/main/scala/sbt/internal/util/TypeFunctions.scala rename to util-collection/src/main/scala/sbt/internal/util/TypeFunctions.scala index 5d11c57fb..faee1aaec 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/TypeFunctions.scala +++ b/util-collection/src/main/scala/sbt/internal/util/TypeFunctions.scala @@ -7,6 +7,7 @@ package sbt.internal.util +/* trait TypeFunctions { import TypeFunctions._ type Id[X] = X @@ -54,7 +55,9 @@ object TypeFunctions extends TypeFunctions { } } } + */ +/* trait ~>[-A[_], +B[_]] { outer => def apply[T](a: A[T]): B[T] // directly on ~> because of type inference limitations @@ -68,3 +71,4 @@ object ~> { val Id: Id ~> Id = idK[Id] implicit def tcIdEquals: Id ~> Id = Id } + */ diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Types.scala b/util-collection/src/main/scala/sbt/internal/util/Types.scala similarity index 61% rename from internal/util-collection/src/main/scala/sbt/internal/util/Types.scala rename to util-collection/src/main/scala/sbt/internal/util/Types.scala index e07b6bd9f..4d01d963e 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Types.scala +++ b/util-collection/src/main/scala/sbt/internal/util/Types.scala @@ -9,8 +9,8 @@ package sbt.internal.util object Types extends Types -trait Types extends TypeFunctions { - val :^: = KCons - type :+:[H, T <: HList] = HCons[H, T] - val :+: = HCons +trait Types /* extends TypeFunctions */ { + // val :^: = KCons + // type :+:[H, T <: HList] = HCons[H, T] + // val :+: = HCons } diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Util.scala b/util-collection/src/main/scala/sbt/internal/util/Util.scala similarity index 87% rename from internal/util-collection/src/main/scala/sbt/internal/util/Util.scala rename to util-collection/src/main/scala/sbt/internal/util/Util.scala index ca03ed381..1f03c0258 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Util.scala +++ b/util-collection/src/main/scala/sbt/internal/util/Util.scala @@ -15,8 +15,8 @@ import scala.language.experimental.macros object Util { def makeList[T](size: Int, value: T): List[T] = List.fill(size)(value) - def separateE[A, B](ps: Seq[Either[A, B]]): (Seq[A], Seq[B]) = - separate(ps)(Types.idFun) + // def separateE[A, B](ps: Seq[Either[A, B]]): (Seq[A], Seq[B]) = + // separate(ps)(Types.idFun) def separate[T, A, B](ps: Seq[T])(f: T => Either[A, B]): (Seq[A], Seq[B]) = { val (a, b) = ps.foldLeft((Nil: Seq[A], Nil: Seq[B]))((xs, y) => prependEither(xs, f(y))) @@ -45,7 +45,7 @@ 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[T](f: => T): Unit = macro Macro.ignore lazy val isMac: Boolean = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("mac") @@ -73,7 +73,7 @@ object Util { implicit class AnyOps[A](private val value: A) extends AnyVal { def some: Option[A] = (Some(value): Option[A]) } - class Macro(val c: blackbox.Context) { - def ignore(f: c.Tree): c.Expr[Unit] = c.universe.reify({ c.Expr[Any](f).splice; () }) - } + // class Macro(val c: blackbox.Context) { + // def ignore(f: c.Tree): c.Expr[Unit] = c.universe.reify({ c.Expr[Any](f).splice; () }) + // } } diff --git a/util-collection/src/main/scala/sbt/util/Applicative.scala b/util-collection/src/main/scala/sbt/util/Applicative.scala new file mode 100644 index 000000000..39752157a --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/Applicative.scala @@ -0,0 +1,19 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +trait Applicative[F[_]] extends Apply[F]: + def pure[A](x: A): F[A] + + override def map[A, B](fa: F[A])(f: A => B): F[B] = + ap(pure(f))(fa) +end Applicative + +object Applicative: + given Applicative[Option] = OptionInstances.optionMonad +end Applicative diff --git a/util-collection/src/main/scala/sbt/util/Apply.scala b/util-collection/src/main/scala/sbt/util/Apply.scala new file mode 100644 index 000000000..ea5ec6ccf --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/Apply.scala @@ -0,0 +1,19 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +trait Apply[F[_]] extends Functor[F]: + def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] + + def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] = + ap(map(fa)(a => (b: B) => (a, b)))(fb) +end Apply + +object Apply: + given Apply[Option] = OptionInstances.optionMonad +end Apply diff --git a/util-collection/src/main/scala/sbt/util/FlatMap.scala b/util-collection/src/main/scala/sbt/util/FlatMap.scala new file mode 100644 index 000000000..9e644b403 --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/FlatMap.scala @@ -0,0 +1,22 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +import scala.annotation.implicitNotFound + +@implicitNotFound("Could not find an instance of FlatMap for ${F}") +trait FlatMap[F[_]] extends Apply[F]: + def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] + + def flatten[A](ffa: F[F[A]]): F[A] = + flatMap(ffa)(fa => fa) +end FlatMap + +object FlatMap: + given FlatMap[Option] = OptionInstances.optionMonad +end FlatMap diff --git a/util-collection/src/main/scala/sbt/util/Functor.scala b/util-collection/src/main/scala/sbt/util/Functor.scala new file mode 100644 index 000000000..983954f02 --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/Functor.scala @@ -0,0 +1,16 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +trait Functor[F[_]]: + def map[A, B](fa: F[A])(f: A => B): F[B] +end Functor + +object Functor: + given Functor[Option] = OptionInstances.optionMonad +end Functor diff --git a/util-collection/src/main/scala/sbt/util/ListInstances.scala b/util-collection/src/main/scala/sbt/util/ListInstances.scala new file mode 100644 index 000000000..32c6904d5 --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/ListInstances.scala @@ -0,0 +1,23 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +private[sbt] object ListInstances: + lazy val listMonad: Monad[List] = + new Monad[List]: + def pure[A](x: A): List[A] = List(x) + def ap[A, B](ff: List[A => B])(fa: List[A]): List[B] = + for + f <- ff + a <- fa + yield f(a) + def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f) + + override def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) + override def flatten[A](ffa: List[List[A]]): List[A] = ffa.flatten +end ListInstances diff --git a/util-collection/src/main/scala/sbt/util/Monad.scala b/util-collection/src/main/scala/sbt/util/Monad.scala new file mode 100644 index 000000000..64403e368 --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/Monad.scala @@ -0,0 +1,19 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +import scala.annotation.implicitNotFound + +@implicitNotFound("Could not find an instance of Monad for ${F}") +trait Monad[F[_]] extends FlatMap[F] with Applicative[F]: +// +end Monad + +object Monad: + given Monad[Option] = OptionInstances.optionMonad +end Monad diff --git a/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala b/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala similarity index 100% rename from internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala rename to util-collection/src/main/scala/sbt/util/OptJsonWriter.scala diff --git a/util-collection/src/main/scala/sbt/util/OptionInstances.scala b/util-collection/src/main/scala/sbt/util/OptionInstances.scala new file mode 100644 index 000000000..3dadfff95 --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/OptionInstances.scala @@ -0,0 +1,21 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +private[sbt] object OptionInstances: + lazy val optionMonad: Monad[Option] = + new Monad[Option]: + def pure[A](x: A): Option[A] = Some(x) + def ap[A, B](ff: Option[A => B])(fa: Option[A]): Option[B] = + if ff.isDefined && fa.isDefined then Some(ff.get(fa.get)) + else None + def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f) + + override def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f) + override def flatten[A](ffa: Option[Option[A]]): Option[A] = ffa.flatten +end OptionInstances diff --git a/util-collection/src/main/scala/sbt/util/Selective.scala b/util-collection/src/main/scala/sbt/util/Selective.scala new file mode 100644 index 000000000..64f7ae983 --- /dev/null +++ b/util-collection/src/main/scala/sbt/util/Selective.scala @@ -0,0 +1,12 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.util + +trait Selective[F[_]] extends Applicative[F]: + def select[A, B](fab: F[Either[A, B]])(fn: F[A => B]): F[B] +end Selective diff --git a/internal/util-collection/src/main/scala/sbt/util/Show.scala b/util-collection/src/main/scala/sbt/util/Show.scala similarity index 85% rename from internal/util-collection/src/main/scala/sbt/util/Show.scala rename to util-collection/src/main/scala/sbt/util/Show.scala index fa2c27008..221824737 100644 --- a/internal/util-collection/src/main/scala/sbt/util/Show.scala +++ b/util-collection/src/main/scala/sbt/util/Show.scala @@ -7,11 +7,12 @@ package sbt.util -trait Show[A] { +trait Show[A]: def show(a: A): String -} -object Show { +end Show + +object Show: def apply[A](f: A => String): Show[A] = a => f(a) def fromToString[A]: Show[A] = _.toString -} +end Show diff --git a/internal/util-collection/src/test/scala/DagSpecification.scala b/util-collection/src/test/scala-2/DagSpecification.scala similarity index 100% rename from internal/util-collection/src/test/scala/DagSpecification.scala rename to util-collection/src/test/scala-2/DagSpecification.scala diff --git a/internal/util-collection/src/test/scala/HListFormatSpec.scala b/util-collection/src/test/scala-2/HListFormatSpec.scala similarity index 100% rename from internal/util-collection/src/test/scala/HListFormatSpec.scala rename to util-collection/src/test/scala-2/HListFormatSpec.scala diff --git a/internal/util-collection/src/test/scala/KeyTest.scala b/util-collection/src/test/scala-2/KeyTest.scala similarity index 100% rename from internal/util-collection/src/test/scala/KeyTest.scala rename to util-collection/src/test/scala-2/KeyTest.scala diff --git a/internal/util-collection/src/test/scala/PMapTest.scala b/util-collection/src/test/scala-2/PMapTest.scala similarity index 100% rename from internal/util-collection/src/test/scala/PMapTest.scala rename to util-collection/src/test/scala-2/PMapTest.scala diff --git a/internal/util-collection/src/test/scala/SettingsExample.scala b/util-collection/src/test/scala-2/SettingsExample.scala similarity index 100% rename from internal/util-collection/src/test/scala/SettingsExample.scala rename to util-collection/src/test/scala-2/SettingsExample.scala diff --git a/internal/util-collection/src/test/scala/SettingsTest.scala b/util-collection/src/test/scala-2/SettingsTest.scala similarity index 100% rename from internal/util-collection/src/test/scala/SettingsTest.scala rename to util-collection/src/test/scala-2/SettingsTest.scala diff --git a/internal/util-collection/src/test/scala/UnitSpec.scala b/util-collection/src/test/scala-2/UnitSpec.scala similarity index 100% rename from internal/util-collection/src/test/scala/UnitSpec.scala rename to util-collection/src/test/scala-2/UnitSpec.scala diff --git a/util-collection/src/test/scala/FunctorTest.scala b/util-collection/src/test/scala/FunctorTest.scala new file mode 100644 index 000000000..65a6c90a7 --- /dev/null +++ b/util-collection/src/test/scala/FunctorTest.scala @@ -0,0 +1,40 @@ +import hedgehog.* +import hedgehog.runner.* +import _root_.sbt.util.Functor + +object FunctorTest extends Properties: + val F = summon[Functor[Option]] + + override def tests: List[Test] = + List( + example("None", testNone), + property("identity", identityProperty), + property("composition", compositionProperty), + property("map", mapProperty), + ) + + def testNone: Result = + Result.assert(F.map(None: Option[Int])(_ + 1) == None) + + def identityProperty: Property = + for x <- Gen.int(Range.linear(-100, 100)).forAll + yield F.map(Some(x))(identity) ==== Some(x) + + def mapProperty: Property = + for + x <- Gen.int(Range.linear(-100, 100)).forAll + f <- genFun.forAll + yield F.map(Some(x))(f) ==== Some(f(x)) + + def compositionProperty: Property = + for + x <- Gen.int(Range.linear(-100, 100)).forAll + f <- genFun.forAll + g <- genFun.forAll + yield F.map(Some(x))(f compose g) ==== F.map(F.map(Some(x))(g))(f) + + def genFun: Gen[Int => Int] = + for x <- Gen.int(Range.linear(-100, 100)) + yield (_: Int) + x + +end FunctorTest