mirror of https://github.com/sbt/sbt.git
Merge branch 'develop' into wip/scalainstance
This commit is contained in:
commit
29c77f6f5f
|
|
@ -9,19 +9,12 @@
|
||||||
package sbt
|
package sbt
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import sbt.internal.util.{
|
import sbt.internal.util.{ AttributeKey, LineRange, MessageOnlyException, RangePosition }
|
||||||
AttributeEntry,
|
|
||||||
AttributeKey,
|
|
||||||
LineRange,
|
|
||||||
MessageOnlyException,
|
|
||||||
RangePosition,
|
|
||||||
Settings
|
|
||||||
}
|
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import sbt.internal.util.complete.DefaultParsers.validID
|
import sbt.internal.util.complete.DefaultParsers.validID
|
||||||
import Def.{ ScopedKey, Setting }
|
import Def.{ ScopedKey, Setting, Settings }
|
||||||
import Scope.GlobalScope
|
import Scope.GlobalScope
|
||||||
import sbt.SlashSyntax0.given
|
import sbt.SlashSyntax0.given
|
||||||
import sbt.internal.parser.SbtParser
|
import sbt.internal.parser.SbtParser
|
||||||
|
|
@ -351,17 +344,6 @@ object BuildUtilLite:
|
||||||
end BuildUtilLite
|
end BuildUtilLite
|
||||||
|
|
||||||
object Index {
|
object Index {
|
||||||
def taskToKeyMap(data: Settings[Scope]): Map[Task[?], ScopedKey[Task[?]]] = {
|
|
||||||
|
|
||||||
val pairs = data.scopes flatMap (scope =>
|
|
||||||
data.data(scope).entries collect { case AttributeEntry(key, value: Task[_]) =>
|
|
||||||
(value, ScopedKey(scope, key.asInstanceOf[AttributeKey[Task[?]]]))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
pairs.toMap[Task[?], ScopedKey[Task[?]]]
|
|
||||||
}
|
|
||||||
|
|
||||||
def allKeys(settings: Seq[Setting[?]]): Set[ScopedKey[?]] = {
|
def allKeys(settings: Seq[Setting[?]]): Set[ScopedKey[?]] = {
|
||||||
val result = new java.util.HashSet[ScopedKey[?]]
|
val result = new java.util.HashSet[ScopedKey[?]]
|
||||||
settings.foreach { s =>
|
settings.foreach { s =>
|
||||||
|
|
@ -372,9 +354,6 @@ object Index {
|
||||||
result.asScala.toSet
|
result.asScala.toSet
|
||||||
}
|
}
|
||||||
|
|
||||||
def attributeKeys(settings: Settings[Scope]): Set[AttributeKey[?]] =
|
|
||||||
settings.data.values.flatMap(_.keys).toSet[AttributeKey[?]]
|
|
||||||
|
|
||||||
def stringToKeyMap(settings: Set[AttributeKey[?]]): Map[String, AttributeKey[?]] =
|
def stringToKeyMap(settings: Set[AttributeKey[?]]): Map[String, AttributeKey[?]] =
|
||||||
stringToKeyMap0(settings)(_.label)
|
stringToKeyMap0(settings)(_.label)
|
||||||
|
|
||||||
|
|
@ -396,19 +375,17 @@ object Index {
|
||||||
|
|
||||||
private type TriggerMap = collection.mutable.HashMap[TaskId[?], Seq[TaskId[?]]]
|
private type TriggerMap = collection.mutable.HashMap[TaskId[?], Seq[TaskId[?]]]
|
||||||
|
|
||||||
def triggers(ss: Settings[Scope]): Triggers = {
|
def triggers(ss: Settings): Triggers = {
|
||||||
val runBefore = new TriggerMap
|
val runBefore = new TriggerMap
|
||||||
val triggeredBy = new TriggerMap
|
val triggeredBy = new TriggerMap
|
||||||
for
|
ss.values.collect { case base: Task[?] =>
|
||||||
a <- ss.data.values
|
|
||||||
case AttributeEntry(_, base: Task[?]) <- a.entries
|
|
||||||
do
|
|
||||||
def update(map: TriggerMap, key: AttributeKey[Seq[Task[?]]]): Unit =
|
def update(map: TriggerMap, key: AttributeKey[Seq[Task[?]]]): Unit =
|
||||||
base.info.attributes.get(key).getOrElse(Seq.empty).foreach { task =>
|
base.getOrElse(key, Seq.empty).foreach { task =>
|
||||||
map(task) = base +: map.getOrElse(task, Nil)
|
map(task) = base +: map.getOrElse(task, Nil)
|
||||||
}
|
}
|
||||||
update(runBefore, Def.runBefore)
|
update(runBefore, Def.runBefore)
|
||||||
update(triggeredBy, Def.triggeredBy)
|
update(triggeredBy, Def.triggeredBy)
|
||||||
|
}
|
||||||
val onComplete = (GlobalScope / Def.onComplete).get(ss).getOrElse(() => ())
|
val onComplete = (GlobalScope / Def.onComplete).get(ss).getOrElse(() => ())
|
||||||
new Triggers(runBefore, triggeredBy, map => { onComplete(); map })
|
new Triggers(runBefore, triggeredBy, map => { onComplete(); map })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -463,10 +463,7 @@ object Tests {
|
||||||
fun: TestFunction,
|
fun: TestFunction,
|
||||||
tags: Seq[(Tag, Int)]
|
tags: Seq[(Tag, Int)]
|
||||||
): Task[Map[String, SuiteResult]] = {
|
): Task[Map[String, SuiteResult]] = {
|
||||||
val base = Task[(String, (SuiteResult, Seq[TestTask]))](
|
val base = Task(Action.Pure(() => (name, fun.apply()), `inline` = false)).setName(name)
|
||||||
Info[(String, (SuiteResult, Seq[TestTask]))]().setName(name),
|
|
||||||
Action.Pure(() => (name, fun.apply()), `inline` = false)
|
|
||||||
)
|
|
||||||
val taggedBase = base.tagw(tags*).tag(fun.tags.map(ConcurrentRestrictions.Tag(_))*)
|
val taggedBase = base.tagw(tags*).tag(fun.tags.map(ConcurrentRestrictions.Tag(_))*)
|
||||||
taggedBase flatMap { case (name, (result, nested)) =>
|
taggedBase flatMap { case (name, (result, nested)) =>
|
||||||
val nestedRunnables = createNestedRunnables(loader, fun, nested)
|
val nestedRunnables = createNestedRunnables(loader, fun, nested)
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ trait BuildSyntax:
|
||||||
end BuildSyntax
|
end BuildSyntax
|
||||||
|
|
||||||
/** A concrete settings system that uses `sbt.Scope` for the scope type. */
|
/** A concrete settings system that uses `sbt.Scope` for the scope type. */
|
||||||
object Def extends BuildSyntax with Init[Scope] with InitializeImplicits:
|
object Def extends BuildSyntax with Init with InitializeImplicits:
|
||||||
|
type ScopeType = Scope
|
||||||
type Classpath = Seq[Attributed[HashedVirtualFileRef]]
|
type Classpath = Seq[Attributed[HashedVirtualFileRef]]
|
||||||
|
|
||||||
def settings(ss: SettingsDefinition*): Seq[Setting[?]] = ss.flatMap(_.settings)
|
def settings(ss: SettingsDefinition*): Seq[Setting[?]] = ss.flatMap(_.settings)
|
||||||
|
|
@ -457,11 +458,11 @@ object Def extends BuildSyntax with Init[Scope] with InitializeImplicits:
|
||||||
sys.error(s"Dummy task '$name' did not get converted to a full task.")
|
sys.error(s"Dummy task '$name' did not get converted to a full task.")
|
||||||
)
|
)
|
||||||
.named(name)
|
.named(name)
|
||||||
base.copy(info = base.info.set(isDummyTask, true))
|
base.set(isDummyTask, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def isDummy(t: Task[?]): Boolean =
|
private[sbt] def isDummy(t: Task[?]): Boolean =
|
||||||
t.info.attributes.get(isDummyTask) getOrElse false
|
t.get(isDummyTask).getOrElse(false)
|
||||||
end Def
|
end Def
|
||||||
|
|
||||||
sealed trait InitializeImplicits { self: Def.type =>
|
sealed trait InitializeImplicits { self: Def.type =>
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ object Previous {
|
||||||
val successfulTaskResults = (
|
val successfulTaskResults = (
|
||||||
for
|
for
|
||||||
case results.TPair(task: Task[?], Result.Value(v)) <- results.toTypedSeq
|
case results.TPair(task: Task[?], Result.Value(v)) <- results.toTypedSeq
|
||||||
key <- task.info.attributes.get(Def.taskDefinitionKey).asInstanceOf[Option[AnyTaskKey]]
|
key <- task.get(Def.taskDefinitionKey).asInstanceOf[Option[AnyTaskKey]]
|
||||||
yield key -> v
|
yield key -> v
|
||||||
).toMap
|
).toMap
|
||||||
// We then traverse the successful results and look up all of the referenced values for
|
// We then traverse the successful results and look up all of the referenced values for
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ object Project:
|
||||||
ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key)
|
ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key)
|
||||||
|
|
||||||
def mapScope(f: Scope => Scope): [a] => ScopedKey[a] => ScopedKey[a] =
|
def mapScope(f: Scope => Scope): [a] => ScopedKey[a] => ScopedKey[a] =
|
||||||
[a] => (k: ScopedKey[a]) => ScopedKey(f(k.scope), k.key)
|
[a] => (k: ScopedKey[a]) => k.copy(scope = f(k.scope))
|
||||||
|
|
||||||
def transform(g: Scope => Scope, ss: Seq[Def.Setting[?]]): Seq[Def.Setting[?]] =
|
def transform(g: Scope => Scope, ss: Seq[Def.Setting[?]]): Seq[Def.Setting[?]] =
|
||||||
// We use caching to avoid creating new Scope instances too many times
|
// We use caching to avoid creating new Scope instances too many times
|
||||||
|
|
@ -361,7 +361,10 @@ object Project:
|
||||||
Project.transform(Scope.replaceThis(scope), ss)
|
Project.transform(Scope.replaceThis(scope), ss)
|
||||||
|
|
||||||
private[sbt] def inScope[A](scope: Scope, i: Initialize[A]): Initialize[A] =
|
private[sbt] def inScope[A](scope: Scope, i: Initialize[A]): Initialize[A] =
|
||||||
i.mapReferenced(Project.mapScope(Scope.replaceThis(scope)))
|
i.mapReferenced(replaceThis(scope))
|
||||||
|
|
||||||
|
private[sbt] def replaceThis(scope: Scope): Def.MapScoped =
|
||||||
|
mapScope(Scope.replaceThis(scope))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a String so that it is suitable for use as a dependency management module identifier.
|
* Normalize a String so that it is suitable for use as a dependency management module identifier.
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ package sbt
|
||||||
import scala.annotation.targetName
|
import scala.annotation.targetName
|
||||||
|
|
||||||
import sbt.internal.util.Types.*
|
import sbt.internal.util.Types.*
|
||||||
import sbt.internal.util.{ AttributeKey, KeyTag, Settings, SourcePosition }
|
import sbt.internal.util.{ AttributeKey, KeyTag, SourcePosition }
|
||||||
import sbt.internal.util.TupleMapExtension.*
|
import sbt.internal.util.TupleMapExtension.*
|
||||||
import sbt.util.OptJsonWriter
|
import sbt.util.OptJsonWriter
|
||||||
import sbt.ConcurrentRestrictions.Tag
|
import sbt.ConcurrentRestrictions.Tag
|
||||||
|
|
@ -303,8 +303,7 @@ object Scoped:
|
||||||
setting(scopedKey, app, source)
|
setting(scopedKey, app, source)
|
||||||
|
|
||||||
/** From the given `Settings`, extract the value bound to this key. */
|
/** From the given `Settings`, extract the value bound to this key. */
|
||||||
final def get(settings: Settings[Scope]): Option[A1] =
|
final def get(settings: Def.Settings): Option[A1] = settings.get(scopedKey)
|
||||||
settings.get(scopedKey.scope, scopedKey.key)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an [[Def.Initialize]] with value `scala.None` if there was no previous definition of this key,
|
* Creates an [[Def.Initialize]] with value `scala.None` if there was no previous definition of this key,
|
||||||
|
|
@ -385,7 +384,7 @@ object Scoped:
|
||||||
): Initialize[Task[A1]] =
|
): Initialize[Task[A1]] =
|
||||||
Initialize
|
Initialize
|
||||||
.joinAny[Task](coerceToAnyTaskSeq(tasks))
|
.joinAny[Task](coerceToAnyTaskSeq(tasks))
|
||||||
.zipWith(init)((ts, i) => i.copy(info = i.info.set(key, ts)))
|
.zipWith(init)((ts, i) => i.set(key, ts))
|
||||||
|
|
||||||
extension [A1](init: Initialize[InputTask[A1]])
|
extension [A1](init: Initialize[InputTask[A1]])
|
||||||
@targetName("onTaskInitializeInputTask")
|
@targetName("onTaskInitializeInputTask")
|
||||||
|
|
@ -460,7 +459,7 @@ object Scoped:
|
||||||
|
|
||||||
def toSettingKey: SettingKey[Task[A1]] = scopedSetting(scope, key)
|
def toSettingKey: SettingKey[Task[A1]] = scopedSetting(scope, key)
|
||||||
|
|
||||||
def get(settings: Settings[Scope]): Option[Task[A1]] = settings.get(scope, key)
|
def get(settings: Def.Settings): Option[Task[A1]] = settings.get(scopedKey)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an [[Def.Initialize]] with value `scala.None` if there was no previous definition of this key,
|
* Creates an [[Def.Initialize]] with value `scala.None` if there was no previous definition of this key,
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ end ParserInstance
|
||||||
|
|
||||||
/** Composes the Task and Initialize Instances to provide an Instance for [A1] Initialize[Task[A1]]. */
|
/** Composes the Task and Initialize Instances to provide an Instance for [A1] Initialize[Task[A1]]. */
|
||||||
object FullInstance:
|
object FullInstance:
|
||||||
type SS = sbt.internal.util.Settings[Scope]
|
type SS = Def.Settings
|
||||||
val settingsData = TaskKey[SS](
|
val settingsData = TaskKey[SS](
|
||||||
"settings-data",
|
"settings-data",
|
||||||
"Provides access to the project data for the build.",
|
"Provides access to the project data for the build.",
|
||||||
|
|
|
||||||
|
|
@ -4001,14 +4001,15 @@ object Classpaths {
|
||||||
try {
|
try {
|
||||||
val extracted = Project.extract(st)
|
val extracted = Project.extract(st)
|
||||||
val sk = (projRef / Zero / Zero / libraryDependencies).scopedKey
|
val sk = (projRef / Zero / Zero / libraryDependencies).scopedKey
|
||||||
val empty = extracted.structure.data.set(sk.scope, sk.key, Nil)
|
val empty = extracted.structure.data.set(sk, Nil)
|
||||||
val settings = extracted.structure.settings filter { (s: Setting[?]) =>
|
val settings = extracted.structure.settings filter { (s: Setting[?]) =>
|
||||||
(s.key.key == libraryDependencies.key) &&
|
(s.key.key == libraryDependencies.key) &&
|
||||||
(s.key.scope.project == Select(projRef))
|
(s.key.scope.project == Select(projRef))
|
||||||
}
|
}
|
||||||
Map(settings.asInstanceOf[Seq[Setting[Seq[ModuleID]]]].flatMap { s =>
|
settings
|
||||||
s.init.evaluate(empty) map { _ -> s.pos }
|
.asInstanceOf[Seq[Setting[Seq[ModuleID]]]]
|
||||||
}*)
|
.flatMap(s => s.init.evaluate(empty).map(_ -> s.pos))
|
||||||
|
.toMap
|
||||||
} catch {
|
} catch {
|
||||||
case NonFatal(_) => Map()
|
case NonFatal(_) => Map()
|
||||||
}
|
}
|
||||||
|
|
@ -4163,7 +4164,7 @@ object Classpaths {
|
||||||
|
|
||||||
private[sbt] def depMap(
|
private[sbt] def depMap(
|
||||||
projects: Seq[ProjectRef],
|
projects: Seq[ProjectRef],
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
log: Logger
|
log: Logger
|
||||||
): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
||||||
val ivyModules = projects.flatMap { proj =>
|
val ivyModules = projects.flatMap { proj =>
|
||||||
|
|
@ -4240,14 +4241,14 @@ object Classpaths {
|
||||||
def interSort(
|
def interSort(
|
||||||
projectRef: ProjectRef,
|
projectRef: ProjectRef,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
deps: BuildDependencies
|
deps: BuildDependencies
|
||||||
): Seq[(ProjectRef, String)] = ClasspathImpl.interSort(projectRef, conf, data, deps)
|
): Seq[(ProjectRef, String)] = ClasspathImpl.interSort(projectRef, conf, data, deps)
|
||||||
|
|
||||||
def interSortConfigurations(
|
def interSortConfigurations(
|
||||||
projectRef: ProjectRef,
|
projectRef: ProjectRef,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
deps: BuildDependencies
|
deps: BuildDependencies
|
||||||
): Seq[(ProjectRef, ConfigRef)] =
|
): Seq[(ProjectRef, ConfigRef)] =
|
||||||
interSort(projectRef, conf, data, deps).map { case (projectRef, configName) =>
|
interSort(projectRef, conf, data, deps).map { case (projectRef, configName) =>
|
||||||
|
|
@ -4291,23 +4292,23 @@ object Classpaths {
|
||||||
sys.error("Configuration '" + conf + "' not defined in '" + in + "'")
|
sys.error("Configuration '" + conf + "' not defined in '" + in + "'")
|
||||||
def allConfigs(conf: Configuration): Seq[Configuration] = ClasspathImpl.allConfigs(conf)
|
def allConfigs(conf: Configuration): Seq[Configuration] = ClasspathImpl.allConfigs(conf)
|
||||||
|
|
||||||
def getConfigurations(p: ResolvedReference, data: Settings[Scope]): Seq[Configuration] =
|
def getConfigurations(p: ResolvedReference, data: Def.Settings): Seq[Configuration] =
|
||||||
ClasspathImpl.getConfigurations(p, data)
|
ClasspathImpl.getConfigurations(p, data)
|
||||||
def confOpt(configurations: Seq[Configuration], conf: String): Option[Configuration] =
|
def confOpt(configurations: Seq[Configuration], conf: String): Option[Configuration] =
|
||||||
ClasspathImpl.confOpt(configurations, conf)
|
ClasspathImpl.confOpt(configurations, conf)
|
||||||
|
|
||||||
def unmanagedLibs(dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
|
def unmanagedLibs(dep: ResolvedReference, conf: String, data: Def.Settings): Task[Classpath] =
|
||||||
ClasspathImpl.unmanagedLibs(dep, conf, data)
|
ClasspathImpl.unmanagedLibs(dep, conf, data)
|
||||||
|
|
||||||
def getClasspath(
|
def getClasspath(
|
||||||
key: TaskKey[Classpath],
|
key: TaskKey[Classpath],
|
||||||
dep: ResolvedReference,
|
dep: ResolvedReference,
|
||||||
conf: String,
|
conf: String,
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): Task[Classpath] =
|
): Task[Classpath] =
|
||||||
ClasspathImpl.getClasspath(key, dep, conf, data)
|
ClasspathImpl.getClasspath(key, dep, conf, data)
|
||||||
|
|
||||||
def defaultConfigurationTask(p: ResolvedReference, data: Settings[Scope]): Configuration =
|
def defaultConfigurationTask(p: ResolvedReference, data: Def.Settings): Configuration =
|
||||||
(p / defaultConfiguration).get(data).flatten.getOrElse(Configurations.Default)
|
(p / defaultConfiguration).get(data).flatten.getOrElse(Configurations.Default)
|
||||||
|
|
||||||
val sbtIvySnapshots: URLRepository = Resolver.sbtIvyRepo("snapshots")
|
val sbtIvySnapshots: URLRepository = Resolver.sbtIvyRepo("snapshots")
|
||||||
|
|
@ -4748,7 +4749,7 @@ trait BuildExtra extends BuildCommon with DefExtra {
|
||||||
def initScoped[T](sk: ScopedKey[?], i: Initialize[T]): Initialize[T] =
|
def initScoped[T](sk: ScopedKey[?], i: Initialize[T]): Initialize[T] =
|
||||||
initScope(fillTaskAxis(sk.scope, sk.key), i)
|
initScope(fillTaskAxis(sk.scope, sk.key), i)
|
||||||
def initScope[T](s: Scope, i: Initialize[T]): Initialize[T] =
|
def initScope[T](s: Scope, i: Initialize[T]): Initialize[T] =
|
||||||
i.mapReferenced(Project.mapScope(Scope.replaceThis(s)))
|
Project.inScope(s, i)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables post-compilation hook for determining tests for tab-completion (such as for 'test-only').
|
* Disables post-compilation hook for determining tests for tab-completion (such as for 'test-only').
|
||||||
|
|
|
||||||
|
|
@ -449,8 +449,8 @@ object EvaluateTask {
|
||||||
ref: ProjectRef
|
ref: ProjectRef
|
||||||
): Option[(Task[T], NodeView)] = {
|
): Option[(Task[T], NodeView)] = {
|
||||||
val thisScope = Load.projectScope(ref)
|
val thisScope = Load.projectScope(ref)
|
||||||
val resolvedScope = Scope.replaceThis(thisScope)(taskKey.scope)
|
val subScoped = Project.replaceThis(thisScope)(taskKey.scopedKey)
|
||||||
for (t <- structure.data.get(resolvedScope, taskKey.key))
|
for (t <- structure.data.get(subScoped))
|
||||||
yield (t, nodeView(state, streams, taskKey :: Nil))
|
yield (t, nodeView(state, streams, taskKey :: Nil))
|
||||||
}
|
}
|
||||||
def nodeView(
|
def nodeView(
|
||||||
|
|
@ -582,7 +582,7 @@ object EvaluateTask {
|
||||||
Function.chain(
|
Function.chain(
|
||||||
results.toTypedSeq flatMap {
|
results.toTypedSeq flatMap {
|
||||||
case results.TPair(_, Result.Value(KeyValue(_, st: StateTransform))) => Some(st.transform)
|
case results.TPair(_, Result.Value(KeyValue(_, st: StateTransform))) => Some(st.transform)
|
||||||
case results.TPair(Task(info, _), Result.Value(v)) => info.post(v).get(transformState)
|
case results.TPair(task: Task[?], Result.Value(v)) => task.post(v).get(transformState)
|
||||||
case _ => Nil
|
case _ => Nil
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import sbt.internal.{ Load, BuildStructure, Act, Aggregation, SessionSettings }
|
||||||
import Scope.GlobalScope
|
import Scope.GlobalScope
|
||||||
import Def.{ ScopedKey, Setting }
|
import Def.{ ScopedKey, Setting }
|
||||||
import sbt.internal.util.complete.Parser
|
import sbt.internal.util.complete.Parser
|
||||||
import sbt.internal.util.AttributeKey
|
|
||||||
import sbt.util.Show
|
import sbt.util.Show
|
||||||
import std.Transform.DummyTaskMap
|
import std.Transform.DummyTaskMap
|
||||||
import sbt.EvaluateTask.extractedTaskConfig
|
import sbt.EvaluateTask.extractedTaskConfig
|
||||||
|
|
@ -34,21 +33,21 @@ final case class Extracted(
|
||||||
* If the project axis is not explicitly specified, it is resolved to be the current project according to the extracted `session`.
|
* If the project axis is not explicitly specified, it is resolved to be the current project according to the extracted `session`.
|
||||||
* Other axes are resolved to be `Zero` if they are not specified.
|
* Other axes are resolved to be `Zero` if they are not specified.
|
||||||
*/
|
*/
|
||||||
def get[T](key: SettingKey[T]): T = getOrError(inCurrent(key.scope), key.key)
|
def get[T](key: SettingKey[T]): T = getOrError(inCurrent(key.scopedKey))
|
||||||
def get[T](key: TaskKey[T]): Task[T] = getOrError(inCurrent(key.scope), key.key)
|
def get[T](key: TaskKey[T]): Task[T] = getOrError(inCurrent(key.scopedKey))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value assigned to `key` in the computed settings map wrapped in Some. If it does not exist, None is returned.
|
* Gets the value assigned to `key` in the computed settings map wrapped in Some. If it does not exist, None is returned.
|
||||||
* If the project axis is not explicitly specified, it is resolved to be the current project according to the extracted `session`.
|
* If the project axis is not explicitly specified, it is resolved to be the current project according to the extracted `session`.
|
||||||
* Other axes are resolved to be `Zero` if they are not specified.
|
* Other axes are resolved to be `Zero` if they are not specified.
|
||||||
*/
|
*/
|
||||||
def getOpt[T](key: SettingKey[T]): Option[T] = structure.data.get(inCurrent(key.scope), key.key)
|
def getOpt[T](key: SettingKey[T]): Option[T] = structure.data.get(inCurrent(key.scopedKey))
|
||||||
def getOpt[T](key: TaskKey[T]): Option[Task[T]] =
|
def getOpt[T](key: TaskKey[T]): Option[Task[T]] =
|
||||||
structure.data.get(inCurrent(key.scope), key.key)
|
structure.data.get(inCurrent(key))
|
||||||
|
|
||||||
private def inCurrent(scope: Scope): Scope =
|
private def inCurrent[T](key: ScopedKey[T]): ScopedKey[T] =
|
||||||
if scope.project == This then scope.rescope(currentRef)
|
if key.scope.project == This then key.copy(scope = key.scope.rescope(currentRef))
|
||||||
else scope
|
else key
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the task specified by `key` and returns the transformed State and the resulting value of the task.
|
* Runs the task specified by `key` and returns the transformed State and the resulting value of the task.
|
||||||
|
|
@ -63,7 +62,7 @@ final case class Extracted(
|
||||||
val config = extractedTaskConfig(this, structure, state)
|
val config = extractedTaskConfig(this, structure, state)
|
||||||
val value: Option[(State, Result[T])] =
|
val value: Option[(State, Result[T])] =
|
||||||
EvaluateTask(structure, key.scopedKey, state, currentRef, config)
|
EvaluateTask(structure, key.scopedKey, state, currentRef, config)
|
||||||
val (newS, result) = getOrError(rkey.scope, rkey.key, value)
|
val (newS, result) = getOrError(rkey.scopedKey, value)
|
||||||
(newS, EvaluateTask.processResult2(result))
|
(newS, EvaluateTask.processResult2(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,15 +115,15 @@ final case class Extracted(
|
||||||
private def resolve[K <: Scoped.ScopingSetting[K] & Scoped](key: K): K =
|
private def resolve[K <: Scoped.ScopingSetting[K] & Scoped](key: K): K =
|
||||||
Scope.resolveScope(GlobalScope, currentRef.build, rootProject)(key.scope) / key
|
Scope.resolveScope(GlobalScope, currentRef.build, rootProject)(key.scope) / key
|
||||||
|
|
||||||
private def getOrError[T](scope: Scope, key: AttributeKey[?], value: Option[T])(implicit
|
private def getOrError[T](key: ScopedKey[?], value: Option[T])(implicit
|
||||||
display: Show[ScopedKey[?]]
|
display: Show[ScopedKey[?]]
|
||||||
): T =
|
): T =
|
||||||
value getOrElse sys.error(display.show(ScopedKey(scope, key)) + " is undefined.")
|
value.getOrElse(sys.error(display.show(key) + " is undefined."))
|
||||||
|
|
||||||
private def getOrError[T](scope: Scope, key: AttributeKey[T])(implicit
|
private def getOrError[T](key: ScopedKey[T])(implicit
|
||||||
display: Show[ScopedKey[?]]
|
display: Show[ScopedKey[?]]
|
||||||
): T =
|
): T =
|
||||||
getOrError(scope, key, structure.data.get(scope, key))(display)
|
getOrError(key, structure.data.get(key))(display)
|
||||||
|
|
||||||
@deprecated(
|
@deprecated(
|
||||||
"This discards session settings. Migrate to appendWithSession or appendWithoutSession.",
|
"This discards session settings. Migrate to appendWithSession or appendWithoutSession.",
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ import sbt.internal.{
|
||||||
SettingGraph,
|
SettingGraph,
|
||||||
SessionSettings
|
SessionSettings
|
||||||
}
|
}
|
||||||
import sbt.internal.util.{ AttributeKey, AttributeMap, Relation, Settings }
|
import sbt.internal.util.{ AttributeKey, AttributeMap, Relation }
|
||||||
import sbt.internal.util.Types.const
|
import sbt.internal.util.Types.const
|
||||||
import sbt.internal.server.ServerHandler
|
import sbt.internal.server.ServerHandler
|
||||||
import sbt.librarymanagement.Configuration
|
import sbt.librarymanagement.Configuration
|
||||||
|
|
@ -288,10 +288,10 @@ trait ProjectExtra extends Scoped.Syntax:
|
||||||
def orIdentity[A](opt: Option[A => A]): A => A =
|
def orIdentity[A](opt: Option[A => A]): A => A =
|
||||||
opt.getOrElse(identity)
|
opt.getOrElse(identity)
|
||||||
|
|
||||||
def getHook[A](key: SettingKey[A => A], data: Settings[Scope]): A => A =
|
def getHook[A](key: SettingKey[A => A], data: Def.Settings): A => A =
|
||||||
orIdentity((Global / key).get(data))
|
orIdentity((Global / key).get(data))
|
||||||
|
|
||||||
def getHooks(data: Settings[Scope]): (State => State, State => State) =
|
def getHooks(data: Def.Settings): (State => State, State => State) =
|
||||||
(getHook(Keys.onLoad, data), getHook(Keys.onUnload, data))
|
(getHook(Keys.onLoad, data), getHook(Keys.onUnload, data))
|
||||||
|
|
||||||
def current(state: State): ProjectRef = session(state).current
|
def current(state: State): ProjectRef = session(state).current
|
||||||
|
|
@ -373,46 +373,34 @@ trait ProjectExtra extends Scoped.Syntax:
|
||||||
|
|
||||||
private[sbt] def scopedKeyData(
|
private[sbt] def scopedKeyData(
|
||||||
structure: BuildStructure,
|
structure: BuildStructure,
|
||||||
scope: Scope,
|
key: ScopedKey[?]
|
||||||
key: AttributeKey[?]
|
|
||||||
): Option[ScopedKeyData[?]] =
|
): Option[ScopedKeyData[?]] =
|
||||||
structure.data.get(scope, key) map { v =>
|
structure.data.getKeyValue(key).map((defining, value) => ScopedKeyData(key, defining, value))
|
||||||
ScopedKeyData(ScopedKey(scope, key), v)
|
|
||||||
}
|
|
||||||
|
|
||||||
def details(structure: BuildStructure, actual: Boolean, scope: Scope, key: AttributeKey[?])(
|
def details(structure: BuildStructure, actual: Boolean, key: ScopedKey[?])(using
|
||||||
using display: Show[ScopedKey[?]]
|
display: Show[ScopedKey[?]]
|
||||||
): String = {
|
): String = {
|
||||||
val scoped = ScopedKey(scope, key)
|
val data = scopedKeyData(structure, key).map(_.description).getOrElse("No entry for key.")
|
||||||
|
val description = key.key.description match
|
||||||
|
case Some(desc) => s"Description:\n\t$desc\n"
|
||||||
|
case None => ""
|
||||||
|
|
||||||
val data = scopedKeyData(structure, scope, key) map { _.description } getOrElse {
|
val (definingKey, providedBy) = structure.data.definingKey(key) match
|
||||||
"No entry for key."
|
case Some(k) => k -> s"Provided by:\n\t${Scope.display(k.scope, key.key.label)}\n"
|
||||||
}
|
case None => key -> ""
|
||||||
val description = key.description match {
|
|
||||||
case Some(desc) => "Description:\n\t" + desc + "\n"; case None => ""
|
|
||||||
}
|
|
||||||
|
|
||||||
val definingScope = structure.data.definingScope(scope, key)
|
|
||||||
val providedBy = definingScope match {
|
|
||||||
case Some(sc) => "Provided by:\n\t" + Scope.display(sc, key.label) + "\n"
|
|
||||||
case None => ""
|
|
||||||
}
|
|
||||||
val definingScoped = definingScope match {
|
|
||||||
case Some(sc) => ScopedKey(sc, key)
|
|
||||||
case None => scoped
|
|
||||||
}
|
|
||||||
val comp =
|
val comp =
|
||||||
Def.compiled(structure.settings, actual)(using
|
Def.compiled(structure.settings, actual)(using
|
||||||
structure.delegates,
|
structure.delegates,
|
||||||
structure.scopeLocal,
|
structure.scopeLocal,
|
||||||
display
|
display
|
||||||
)
|
)
|
||||||
val definedAt = comp get definingScoped map { c =>
|
val definedAt = comp
|
||||||
Def.definedAtString(c.settings).capitalize
|
.get(definingKey)
|
||||||
} getOrElse ""
|
.map(c => Def.definedAtString(c.settings).capitalize)
|
||||||
|
.getOrElse("")
|
||||||
|
|
||||||
val cMap = Def.flattenLocals(comp)
|
val cMap = Def.flattenLocals(comp)
|
||||||
val related = cMap.keys.filter(k => k.key == key && k.scope != scope)
|
val related = cMap.keys.filter(k => k.key == key.key && k.scope != key.scope)
|
||||||
def derivedDependencies(c: ScopedKey[?]): List[ScopedKey[?]] =
|
def derivedDependencies(c: ScopedKey[?]): List[ScopedKey[?]] =
|
||||||
comp
|
comp
|
||||||
.get(c)
|
.get(c)
|
||||||
|
|
@ -420,14 +408,14 @@ trait ProjectExtra extends Scoped.Syntax:
|
||||||
.toList
|
.toList
|
||||||
.flatten
|
.flatten
|
||||||
|
|
||||||
val depends = cMap.get(scoped) match {
|
val depends = cMap.get(key) match
|
||||||
case Some(c) => c.dependencies.toSet; case None => Set.empty
|
case Some(c) => c.dependencies.toSet
|
||||||
}
|
case None => Set.empty
|
||||||
val derivedDepends: Set[ScopedKey[?]] = derivedDependencies(definingScoped).toSet
|
val derivedDepends: Set[ScopedKey[?]] = derivedDependencies(definingKey).toSet
|
||||||
|
|
||||||
val reverse = Project.reverseDependencies(cMap, scoped)
|
val reverse = Project.reverseDependencies(cMap, key)
|
||||||
val derivedReverse =
|
val derivedReverse =
|
||||||
reverse.filter(r => derivedDependencies(r).contains(definingScoped)).toSet
|
reverse.filter(r => derivedDependencies(r).contains(definingKey)).toSet
|
||||||
|
|
||||||
def printDepScopes(
|
def printDepScopes(
|
||||||
baseLabel: String,
|
baseLabel: String,
|
||||||
|
|
@ -460,7 +448,7 @@ trait ProjectExtra extends Scoped.Syntax:
|
||||||
definedAt +
|
definedAt +
|
||||||
printDepScopes("Dependencies", "derived from", depends, derivedDepends) +
|
printDepScopes("Dependencies", "derived from", depends, derivedDepends) +
|
||||||
printDepScopes("Reverse dependencies", "derives", reverse, derivedReverse) +
|
printDepScopes("Reverse dependencies", "derives", reverse, derivedReverse) +
|
||||||
printScopes("Delegates", delegates(structure, scope, key)) +
|
printScopes("Delegates", delegates(structure, key.scope, key.key)) +
|
||||||
printScopes("Related", related, 10)
|
printScopes("Related", related, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,16 +11,14 @@ package sbt
|
||||||
import Def.ScopedKey
|
import Def.ScopedKey
|
||||||
import sbt.internal.util.KeyTag
|
import sbt.internal.util.KeyTag
|
||||||
|
|
||||||
final case class ScopedKeyData[A](scoped: ScopedKey[A], value: Any) {
|
final case class ScopedKeyData[A](key: ScopedKey[A], definingKey: ScopedKey[A], value: Any) {
|
||||||
val key = scoped.key
|
def typeName: String = key.key.tag.toString
|
||||||
val scope = scoped.scope
|
|
||||||
def typeName: String = key.tag.toString
|
|
||||||
def settingValue: Option[Any] =
|
def settingValue: Option[Any] =
|
||||||
key.tag match
|
key.key.tag match
|
||||||
case KeyTag.Setting(_) => Some(value)
|
case KeyTag.Setting(_) => Some(value)
|
||||||
case _ => None
|
case _ => None
|
||||||
def description: String =
|
def description: String =
|
||||||
key.tag match
|
key.key.tag match
|
||||||
case KeyTag.Task(typeArg) => s"Task: $typeArg"
|
case KeyTag.Task(typeArg) => s"Task: $typeArg"
|
||||||
case KeyTag.SeqTask(typeArg) => s"Task: Seq[$typeArg]"
|
case KeyTag.SeqTask(typeArg) => s"Task: Seq[$typeArg]"
|
||||||
case KeyTag.InputTask(typeArg) => s"Input task: $typeArg"
|
case KeyTag.InputTask(typeArg) => s"Input task: $typeArg"
|
||||||
|
|
|
||||||
|
|
@ -49,20 +49,21 @@ object SessionVar {
|
||||||
|
|
||||||
def orEmpty(opt: Option[Map]) = opt.getOrElse(emptyMap)
|
def orEmpty(opt: Option[Map]) = opt.getOrElse(emptyMap)
|
||||||
|
|
||||||
def transform[S](task: Task[S], f: (State, S) => State): Task[S] = {
|
def transform[S](task: Task[S], f: (State, S) => State): Task[S] =
|
||||||
val g = (s: S, map: AttributeMap) => map.put(Keys.transformState, (state: State) => f(state, s))
|
val g = (s: S, map: AttributeMap) => map.put(Keys.transformState, (state: State) => f(state, s))
|
||||||
task.copy(info = task.info.postTransform(g))
|
task.postTransform(g)
|
||||||
}
|
|
||||||
|
|
||||||
def resolveContext[T](
|
def resolveContext[T](
|
||||||
key: ScopedKey[Task[T]],
|
key: ScopedKey[Task[T]],
|
||||||
context: Scope,
|
context: Scope,
|
||||||
state: State
|
state: State
|
||||||
): ScopedKey[Task[T]] = {
|
): ScopedKey[Task[T]] =
|
||||||
val subScope = Scope.replaceThis(context)(key.scope)
|
val subScoped = Project.replaceThis(context)(key)
|
||||||
val scope = Project.structure(state).data.definingScope(subScope, key.key) getOrElse subScope
|
Project
|
||||||
ScopedKey(scope, key.key)
|
.structure(state)
|
||||||
}
|
.data
|
||||||
|
.definingKey(subScoped)
|
||||||
|
.getOrElse(subScoped)
|
||||||
|
|
||||||
def read[T](key: ScopedKey[Task[T]], state: State)(implicit f: JsonFormat[T]): Option[T] =
|
def read[T](key: ScopedKey[Task[T]], state: State)(implicit f: JsonFormat[T]): Option[T] =
|
||||||
Project.structure(state).streams(state).use(key) { s =>
|
Project.structure(state).streams(state).use(key) { s =>
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ private[sbt] abstract class AbstractTaskExecuteProgress extends ExecuteProgress
|
||||||
}
|
}
|
||||||
private def taskName0(t: TaskId[?]): String = {
|
private def taskName0(t: TaskId[?]): String = {
|
||||||
def definedName(node: Task[?]): Option[String] =
|
def definedName(node: Task[?]): Option[String] =
|
||||||
node.info.name.orElse(TaskName.transformNode(node).map(showScopedKey.show))
|
node.name.orElse(TaskName.transformNode(node).map(showScopedKey.show))
|
||||||
def inferredName(t: Task[?]): Option[String] = nameDelegate(t) map taskName
|
def inferredName(t: Task[?]): Option[String] = nameDelegate(t) map taskName
|
||||||
def nameDelegate(t: Task[?]): Option[TaskId[?]] =
|
def nameDelegate(t: Task[?]): Option[TaskId[?]] =
|
||||||
Option(anonOwners.get(t)).orElse(Option(calledBy.get(t)))
|
Option(anonOwners.get(t)).orElse(Option(calledBy.get(t)))
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import sbt.internal.util.{
|
||||||
AttributeMap,
|
AttributeMap,
|
||||||
IMap,
|
IMap,
|
||||||
MessageOnlyException,
|
MessageOnlyException,
|
||||||
Settings,
|
|
||||||
Util,
|
Util,
|
||||||
}
|
}
|
||||||
import sbt.util.Show
|
import sbt.util.Show
|
||||||
|
|
@ -61,7 +60,7 @@ object Act {
|
||||||
current: ProjectRef,
|
current: ProjectRef,
|
||||||
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
||||||
keyMap: Map[String, AttributeKey[?]],
|
keyMap: Map[String, AttributeKey[?]],
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): Parser[ScopedKey[Any]] =
|
): Parser[ScopedKey[Any]] =
|
||||||
scopedKeySelected(index, current, defaultConfigs, keyMap, data, askProject = true)
|
scopedKeySelected(index, current, defaultConfigs, keyMap, data, askProject = true)
|
||||||
.map(_.key.asInstanceOf[ScopedKey[Any]])
|
.map(_.key.asInstanceOf[ScopedKey[Any]])
|
||||||
|
|
@ -115,7 +114,7 @@ object Act {
|
||||||
current: ProjectRef,
|
current: ProjectRef,
|
||||||
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
||||||
keyMap: Map[String, AttributeKey[?]],
|
keyMap: Map[String, AttributeKey[?]],
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
askProject: Boolean,
|
askProject: Boolean,
|
||||||
): Parser[ParsedKey] =
|
): Parser[ParsedKey] =
|
||||||
scopedKeyFull(index, current, defaultConfigs, keyMap, askProject = askProject).flatMap {
|
scopedKeyFull(index, current, defaultConfigs, keyMap, askProject = askProject).flatMap {
|
||||||
|
|
@ -197,7 +196,7 @@ object Act {
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
|
|
||||||
def select(allKeys: Seq[Parser[ParsedKey]], data: Settings[Scope])(implicit
|
def select(allKeys: Seq[Parser[ParsedKey]], data: Def.Settings)(implicit
|
||||||
show: Show[ScopedKey[?]]
|
show: Show[ScopedKey[?]]
|
||||||
): Parser[ParsedKey] =
|
): Parser[ParsedKey] =
|
||||||
seq(allKeys) flatMap { ss =>
|
seq(allKeys) flatMap { ss =>
|
||||||
|
|
@ -235,10 +234,7 @@ object Act {
|
||||||
def showAmbiguous(keys: Seq[ScopedKey[?]])(implicit show: Show[ScopedKey[?]]): String =
|
def showAmbiguous(keys: Seq[ScopedKey[?]])(implicit show: Show[ScopedKey[?]]): String =
|
||||||
keys.take(3).map(x => show.show(x)).mkString("", ", ", if (keys.size > 3) ", ..." else "")
|
keys.take(3).map(x => show.show(x)).mkString("", ", ", if (keys.size > 3) ", ..." else "")
|
||||||
|
|
||||||
def isValid(data: Settings[Scope])(parsed: ParsedKey): Boolean = {
|
def isValid(data: Def.Settings)(parsed: ParsedKey): Boolean = data.contains(parsed.key)
|
||||||
val key = parsed.key
|
|
||||||
data.definingScope(key.scope, key.key) == Some(key.scope)
|
|
||||||
}
|
|
||||||
|
|
||||||
def examples(p: Parser[String], exs: Set[String], label: String): Parser[String] =
|
def examples(p: Parser[String], exs: Set[String], label: String): Parser[String] =
|
||||||
(p !!! ("Expected " + label)).examples(exs)
|
(p !!! ("Expected " + label)).examples(exs)
|
||||||
|
|
@ -571,28 +567,14 @@ object Act {
|
||||||
def keyValues[T](extracted: Extracted)(keys: Seq[ScopedKey[T]]): Values[T] =
|
def keyValues[T](extracted: Extracted)(keys: Seq[ScopedKey[T]]): Values[T] =
|
||||||
keyValues(extracted.structure)(keys)
|
keyValues(extracted.structure)(keys)
|
||||||
def keyValues[T](structure: BuildStructure)(keys: Seq[ScopedKey[T]]): Values[T] =
|
def keyValues[T](structure: BuildStructure)(keys: Seq[ScopedKey[T]]): Values[T] =
|
||||||
keys.flatMap { key =>
|
keys.flatMap(key => getValue(structure.data, key).map(KeyValue(key, _)))
|
||||||
getValue(structure.data, key.scope, key.key) map { value =>
|
|
||||||
KeyValue(key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private def anyKeyValues(
|
|
||||||
structure: BuildStructure,
|
|
||||||
keys: Seq[ScopedKey[?]]
|
|
||||||
): Seq[KeyValue[?]] =
|
|
||||||
keys.flatMap { key =>
|
|
||||||
getValue(structure.data, key.scope, key.key) map { value =>
|
|
||||||
KeyValue(key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def getValue[T](
|
private def anyKeyValues(structure: BuildStructure, keys: Seq[ScopedKey[?]]): Seq[KeyValue[?]] =
|
||||||
data: Settings[Scope],
|
keys.flatMap(key => getValue(structure.data, key).map(KeyValue(key, _)))
|
||||||
scope: Scope,
|
|
||||||
key: AttributeKey[T]
|
private def getValue[T](data: Def.Settings, key: ScopedKey[T]): Option[T] =
|
||||||
): Option[T] =
|
if (java.lang.Boolean.getBoolean("sbt.cli.nodelegation")) data.getDirect(key)
|
||||||
if (java.lang.Boolean.getBoolean("sbt.cli.nodelegation")) data.getDirect(scope, key)
|
else data.get(key)
|
||||||
else data.get(scope, key)
|
|
||||||
|
|
||||||
def requireSession[T](s: State, p: => Parser[T]): Parser[T] =
|
def requireSession[T](s: State, p: => Parser[T]): Parser[T] =
|
||||||
if s.get(sessionSettings).isEmpty then failure("No project loaded") else p
|
if s.get(sessionSettings).isEmpty then failure("No project loaded") else p
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ package internal
|
||||||
|
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
|
|
||||||
import sbt.Def.ScopedKey
|
import sbt.Def.{ ScopedKey, Settings }
|
||||||
import sbt.Keys.{ showSuccess, showTiming, timingFormat }
|
import sbt.Keys.{ showSuccess, showTiming, timingFormat }
|
||||||
import sbt.ProjectExtra.*
|
import sbt.ProjectExtra.*
|
||||||
import sbt.SlashSyntax0.given
|
import sbt.SlashSyntax0.given
|
||||||
|
|
@ -157,7 +157,7 @@ object Aggregation {
|
||||||
private def timingString(
|
private def timingString(
|
||||||
startTime: Long,
|
startTime: Long,
|
||||||
endTime: Long,
|
endTime: Long,
|
||||||
data: Settings[Scope],
|
data: Settings,
|
||||||
currentRef: ProjectRef,
|
currentRef: ProjectRef,
|
||||||
): String = {
|
): String = {
|
||||||
val format = (currentRef / timingFormat).get(data) getOrElse defaultFormat
|
val format = (currentRef / timingFormat).get(data) getOrElse defaultFormat
|
||||||
|
|
@ -266,29 +266,40 @@ object Aggregation {
|
||||||
else extra.aggregates.forward(ref)
|
else extra.aggregates.forward(ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the reverse aggregate keys of all the `keys` at once.
|
||||||
|
* This is more performant than computing the revere aggregate keys of each key individually
|
||||||
|
* because of the duplicates. One aggregate key is the aggregation of many keys.
|
||||||
|
*/
|
||||||
|
def reverseAggregate[Proj](
|
||||||
|
keys: Set[ScopedKey[?]],
|
||||||
|
extra: BuildUtil[Proj],
|
||||||
|
): Iterable[ScopedKey[?]] =
|
||||||
|
val mask = ScopeMask()
|
||||||
|
def recur(keys: Set[ScopedKey[?]], acc: Set[ScopedKey[?]]): Set[ScopedKey[?]] =
|
||||||
|
if keys.isEmpty then acc
|
||||||
|
else
|
||||||
|
val aggKeys = for
|
||||||
|
key <- keys
|
||||||
|
ref <- projectAggregates(key.scope.project.toOption, extra, reverse = true)
|
||||||
|
toResolve = key.scope.copy(project = Select(ref))
|
||||||
|
resolved = Resolve(extra, Zero, key.key, mask)(toResolve)
|
||||||
|
scoped = ScopedKey(resolved, key.key)
|
||||||
|
if !acc.contains(scoped)
|
||||||
|
yield scoped
|
||||||
|
val filteredAggKeys = aggKeys.filter(aggregationEnabled(_, extra.data))
|
||||||
|
// recursive because an aggregate project can be aggregated in another aggregate project
|
||||||
|
recur(filteredAggKeys, acc ++ filteredAggKeys)
|
||||||
|
recur(keys, keys)
|
||||||
|
|
||||||
def aggregate[A1, Proj](
|
def aggregate[A1, Proj](
|
||||||
key: ScopedKey[A1],
|
key: ScopedKey[A1],
|
||||||
rawMask: ScopeMask,
|
rawMask: ScopeMask,
|
||||||
extra: BuildUtil[Proj],
|
extra: BuildUtil[Proj]
|
||||||
reverse: Boolean = false
|
|
||||||
): Seq[ScopedKey[A1]] =
|
): Seq[ScopedKey[A1]] =
|
||||||
val mask = rawMask.copy(project = true)
|
val mask = rawMask.copy(project = true)
|
||||||
Dag.topologicalSort(key): (k) =>
|
Dag.topologicalSort(key): (k) =>
|
||||||
if reverse then reverseAggregatedKeys(k, extra, mask)
|
if aggregationEnabled(k, extra.data) then aggregatedKeys(k, extra, mask) else Nil
|
||||||
else if aggregationEnabled(k, extra.data) then aggregatedKeys(k, extra, mask)
|
|
||||||
else Nil
|
|
||||||
|
|
||||||
def reverseAggregatedKeys[T](
|
|
||||||
key: ScopedKey[T],
|
|
||||||
extra: BuildUtil[?],
|
|
||||||
mask: ScopeMask
|
|
||||||
): Seq[ScopedKey[T]] =
|
|
||||||
projectAggregates(key.scope.project.toOption, extra, reverse = true) flatMap { ref =>
|
|
||||||
val toResolve = key.scope.copy(project = Select(ref))
|
|
||||||
val resolved = Resolve(extra, Zero, key.key, mask)(toResolve)
|
|
||||||
val skey = ScopedKey(resolved, key.key)
|
|
||||||
if (aggregationEnabled(skey, extra.data)) skey :: Nil else Nil
|
|
||||||
}
|
|
||||||
|
|
||||||
def aggregatedKeys[T](
|
def aggregatedKeys[T](
|
||||||
key: ScopedKey[T],
|
key: ScopedKey[T],
|
||||||
|
|
@ -301,7 +312,7 @@ object Aggregation {
|
||||||
ScopedKey(resolved, key.key)
|
ScopedKey(resolved, key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
def aggregationEnabled(key: ScopedKey[?], data: Settings[Scope]): Boolean =
|
def aggregationEnabled(key: ScopedKey[?], data: Settings): Boolean =
|
||||||
(Scope.fillTaskAxis(key.scope, key.key) / Keys.aggregate).get(data).getOrElse(true)
|
(Scope.fillTaskAxis(key.scope, key.key) / Keys.aggregate).get(data).getOrElse(true)
|
||||||
private[sbt] val suppressShow =
|
private[sbt] val suppressShow =
|
||||||
AttributeKey[Boolean]("suppress-aggregation-show", Int.MaxValue)
|
AttributeKey[Boolean]("suppress-aggregation-show", Int.MaxValue)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import sbt.SlashSyntax0.given
|
||||||
import BuildStreams.Streams
|
import BuildStreams.Streams
|
||||||
import sbt.io.syntax._
|
import sbt.io.syntax._
|
||||||
import sbt.internal.inc.MappedFileConverter
|
import sbt.internal.inc.MappedFileConverter
|
||||||
import sbt.internal.util.{ AttributeEntry, AttributeKey, AttributeMap, Attributed, Settings }
|
import sbt.internal.util.{ AttributeEntry, AttributeKey, AttributeMap, Attributed }
|
||||||
import sbt.internal.util.Attributed.data
|
import sbt.internal.util.Attributed.data
|
||||||
import sbt.util.Logger
|
import sbt.util.Logger
|
||||||
import xsbti.FileConverter
|
import xsbti.FileConverter
|
||||||
|
|
@ -29,7 +29,7 @@ final class BuildStructure(
|
||||||
val units: Map[URI, LoadedBuildUnit],
|
val units: Map[URI, LoadedBuildUnit],
|
||||||
val root: URI,
|
val root: URI,
|
||||||
val settings: Seq[Setting[?]],
|
val settings: Seq[Setting[?]],
|
||||||
val data: Settings[Scope],
|
val data: Def.Settings,
|
||||||
val index: StructureIndex,
|
val index: StructureIndex,
|
||||||
val streams: State => Streams,
|
val streams: State => Streams,
|
||||||
val delegates: Scope => Seq[Scope],
|
val delegates: Scope => Seq[Scope],
|
||||||
|
|
@ -71,7 +71,6 @@ final class BuildStructure(
|
||||||
// information that is not original, but can be reconstructed from the rest of BuildStructure
|
// information that is not original, but can be reconstructed from the rest of BuildStructure
|
||||||
final class StructureIndex(
|
final class StructureIndex(
|
||||||
val keyMap: Map[String, AttributeKey[?]],
|
val keyMap: Map[String, AttributeKey[?]],
|
||||||
val taskToKey: Map[Task[?], ScopedKey[Task[?]]],
|
|
||||||
val triggers: Triggers,
|
val triggers: Triggers,
|
||||||
val keyIndex: KeyIndex,
|
val keyIndex: KeyIndex,
|
||||||
val aggregateKeyIndex: KeyIndex,
|
val aggregateKeyIndex: KeyIndex,
|
||||||
|
|
@ -271,7 +270,7 @@ final class LoadedBuild(val root: URI, val units: Map[URI, LoadedBuildUnit]) {
|
||||||
unit.projects.map(p => ProjectRef(build, p.id) -> p)
|
unit.projects.map(p => ProjectRef(build, p.id) -> p)
|
||||||
}.toIndexedSeq
|
}.toIndexedSeq
|
||||||
|
|
||||||
def extra(data: Settings[Scope])(keyIndex: KeyIndex): BuildUtil[ResolvedProject] =
|
def extra(data: Def.Settings)(keyIndex: KeyIndex): BuildUtil[ResolvedProject] =
|
||||||
BuildUtil(root, units, keyIndex, data)
|
BuildUtil(root, units, keyIndex, data)
|
||||||
|
|
||||||
private[sbt] def autos = GroupedAutoPlugins(units)
|
private[sbt] def autos = GroupedAutoPlugins(units)
|
||||||
|
|
@ -309,7 +308,7 @@ object BuildStreams {
|
||||||
def mkStreams(
|
def mkStreams(
|
||||||
units: Map[URI, LoadedBuildUnit],
|
units: Map[URI, LoadedBuildUnit],
|
||||||
root: URI,
|
root: URI,
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): State => Streams = s => {
|
): State => Streams = s => {
|
||||||
s.get(Keys.stateStreams).getOrElse {
|
s.get(Keys.stateStreams).getOrElse {
|
||||||
std.Streams(
|
std.Streams(
|
||||||
|
|
@ -324,7 +323,7 @@ object BuildStreams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def path(units: Map[URI, LoadedBuildUnit], root: URI, data: Settings[Scope])(
|
def path(units: Map[URI, LoadedBuildUnit], root: URI, data: Def.Settings)(
|
||||||
scoped: ScopedKey[?]
|
scoped: ScopedKey[?]
|
||||||
): File =
|
): File =
|
||||||
resolvePath(projectPath(units, root, scoped, data), nonProjectPath(scoped))
|
resolvePath(projectPath(units, root, scoped, data), nonProjectPath(scoped))
|
||||||
|
|
@ -386,7 +385,7 @@ object BuildStreams {
|
||||||
units: Map[URI, LoadedBuildUnit],
|
units: Map[URI, LoadedBuildUnit],
|
||||||
root: URI,
|
root: URI,
|
||||||
scoped: ScopedKey[?],
|
scoped: ScopedKey[?],
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): File =
|
): File =
|
||||||
scoped.scope.project match {
|
scoped.scope.project match {
|
||||||
case Zero => refTarget(GlobalScope, units(root).localBase, data) / GlobalPath
|
case Zero => refTarget(GlobalScope, units(root).localBase, data) / GlobalPath
|
||||||
|
|
@ -397,9 +396,9 @@ object BuildStreams {
|
||||||
case This => sys.error("Unresolved project reference (This) in " + displayFull(scoped))
|
case This => sys.error("Unresolved project reference (This) in " + displayFull(scoped))
|
||||||
}
|
}
|
||||||
|
|
||||||
def refTarget(ref: ResolvedReference, fallbackBase: File, data: Settings[Scope]): File =
|
def refTarget(ref: ResolvedReference, fallbackBase: File, data: Def.Settings): File =
|
||||||
refTarget(GlobalScope.copy(project = Select(ref)), fallbackBase, data)
|
refTarget(GlobalScope.copy(project = Select(ref)), fallbackBase, data)
|
||||||
|
|
||||||
def refTarget(scope: Scope, fallbackBase: File, data: Settings[Scope]): File =
|
def refTarget(scope: Scope, fallbackBase: File, data: Def.Settings): File =
|
||||||
((scope / Keys.target).get(data) getOrElse outputDirectory(fallbackBase)) / StreamsDirectory
|
((scope / Keys.target).get(data) getOrElse outputDirectory(fallbackBase)) / StreamsDirectory
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@
|
||||||
package sbt
|
package sbt
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import sbt.internal.util.{ Relation, Settings, Dag }
|
import sbt.internal.util.{ Relation, Dag }
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
final class BuildUtil[Proj](
|
final class BuildUtil[Proj](
|
||||||
val keyIndex: KeyIndex,
|
val keyIndex: KeyIndex,
|
||||||
val data: Settings[Scope],
|
val data: Def.Settings,
|
||||||
val root: URI,
|
val root: URI,
|
||||||
val rootProjectID: URI => String,
|
val rootProjectID: URI => String,
|
||||||
val project: (URI, String) => Proj,
|
val project: (URI, String) => Proj,
|
||||||
|
|
@ -57,7 +57,7 @@ object BuildUtil {
|
||||||
root: URI,
|
root: URI,
|
||||||
units: Map[URI, LoadedBuildUnit],
|
units: Map[URI, LoadedBuildUnit],
|
||||||
keyIndex: KeyIndex,
|
keyIndex: KeyIndex,
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): BuildUtil[ResolvedProject] = {
|
): BuildUtil[ResolvedProject] = {
|
||||||
val getp = (build: URI, project: String) => Load.getProject(units, build, project)
|
val getp = (build: URI, project: String) => Load.getProject(units, build, project)
|
||||||
val configs = (_: ResolvedProject).configurations.map(c => ConfigKey(c.name))
|
val configs = (_: ResolvedProject).configurations.map(c => ConfigKey(c.name))
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import sbt.Keys._
|
||||||
import sbt.nio.Keys._
|
import sbt.nio.Keys._
|
||||||
import sbt.nio.file.{ Glob, RecursiveGlob }
|
import sbt.nio.file.{ Glob, RecursiveGlob }
|
||||||
import sbt.Def.Initialize
|
import sbt.Def.Initialize
|
||||||
import sbt.internal.util.{ Attributed, Dag, Settings }
|
import sbt.internal.util.{ Attributed, Dag }
|
||||||
import sbt.librarymanagement.{ Configuration, TrackLevel }
|
import sbt.librarymanagement.{ Configuration, TrackLevel }
|
||||||
import sbt.librarymanagement.Configurations.names
|
import sbt.librarymanagement.Configurations.names
|
||||||
import sbt.std.TaskExtra._
|
import sbt.std.TaskExtra._
|
||||||
|
|
@ -180,7 +180,7 @@ private[sbt] object ClasspathImpl {
|
||||||
projectRef: ProjectRef,
|
projectRef: ProjectRef,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
self: Configuration,
|
self: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
deps: BuildDependencies,
|
deps: BuildDependencies,
|
||||||
track: TrackLevel,
|
track: TrackLevel,
|
||||||
log: Logger
|
log: Logger
|
||||||
|
|
@ -198,7 +198,7 @@ private[sbt] object ClasspathImpl {
|
||||||
projectRef: ProjectRef,
|
projectRef: ProjectRef,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
self: Configuration,
|
self: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
deps: BuildDependencies,
|
deps: BuildDependencies,
|
||||||
track: TrackLevel,
|
track: TrackLevel,
|
||||||
log: Logger
|
log: Logger
|
||||||
|
|
@ -244,7 +244,7 @@ private[sbt] object ClasspathImpl {
|
||||||
projectRef: ProjectRef,
|
projectRef: ProjectRef,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
self: Configuration,
|
self: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
deps: BuildDependencies,
|
deps: BuildDependencies,
|
||||||
track: TrackLevel,
|
track: TrackLevel,
|
||||||
log: Logger
|
log: Logger
|
||||||
|
|
@ -282,7 +282,7 @@ private[sbt] object ClasspathImpl {
|
||||||
def unmanagedDependencies0(
|
def unmanagedDependencies0(
|
||||||
projectRef: ProjectRef,
|
projectRef: ProjectRef,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
deps: BuildDependencies,
|
deps: BuildDependencies,
|
||||||
log: Logger
|
log: Logger
|
||||||
): Initialize[Task[Classpath]] =
|
): Initialize[Task[Classpath]] =
|
||||||
|
|
@ -306,7 +306,7 @@ private[sbt] object ClasspathImpl {
|
||||||
def unmanagedLibs(
|
def unmanagedLibs(
|
||||||
dep: ResolvedReference,
|
dep: ResolvedReference,
|
||||||
conf: String,
|
conf: String,
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): Task[Classpath] =
|
): Task[Classpath] =
|
||||||
getClasspath(unmanagedJars, dep, conf, data)
|
getClasspath(unmanagedJars, dep, conf, data)
|
||||||
|
|
||||||
|
|
@ -315,7 +315,7 @@ private[sbt] object ClasspathImpl {
|
||||||
deps: BuildDependencies,
|
deps: BuildDependencies,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
self: Configuration,
|
self: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
track: TrackLevel,
|
track: TrackLevel,
|
||||||
includeSelf: Boolean,
|
includeSelf: Boolean,
|
||||||
log: Logger
|
log: Logger
|
||||||
|
|
@ -346,7 +346,7 @@ private[sbt] object ClasspathImpl {
|
||||||
def interSort(
|
def interSort(
|
||||||
projectRef: ProjectRef,
|
projectRef: ProjectRef,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
deps: BuildDependencies
|
deps: BuildDependencies
|
||||||
): Seq[(ProjectRef, String)] =
|
): Seq[(ProjectRef, String)] =
|
||||||
val visited = (new LinkedHashSet[(ProjectRef, String)]).asScala
|
val visited = (new LinkedHashSet[(ProjectRef, String)]).asScala
|
||||||
|
|
@ -431,7 +431,7 @@ private[sbt] object ClasspathImpl {
|
||||||
def allConfigs(conf: Configuration): Seq[Configuration] =
|
def allConfigs(conf: Configuration): Seq[Configuration] =
|
||||||
Dag.topologicalSort(conf)(_.extendsConfigs)
|
Dag.topologicalSort(conf)(_.extendsConfigs)
|
||||||
|
|
||||||
def getConfigurations(p: ResolvedReference, data: Settings[Scope]): Seq[Configuration] =
|
def getConfigurations(p: ResolvedReference, data: Def.Settings): Seq[Configuration] =
|
||||||
(p / ivyConfigurations).get(data).getOrElse(Nil)
|
(p / ivyConfigurations).get(data).getOrElse(Nil)
|
||||||
|
|
||||||
def confOpt(configurations: Seq[Configuration], conf: String): Option[Configuration] =
|
def confOpt(configurations: Seq[Configuration], conf: String): Option[Configuration] =
|
||||||
|
|
@ -441,14 +441,14 @@ private[sbt] object ClasspathImpl {
|
||||||
key: TaskKey[Seq[A]],
|
key: TaskKey[Seq[A]],
|
||||||
dep: ResolvedReference,
|
dep: ResolvedReference,
|
||||||
conf: Configuration,
|
conf: Configuration,
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): Task[Seq[A]] = getClasspath(key, dep, conf.name, data)
|
): Task[Seq[A]] = getClasspath(key, dep, conf.name, data)
|
||||||
|
|
||||||
def getClasspath[A](
|
def getClasspath[A](
|
||||||
key: TaskKey[Seq[A]],
|
key: TaskKey[Seq[A]],
|
||||||
dep: ResolvedReference,
|
dep: ResolvedReference,
|
||||||
conf: String,
|
conf: String,
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): Task[Seq[A]] =
|
): Task[Seq[A]] =
|
||||||
(dep / ConfigKey(conf) / key).get(data) match {
|
(dep / ConfigKey(conf) / key).get(data) match {
|
||||||
case Some(x) => x
|
case Some(x) => x
|
||||||
|
|
|
||||||
|
|
@ -114,11 +114,9 @@ private[sbt] object Clean {
|
||||||
// This is the special portion of the task where we clear out the relevant streams
|
// This is the special portion of the task where we clear out the relevant streams
|
||||||
// and file outputs of a task.
|
// and file outputs of a task.
|
||||||
val streamsKey = scope.task.toOption.map(k => ScopedKey(scope.copy(task = Zero), k))
|
val streamsKey = scope.task.toOption.map(k => ScopedKey(scope.copy(task = Zero), k))
|
||||||
|
val stampKey = ScopedKey(scope, inputFileStamps.key)
|
||||||
val stampsKey =
|
val stampsKey =
|
||||||
extracted.structure.data.getDirect(scope, inputFileStamps.key) match {
|
if extracted.structure.data.contains(stampKey) then stampKey :: Nil else Nil
|
||||||
case Some(_) => ScopedKey(scope, inputFileStamps.key) :: Nil
|
|
||||||
case _ => Nil
|
|
||||||
}
|
|
||||||
val streamsGlobs =
|
val streamsGlobs =
|
||||||
(streamsKey.toSeq ++ stampsKey)
|
(streamsKey.toSeq ++ stampsKey)
|
||||||
.map(k => manager(k).cacheDirectory.toPath.toGlob / **)
|
.map(k => manager(k).cacheDirectory.toPath.toGlob / **)
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ object GlobalPlugin {
|
||||||
(prods ++ intcp).distinct
|
(prods ++ intcp).distinct
|
||||||
)(updateReport.value)
|
)(updateReport.value)
|
||||||
}
|
}
|
||||||
val resolvedTaskInit = taskInit.mapReferenced(Project.mapScope(Scope.replaceThis(p)))
|
val resolvedTaskInit = taskInit.mapReferenced(Project.replaceThis(p))
|
||||||
val task = resolvedTaskInit.evaluate(data)
|
val task = resolvedTaskInit.evaluate(data)
|
||||||
val roots = resolvedTaskInit.dependencies
|
val roots = resolvedTaskInit.dependencies
|
||||||
evaluate(state, structure, task, roots)
|
evaluate(state, structure, task, roots)
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,7 @@ object Inspect {
|
||||||
val extracted = Project.extract(s)
|
val extracted = Project.extract(s)
|
||||||
import extracted._
|
import extracted._
|
||||||
option match {
|
option match {
|
||||||
case Details(actual) =>
|
case Details(actual) => Project.details(extracted.structure, actual, sk)
|
||||||
Project.details(extracted.structure, actual, sk.scope, sk.key)
|
|
||||||
case DependencyTreeMode =>
|
case DependencyTreeMode =>
|
||||||
val basedir = new File(Project.session(s).current.build)
|
val basedir = new File(Project.session(s).current.build)
|
||||||
Project
|
Project
|
||||||
|
|
|
||||||
|
|
@ -29,30 +29,14 @@ object KeyIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
def aggregate(
|
def aggregate(
|
||||||
known: Iterable[ScopedKey[?]],
|
known: Set[ScopedKey[?]],
|
||||||
extra: BuildUtil[?],
|
extra: BuildUtil[?],
|
||||||
projects: Map[URI, Set[String]],
|
projects: Map[URI, Set[String]],
|
||||||
configurations: Map[String, Seq[Configuration]]
|
configurations: Map[String, Seq[Configuration]]
|
||||||
): ExtendableKeyIndex = {
|
): ExtendableKeyIndex =
|
||||||
/*
|
Aggregation
|
||||||
* Used to be:
|
.reverseAggregate(known.filter(k => validID(k.key.label)), extra)
|
||||||
* (base(projects, configurations) /: known) { (index, key) =>
|
.foldLeft(base(projects, configurations))(_.add(_))
|
||||||
* index.addAggregated(key, extra)
|
|
||||||
* }
|
|
||||||
* This was a significant serial bottleneck during project loading that we can work around by
|
|
||||||
* computing the aggregations in parallel and then bulk adding them to the index.
|
|
||||||
*/
|
|
||||||
import scala.collection.parallel.CollectionConverters.*
|
|
||||||
val toAggregate = known.par.map {
|
|
||||||
case key if validID(key.key.label) =>
|
|
||||||
Aggregation.aggregate(key, ScopeMask(), extra, reverse = true)
|
|
||||||
case _ => Nil
|
|
||||||
}
|
|
||||||
toAggregate.foldLeft(base(projects, configurations)) {
|
|
||||||
case (index, Nil) => index
|
|
||||||
case (index, keys) => keys.foldLeft(index)(_.add(_))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def base(
|
private def base(
|
||||||
projects: Map[URI, Set[String]],
|
projects: Map[URI, Set[String]],
|
||||||
|
|
@ -278,7 +262,7 @@ private[sbt] final class KeyIndex0(val data: BuildIndex) extends ExtendableKeyIn
|
||||||
|
|
||||||
def addAggregated(scoped: ScopedKey[?], extra: BuildUtil[?]): ExtendableKeyIndex =
|
def addAggregated(scoped: ScopedKey[?], extra: BuildUtil[?]): ExtendableKeyIndex =
|
||||||
if (validID(scoped.key.label)) {
|
if (validID(scoped.key.label)) {
|
||||||
val aggregateProjects = Aggregation.aggregate(scoped, ScopeMask(), extra, reverse = true)
|
val aggregateProjects = Aggregation.reverseAggregate(Set(scoped), extra)
|
||||||
aggregateProjects.foldLeft(this: ExtendableKeyIndex)(_.add(_))
|
aggregateProjects.foldLeft(this: ExtendableKeyIndex)(_.add(_))
|
||||||
} else this
|
} else this
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ object LintUnused {
|
||||||
}
|
}
|
||||||
|
|
||||||
def lintResultLines(
|
def lintResultLines(
|
||||||
result: Seq[(ScopedKey[?], String, Vector[SourcePosition])]
|
result: Seq[(ScopedKey[?], String, Seq[SourcePosition])]
|
||||||
): Vector[String] = {
|
): Vector[String] = {
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
val buffer = ListBuffer.empty[String]
|
val buffer = ListBuffer.empty[String]
|
||||||
|
|
@ -127,7 +127,7 @@ object LintUnused {
|
||||||
state: State,
|
state: State,
|
||||||
includeKeys: String => Boolean,
|
includeKeys: String => Boolean,
|
||||||
excludeKeys: String => Boolean
|
excludeKeys: String => Boolean
|
||||||
): Seq[(ScopedKey[?], String, Vector[SourcePosition])] = {
|
): Seq[(ScopedKey[?], String, Seq[SourcePosition])] = {
|
||||||
val extracted = Project.extract(state)
|
val extracted = Project.extract(state)
|
||||||
val structure = extracted.structure
|
val structure = extracted.structure
|
||||||
val display = Def.showShortKey(None) // extracted.showKey
|
val display = Def.showShortKey(None) // extracted.showKey
|
||||||
|
|
@ -135,17 +135,11 @@ object LintUnused {
|
||||||
val cMap = Def.flattenLocals(comp)
|
val cMap = Def.flattenLocals(comp)
|
||||||
val used: Set[ScopedKey[?]] = cMap.values.flatMap(_.dependencies).toSet
|
val used: Set[ScopedKey[?]] = cMap.values.flatMap(_.dependencies).toSet
|
||||||
val unused: Seq[ScopedKey[?]] = cMap.keys.filter(!used.contains(_)).toSeq
|
val unused: Seq[ScopedKey[?]] = cMap.keys.filter(!used.contains(_)).toSeq
|
||||||
val withDefinedAts: Seq[UnusedKey] = unused map { u =>
|
val withDefinedAts: Seq[UnusedKey] = unused.map { u =>
|
||||||
val definingScope = structure.data.definingScope(u.scope, u.key)
|
val data = Project.scopedKeyData(structure, u)
|
||||||
val definingScoped = definingScope match {
|
val definedAt = comp.get(data.map(_.definingKey).getOrElse(u)) match
|
||||||
case Some(sc) => ScopedKey(sc, u.key)
|
case Some(c) => definedAtString(c.settings)
|
||||||
case _ => u
|
|
||||||
}
|
|
||||||
val definedAt = comp.get(definingScoped) match {
|
|
||||||
case Some(c) => definedAtString(c.settings.toVector)
|
|
||||||
case _ => Vector.empty
|
case _ => Vector.empty
|
||||||
}
|
|
||||||
val data = Project.scopedKeyData(structure, u.scope, u.key)
|
|
||||||
UnusedKey(u, definedAt, data)
|
UnusedKey(u, definedAt, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,18 +161,16 @@ object LintUnused {
|
||||||
&& isLocallyDefined(u) =>
|
&& isLocallyDefined(u) =>
|
||||||
u
|
u
|
||||||
}
|
}
|
||||||
(unusedKeys map { u =>
|
unusedKeys.map(u => (u.scoped, display.show(u.scoped), u.positions)).sortBy(_._2)
|
||||||
(u.scoped, display.show(u.scoped), u.positions)
|
|
||||||
}).sortBy(_._2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private case class UnusedKey(
|
private case class UnusedKey(
|
||||||
scoped: ScopedKey[?],
|
scoped: ScopedKey[?],
|
||||||
positions: Vector[SourcePosition],
|
positions: Seq[SourcePosition],
|
||||||
data: Option[ScopedKeyData[?]]
|
data: Option[ScopedKeyData[?]]
|
||||||
)
|
)
|
||||||
|
|
||||||
private def definedAtString(settings: Vector[Setting[?]]): Vector[SourcePosition] = {
|
private def definedAtString(settings: Seq[Setting[?]]): Seq[SourcePosition] = {
|
||||||
settings flatMap { setting =>
|
settings flatMap { setting =>
|
||||||
setting.pos match {
|
setting.pos match {
|
||||||
case NoPosition => Vector.empty
|
case NoPosition => Vector.empty
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import sbt.internal.inc.classpath.ClasspathUtil
|
||||||
import sbt.internal.inc.{ MappedFileConverter, ScalaInstance, ZincLmUtil, ZincUtil }
|
import sbt.internal.inc.{ MappedFileConverter, ScalaInstance, ZincLmUtil, ZincUtil }
|
||||||
import sbt.internal.util.Attributed.data
|
import sbt.internal.util.Attributed.data
|
||||||
import sbt.internal.util.Types.const
|
import sbt.internal.util.Types.const
|
||||||
import sbt.internal.util.{ Attributed, Settings }
|
import sbt.internal.util.Attributed
|
||||||
import sbt.internal.server.BuildServerEvalReporter
|
import sbt.internal.server.BuildServerEvalReporter
|
||||||
import sbt.io.{ GlobFilter, IO }
|
import sbt.io.{ GlobFilter, IO }
|
||||||
import sbt.librarymanagement.ivy.{ InlineIvyConfiguration, IvyDependencyResolution, IvyPaths }
|
import sbt.librarymanagement.ivy.{ InlineIvyConfiguration, IvyDependencyResolution, IvyPaths }
|
||||||
|
|
@ -310,7 +310,7 @@ private[sbt] object Load {
|
||||||
(rootEval, bs)
|
(rootEval, bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def checkTargets(data: Settings[Scope]): Option[String] =
|
private def checkTargets(data: Def.Settings): Option[String] =
|
||||||
val dups = overlappingTargets(allTargets(data))
|
val dups = overlappingTargets(allTargets(data))
|
||||||
if (dups.isEmpty) None
|
if (dups.isEmpty) None
|
||||||
else {
|
else {
|
||||||
|
|
@ -323,7 +323,7 @@ private[sbt] object Load {
|
||||||
private def overlappingTargets(targets: Seq[(ProjectRef, File)]): Map[File, Seq[ProjectRef]] =
|
private def overlappingTargets(targets: Seq[(ProjectRef, File)]): Map[File, Seq[ProjectRef]] =
|
||||||
targets.groupBy(_._2).view.filter(_._2.size > 1).mapValues(_.map(_._1)).toMap
|
targets.groupBy(_._2).view.filter(_._2.size > 1).mapValues(_.map(_._1)).toMap
|
||||||
|
|
||||||
private def allTargets(data: Settings[Scope]): Seq[(ProjectRef, File)] = {
|
private def allTargets(data: Def.Settings): Seq[(ProjectRef, File)] = {
|
||||||
import ScopeFilter._
|
import ScopeFilter._
|
||||||
val allProjects = ScopeFilter(Make.inAnyProject)
|
val allProjects = ScopeFilter(Make.inAnyProject)
|
||||||
val targetAndRef = Def.setting { (Keys.thisProjectRef.value, Keys.target.value) }
|
val targetAndRef = Def.setting { (Keys.thisProjectRef.value, Keys.target.value) }
|
||||||
|
|
@ -366,25 +366,24 @@ private[sbt] object Load {
|
||||||
}
|
}
|
||||||
|
|
||||||
def setDefinitionKey[T](tk: Task[T], key: ScopedKey[?]): Task[T] =
|
def setDefinitionKey[T](tk: Task[T], key: ScopedKey[?]): Task[T] =
|
||||||
if (isDummy(tk)) tk else Task(tk.info.set(Keys.taskDefinitionKey, key), tk.work)
|
if (isDummy(tk)) tk else tk.set(Keys.taskDefinitionKey, key)
|
||||||
|
|
||||||
def structureIndex(
|
def structureIndex(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
settings: Seq[Setting[?]],
|
settings: Seq[Setting[?]],
|
||||||
extra: KeyIndex => BuildUtil[?],
|
extra: KeyIndex => BuildUtil[?],
|
||||||
projects: Map[URI, LoadedBuildUnit]
|
projects: Map[URI, LoadedBuildUnit]
|
||||||
): StructureIndex = {
|
): StructureIndex = {
|
||||||
val keys = Index.allKeys(settings)
|
val keys = Index.allKeys(settings)
|
||||||
val attributeKeys = Index.attributeKeys(data) ++ keys.map(_.key)
|
val attributeKeys = data.attributeKeys ++ keys.map(_.key)
|
||||||
val scopedKeys = keys ++ data.allKeys((s, k) => ScopedKey(s, k)).toVector
|
val scopedKeys = keys ++ data.keys
|
||||||
val projectsMap = projects.view.mapValues(_.defined.keySet).toMap
|
val projectsMap = projects.view.mapValues(_.defined.keySet).toMap
|
||||||
val configsMap: Map[String, Seq[Configuration]] =
|
val configsMap: Map[String, Seq[Configuration]] =
|
||||||
projects.values.flatMap(bu => bu.defined map { case (k, v) => (k, v.configurations) }).toMap
|
projects.values.flatMap(bu => bu.defined map { case (k, v) => (k, v.configurations) }).toMap
|
||||||
val keyIndex = KeyIndex(scopedKeys.toVector, projectsMap, configsMap)
|
val keyIndex = KeyIndex(scopedKeys, projectsMap, configsMap)
|
||||||
val aggIndex = KeyIndex.aggregate(scopedKeys.toVector, extra(keyIndex), projectsMap, configsMap)
|
val aggIndex = KeyIndex.aggregate(scopedKeys, extra(keyIndex), projectsMap, configsMap)
|
||||||
new StructureIndex(
|
new StructureIndex(
|
||||||
Index.stringToKeyMap(attributeKeys),
|
Index.stringToKeyMap(attributeKeys),
|
||||||
Index.taskToKeyMap(data),
|
|
||||||
Index.triggers(data),
|
Index.triggers(data),
|
||||||
keyIndex,
|
keyIndex,
|
||||||
aggIndex
|
aggIndex
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import java.io.PrintWriter
|
||||||
|
|
||||||
sealed abstract class LogManager {
|
sealed abstract class LogManager {
|
||||||
def apply(
|
def apply(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
writer: PrintWriter,
|
writer: PrintWriter,
|
||||||
|
|
@ -30,20 +30,20 @@ sealed abstract class LogManager {
|
||||||
): ManagedLogger
|
): ManagedLogger
|
||||||
@deprecated("Use alternate apply that provides a LoggerContext", "1.4.0")
|
@deprecated("Use alternate apply that provides a LoggerContext", "1.4.0")
|
||||||
def apply(
|
def apply(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
writer: PrintWriter
|
writer: PrintWriter
|
||||||
): ManagedLogger = apply(data, state, task, writer, LoggerContext.globalContext)
|
): ManagedLogger = apply(data, state, task, writer, LoggerContext.globalContext)
|
||||||
|
|
||||||
def backgroundLog(
|
def backgroundLog(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
context: LoggerContext
|
context: LoggerContext
|
||||||
): ManagedLogger
|
): ManagedLogger
|
||||||
@deprecated("Use alternate background log that provides a LoggerContext", "1.4.0")
|
@deprecated("Use alternate background log that provides a LoggerContext", "1.4.0")
|
||||||
final def backgroundLog(data: Settings[Scope], state: State, task: ScopedKey[?]): ManagedLogger =
|
final def backgroundLog(data: Def.Settings, state: State, task: ScopedKey[?]): ManagedLogger =
|
||||||
backgroundLog(data, state, task, LoggerContext.globalContext)
|
backgroundLog(data, state, task, LoggerContext.globalContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ object LogManager {
|
||||||
// This is called by mkStreams
|
// This is called by mkStreams
|
||||||
//
|
//
|
||||||
def construct(
|
def construct(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State
|
state: State
|
||||||
): (ScopedKey[?], PrintWriter) => ManagedLogger =
|
): (ScopedKey[?], PrintWriter) => ManagedLogger =
|
||||||
(task: ScopedKey[?], to: PrintWriter) => {
|
(task: ScopedKey[?], to: PrintWriter) => {
|
||||||
|
|
@ -74,7 +74,7 @@ object LogManager {
|
||||||
|
|
||||||
@deprecated("Use alternate constructBackgroundLog that provides a LoggerContext", "1.8.0")
|
@deprecated("Use alternate constructBackgroundLog that provides a LoggerContext", "1.8.0")
|
||||||
def constructBackgroundLog(
|
def constructBackgroundLog(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State
|
state: State
|
||||||
): ScopedKey[?] => ManagedLogger = {
|
): ScopedKey[?] => ManagedLogger = {
|
||||||
val context = state.get(Keys.loggerContext).getOrElse(LoggerContext.globalContext)
|
val context = state.get(Keys.loggerContext).getOrElse(LoggerContext.globalContext)
|
||||||
|
|
@ -82,7 +82,7 @@ object LogManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
def constructBackgroundLog(
|
def constructBackgroundLog(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
context: LoggerContext
|
context: LoggerContext
|
||||||
): (ScopedKey[?]) => ManagedLogger =
|
): (ScopedKey[?]) => ManagedLogger =
|
||||||
|
|
@ -119,7 +119,7 @@ object LogManager {
|
||||||
extra: AppenderSupplier
|
extra: AppenderSupplier
|
||||||
) extends LogManager {
|
) extends LogManager {
|
||||||
def apply(
|
def apply(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
to: PrintWriter,
|
to: PrintWriter,
|
||||||
|
|
@ -137,7 +137,7 @@ object LogManager {
|
||||||
)
|
)
|
||||||
|
|
||||||
def backgroundLog(
|
def backgroundLog(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
context: LoggerContext
|
context: LoggerContext
|
||||||
|
|
@ -150,16 +150,16 @@ object LogManager {
|
||||||
// to change from global being the default to overriding, switch the order of state.get and data.get
|
// to change from global being the default to overriding, switch the order of state.get and data.get
|
||||||
def getOr[T](
|
def getOr[T](
|
||||||
key: AttributeKey[T],
|
key: AttributeKey[T],
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
state: State,
|
state: State,
|
||||||
default: T
|
default: T
|
||||||
): T =
|
): T =
|
||||||
data.get(scope, key) orElse state.get(key) getOrElse default
|
data.get(ScopedKey(scope, key)).orElse(state.get(key)).getOrElse(default)
|
||||||
|
|
||||||
@deprecated("Use defaultLogger that provides a LoggerContext", "1.4.0")
|
@deprecated("Use defaultLogger that provides a LoggerContext", "1.4.0")
|
||||||
def defaultLogger(
|
def defaultLogger(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
console: Appender,
|
console: Appender,
|
||||||
|
|
@ -170,7 +170,7 @@ object LogManager {
|
||||||
defaultLogger(data, state, task, console, backed, relay, extra, LoggerContext.globalContext)
|
defaultLogger(data, state, task, console, backed, relay, extra, LoggerContext.globalContext)
|
||||||
// This is the main function that is used to generate the logger for tasks.
|
// This is the main function that is used to generate the logger for tasks.
|
||||||
def defaultLogger(
|
def defaultLogger(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
console: Appender,
|
console: Appender,
|
||||||
|
|
@ -242,7 +242,7 @@ object LogManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
def backgroundLog(
|
def backgroundLog(
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
state: State,
|
state: State,
|
||||||
task: ScopedKey[?],
|
task: ScopedKey[?],
|
||||||
console: Appender,
|
console: Appender,
|
||||||
|
|
@ -271,7 +271,7 @@ object LogManager {
|
||||||
|
|
||||||
// TODO: Fix this
|
// TODO: Fix this
|
||||||
// if global logging levels are not explicitly set, set them from project settings
|
// if global logging levels are not explicitly set, set them from project settings
|
||||||
// private[sbt] def setGlobalLogLevels(s: State, data: Settings[Scope]): State =
|
// private[sbt] def setGlobalLogLevels(s: State, data: Def.Settings): State =
|
||||||
// if (hasExplicitGlobalLogLevels(s))
|
// if (hasExplicitGlobalLogLevels(s))
|
||||||
// s
|
// s
|
||||||
// else {
|
// else {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ private[sbt] case class ProjectQuery(
|
||||||
val scalaMatches =
|
val scalaMatches =
|
||||||
params.get(Keys.scalaBinaryVersion.key) match
|
params.get(Keys.scalaBinaryVersion.key) match
|
||||||
case Some(expected) =>
|
case Some(expected) =>
|
||||||
val actualSbv = structure.data.get(Scope.ThisScope.rescope(p), scalaBinaryVersion.key)
|
val actualSbv =
|
||||||
|
structure.data.get(Def.ScopedKey(Scope.ThisScope.rescope(p), scalaBinaryVersion.key))
|
||||||
actualSbv match
|
actualSbv match
|
||||||
case Some(sbv) => sbv == expected
|
case Some(sbv) => sbv == expected
|
||||||
case None => true
|
case None => true
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
package sbt
|
package sbt
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import sbt.internal.util.{ AttributeKey, complete, Relation, Settings, Util }
|
import sbt.internal.util.{ AttributeKey, complete, Relation, Util }
|
||||||
import sbt.util.Show
|
import sbt.util.Show
|
||||||
import sbt.librarymanagement.Configuration
|
import sbt.librarymanagement.Configuration
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ private[sbt] object SettingCompletions {
|
||||||
* The last part of the completion will generate a template for the value or function literal that will initialize the setting or task.
|
* The last part of the completion will generate a template for the value or function literal that will initialize the setting or task.
|
||||||
*/
|
*/
|
||||||
def settingParser(
|
def settingParser(
|
||||||
settings: Settings[Scope],
|
settings: Def.Settings,
|
||||||
rawKeyMap: Map[String, AttributeKey[?]],
|
rawKeyMap: Map[String, AttributeKey[?]],
|
||||||
context: ResolvedProject,
|
context: ResolvedProject,
|
||||||
): Parser[String] = {
|
): Parser[String] = {
|
||||||
|
|
@ -156,7 +156,7 @@ private[sbt] object SettingCompletions {
|
||||||
/** Parser for a Scope+AttributeKey (ScopedKey). */
|
/** Parser for a Scope+AttributeKey (ScopedKey). */
|
||||||
def scopedKeyParser(
|
def scopedKeyParser(
|
||||||
keyMap: Map[String, AttributeKey[?]],
|
keyMap: Map[String, AttributeKey[?]],
|
||||||
settings: Settings[Scope],
|
settings: Def.Settings,
|
||||||
context: ResolvedProject
|
context: ResolvedProject
|
||||||
): Parser[ScopedKey[?]] = {
|
): Parser[ScopedKey[?]] = {
|
||||||
val cutoff = KeyRanks.MainCutoff
|
val cutoff = KeyRanks.MainCutoff
|
||||||
|
|
@ -195,15 +195,11 @@ private[sbt] object SettingCompletions {
|
||||||
*/
|
*/
|
||||||
def scopeParser(
|
def scopeParser(
|
||||||
key: AttributeKey[?],
|
key: AttributeKey[?],
|
||||||
settings: Settings[Scope],
|
settings: Def.Settings,
|
||||||
context: ResolvedProject
|
context: ResolvedProject
|
||||||
): Parser[Scope] = {
|
): Parser[Scope] = {
|
||||||
val data = settings.data
|
val definedScopes = settings.keys.collect { case sk if sk.key == key => sk.scope }
|
||||||
val allScopes = data.keys.toSeq
|
scope(settings.scopes.toSeq, definedScopes.toSeq, context)
|
||||||
val definedScopes = data.toSeq flatMap { case (scope, attrs) =>
|
|
||||||
if attrs.contains(key) then scope :: Nil else Nil
|
|
||||||
}
|
|
||||||
scope(allScopes, definedScopes, context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def scope(
|
private def scope(
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,8 @@ object SettingGraph {
|
||||||
compiled(structure.settings, false)(using structure.delegates, structure.scopeLocal, display)
|
compiled(structure.settings, false)(using structure.delegates, structure.scopeLocal, display)
|
||||||
)
|
)
|
||||||
def loop(scoped: ScopedKey[?], generation: Int): SettingGraph = {
|
def loop(scoped: ScopedKey[?], generation: Int): SettingGraph = {
|
||||||
val key = scoped.key
|
val data = Project.scopedKeyData(structure, scoped)
|
||||||
val scope = scoped.scope
|
val definedIn = data.map(d => display.show(d.definingKey))
|
||||||
val definedIn = structure.data.definingScope(scope, key) map { sc =>
|
|
||||||
display.show(ScopedKey(sc, key))
|
|
||||||
}
|
|
||||||
val depends = cMap.get(scoped) match {
|
val depends = cMap.get(scoped) match {
|
||||||
case Some(c) => c.dependencies.toSet; case None => Set.empty
|
case Some(c) => c.dependencies.toSet; case None => Set.empty
|
||||||
}
|
}
|
||||||
|
|
@ -39,8 +36,8 @@ object SettingGraph {
|
||||||
SettingGraph(
|
SettingGraph(
|
||||||
display.show(scoped),
|
display.show(scoped),
|
||||||
definedIn,
|
definedIn,
|
||||||
Project.scopedKeyData(structure, scope, key),
|
data,
|
||||||
key.description,
|
scoped.key.description,
|
||||||
basedir,
|
basedir,
|
||||||
depends map { (x: ScopedKey[?]) =>
|
depends map { (x: ScopedKey[?]) =>
|
||||||
loop(x, generation + 1)
|
loop(x, generation + 1)
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ import Keys.taskDefinitionKey
|
||||||
private[sbt] object TaskName {
|
private[sbt] object TaskName {
|
||||||
def name(node: Task[?]): String = definedName(node).getOrElse(anonymousName(node))
|
def name(node: Task[?]): String = definedName(node).getOrElse(anonymousName(node))
|
||||||
def definedName(node: Task[?]): Option[String] =
|
def definedName(node: Task[?]): Option[String] =
|
||||||
node.info.name.orElse(transformNode(node).map(displayFull))
|
node.name.orElse(transformNode(node).map(displayFull))
|
||||||
def anonymousName(node: TaskId[?]): String =
|
def anonymousName(node: TaskId[?]): String =
|
||||||
"<anon-" + System.identityHashCode(node).toHexString + ">"
|
"<anon-" + System.identityHashCode(node).toHexString + ">"
|
||||||
def transformNode(node: Task[?]): Option[ScopedKey[?]] =
|
def transformNode(node: Task[?]): Option[ScopedKey[?]] =
|
||||||
node.info.attributes.get(taskDefinitionKey)
|
node.get(taskDefinitionKey)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import sbt.ProjectExtra.*
|
||||||
import sbt.SlashSyntax0.given
|
import sbt.SlashSyntax0.given
|
||||||
import sbt.internal.io.Source
|
import sbt.internal.io.Source
|
||||||
import sbt.internal.nio.Globs
|
import sbt.internal.nio.Globs
|
||||||
import sbt.internal.util.AttributeMap
|
|
||||||
import sbt.internal.util.complete.Parser
|
import sbt.internal.util.complete.Parser
|
||||||
import sbt.nio.FileStamper
|
import sbt.nio.FileStamper
|
||||||
import sbt.nio.Keys._
|
import sbt.nio.Keys._
|
||||||
|
|
@ -54,7 +53,7 @@ private[sbt] object WatchTransitiveDependencies {
|
||||||
val state: State
|
val state: State
|
||||||
) {
|
) {
|
||||||
def structure: BuildStructure = extracted.structure
|
def structure: BuildStructure = extracted.structure
|
||||||
def data: Map[Scope, AttributeMap] = extracted.structure.data.data
|
def data: Settings = extracted.structure.data
|
||||||
}
|
}
|
||||||
|
|
||||||
private def argumentsImpl(
|
private def argumentsImpl(
|
||||||
|
|
@ -113,18 +112,18 @@ private[sbt] object WatchTransitiveDependencies {
|
||||||
val keys = collectKeys(args, allKeys, Set.empty, Set.empty)
|
val keys = collectKeys(args, allKeys, Set.empty, Set.empty)
|
||||||
def getDynamicInputs(scopedKey: ScopedKey[Seq[Glob]], trigger: Boolean): Seq[DynamicInput] = {
|
def getDynamicInputs(scopedKey: ScopedKey[Seq[Glob]], trigger: Boolean): Seq[DynamicInput] = {
|
||||||
data
|
data
|
||||||
.get(scopedKey.scope)
|
.getDirect(scopedKey)
|
||||||
.map { am =>
|
.map { globs =>
|
||||||
am.get(scopedKey.key) match {
|
if (!trigger) {
|
||||||
case Some(globs: Seq[Glob]) =>
|
val stamper =
|
||||||
if (!trigger) {
|
data.getDirect(scopedKey.copy(key = inputFileStamper.key)).getOrElse(FileStamper.Hash)
|
||||||
val stamper = am.get(inputFileStamper.key).getOrElse(FileStamper.Hash)
|
val forceTrigger =
|
||||||
val forceTrigger = am.get(watchForceTriggerOnAnyChange.key).getOrElse(false)
|
data
|
||||||
globs.map(g => DynamicInput(g, stamper, forceTrigger))
|
.getDirect(scopedKey.copy(key = watchForceTriggerOnAnyChange.key))
|
||||||
} else {
|
.getOrElse(false)
|
||||||
globs.map(g => DynamicInput(g, FileStamper.LastModified, forceTrigger = true))
|
globs.map(g => DynamicInput(g, stamper, forceTrigger))
|
||||||
}
|
} else {
|
||||||
case None => Nil: Seq[DynamicInput]
|
globs.map(g => DynamicInput(g, FileStamper.LastModified, forceTrigger = true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.getOrElse(Nil)
|
.getOrElse(Nil)
|
||||||
|
|
@ -148,21 +147,15 @@ private[sbt] object WatchTransitiveDependencies {
|
||||||
.toIndexedSeq
|
.toIndexedSeq
|
||||||
val projects = projectScopes.flatMap(_.project.toOption).distinct.toSet
|
val projects = projectScopes.flatMap(_.project.toOption).distinct.toSet
|
||||||
val scopes: Seq[Either[Scope, Seq[Glob]]] =
|
val scopes: Seq[Either[Scope, Seq[Glob]]] =
|
||||||
data.flatMap { case (s, am) =>
|
data.scopes.toSeq
|
||||||
if (s == Scope.Global || s.project.toOption.exists(projects.contains))
|
.filter(s => s == Scope.Global || s.project.toOption.exists(projects.contains))
|
||||||
am.get(Keys.watchSources.key) match {
|
.flatMap { s =>
|
||||||
case Some(k) =>
|
data.getDirect(ScopedKey(s, Keys.watchSources.key)).map { task =>
|
||||||
k.work match {
|
task.work match
|
||||||
// Avoid extracted.runTask if possible.
|
case a: Action.Pure[Seq[Watched.WatchSource]] => Right(a.f().map(_.toGlob))
|
||||||
case Action.Pure(w, _) => Some(Right(w().map(_.toGlob)))
|
case _ => Left(s)
|
||||||
case _ => Some(Left(s))
|
|
||||||
}
|
|
||||||
case _ => None
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}.toSeq
|
|
||||||
def toDynamicInput(glob: Glob): DynamicInput =
|
def toDynamicInput(glob: Glob): DynamicInput =
|
||||||
DynamicInput(glob, FileStamper.LastModified, forceTrigger = true)
|
DynamicInput(glob, FileStamper.LastModified, forceTrigger = true)
|
||||||
scopes.flatMap {
|
scopes.flatMap {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import sjsonnew._
|
||||||
import sjsonnew.support.scalajson.unsafe._
|
import sjsonnew.support.scalajson.unsafe._
|
||||||
|
|
||||||
object SettingQuery {
|
object SettingQuery {
|
||||||
import sbt.internal.util.{ AttributeKey, Settings }
|
import sbt.internal.util.AttributeKey
|
||||||
import sbt.internal.util.complete.{ DefaultParsers, Parser }, DefaultParsers._
|
import sbt.internal.util.complete.{ DefaultParsers, Parser }, DefaultParsers._
|
||||||
import sbt.Def.{ showBuildRelativeKey2, ScopedKey }
|
import sbt.Def.{ showBuildRelativeKey2, ScopedKey }
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ object SettingQuery {
|
||||||
currentBuild: URI,
|
currentBuild: URI,
|
||||||
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
||||||
keyMap: Map[String, AttributeKey[?]],
|
keyMap: Map[String, AttributeKey[?]],
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): Parser[ParsedKey] =
|
): Parser[ParsedKey] =
|
||||||
scopedKeyFull(index, currentBuild, defaultConfigs, keyMap) flatMap { choices =>
|
scopedKeyFull(index, currentBuild, defaultConfigs, keyMap) flatMap { choices =>
|
||||||
Act.select(choices, data)(showBuildRelativeKey2(currentBuild))
|
Act.select(choices, data)(showBuildRelativeKey2(currentBuild))
|
||||||
|
|
@ -81,7 +81,7 @@ object SettingQuery {
|
||||||
currentBuild: URI,
|
currentBuild: URI,
|
||||||
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
defaultConfigs: Option[ResolvedReference] => Seq[String],
|
||||||
keyMap: Map[String, AttributeKey[?]],
|
keyMap: Map[String, AttributeKey[?]],
|
||||||
data: Settings[Scope]
|
data: Def.Settings
|
||||||
): Parser[ScopedKey[?]] =
|
): Parser[ScopedKey[?]] =
|
||||||
scopedKeySelected(index, currentBuild, defaultConfigs, keyMap, data).map(_.key)
|
scopedKeySelected(index, currentBuild, defaultConfigs, keyMap, data).map(_.key)
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ object SettingQuery {
|
||||||
|
|
||||||
def getSettingValue[A](structure: BuildStructure, key: Def.ScopedKey[A]): Either[String, A] =
|
def getSettingValue[A](structure: BuildStructure, key: Def.ScopedKey[A]): Either[String, A] =
|
||||||
structure.data
|
structure.data
|
||||||
.get(key.scope, key.key)
|
.get(key)
|
||||||
.toRight(s"Key ${Def.displayFull(key)} not found")
|
.toRight(s"Key ${Def.displayFull(key)} not found")
|
||||||
.flatMap {
|
.flatMap {
|
||||||
case _: Task[_] => Left(s"Key ${Def.displayFull(key)} is a task, can only query settings")
|
case _: Task[_] => Left(s"Key ${Def.displayFull(key)} is a task, can only query settings")
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ private[sbt] object Settings {
|
||||||
* @return the setting with the task definition
|
* @return the setting with the task definition
|
||||||
*/
|
*/
|
||||||
private def addTaskDefinition[T](setting: Def.Setting[Task[T]]): Def.Setting[Task[T]] =
|
private def addTaskDefinition[T](setting: Def.Setting[Task[T]]): Def.Setting[Task[T]] =
|
||||||
setting.mapInit((sk, task) => Task(task.info.set(taskDefinitionKey, sk), task.work))
|
setting.mapInit((sk, task) => task.set(taskDefinitionKey, sk))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all of the paths described by a glob along with their basic file attributes.
|
* Returns all of the paths described by a glob along with their basic file attributes.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ import sbt.internal.util.{
|
||||||
ConsoleOut,
|
ConsoleOut,
|
||||||
GlobalLogging,
|
GlobalLogging,
|
||||||
MainAppender,
|
MainAppender,
|
||||||
Settings,
|
|
||||||
Terminal,
|
Terminal,
|
||||||
}
|
}
|
||||||
import sbt.internal.inc.PlainVirtualFileConverter
|
import sbt.internal.inc.PlainVirtualFileConverter
|
||||||
|
|
@ -97,7 +96,7 @@ object FakeState {
|
||||||
val delegates: (Scope) => Seq[Scope] = _ => Nil
|
val delegates: (Scope) => Seq[Scope] = _ => Nil
|
||||||
val scopeLocal: Def.ScopeLocal = _ => Nil
|
val scopeLocal: Def.ScopeLocal = _ => Nil
|
||||||
|
|
||||||
val (cMap, data: Settings[Scope]) =
|
val (cMap, data: Def.Settings) =
|
||||||
Def.makeWithCompiledMap(settings)(using delegates, scopeLocal, Def.showFullKey)
|
Def.makeWithCompiledMap(settings)(using delegates, scopeLocal, Def.showFullKey)
|
||||||
val extra: KeyIndex => BuildUtil[?] = (keyIndex) =>
|
val extra: KeyIndex => BuildUtil[?] = (keyIndex) =>
|
||||||
BuildUtil(base.toURI, Map.empty, keyIndex, data)
|
BuildUtil(base.toURI, Map.empty, keyIndex, data)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ package sbt
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import Def.{ ScopedKey, Setting }
|
import Def.{ ScopedKey, Setting }
|
||||||
import sbt.internal.util.{ AttributeKey, AttributeMap, Relation, Settings }
|
import sbt.internal.util.{ AttributeKey, Relation }
|
||||||
import sbt.internal.util.Types.{ const, some }
|
import sbt.internal.util.Types.{ const, some }
|
||||||
import sbt.internal.util.complete.Parser
|
import sbt.internal.util.complete.Parser
|
||||||
import sbt.librarymanagement.Configuration
|
import sbt.librarymanagement.Configuration
|
||||||
|
|
@ -59,17 +59,18 @@ abstract class TestBuild {
|
||||||
sealed case class Structure(
|
sealed case class Structure(
|
||||||
env: Env,
|
env: Env,
|
||||||
current: ProjectRef,
|
current: ProjectRef,
|
||||||
data: Settings[Scope],
|
data: Def.Settings,
|
||||||
keyIndex: KeyIndex,
|
keyIndex: KeyIndex,
|
||||||
keyMap: Map[String, AttributeKey[?]]
|
keyMap: Map[String, AttributeKey[?]]
|
||||||
) {
|
) {
|
||||||
override def toString =
|
override def toString =
|
||||||
env.toString + "\n" + "current: " + current + "\nSettings:\n\t" + showData + keyMap.keys
|
env.toString + "\n" + "current: " + current + "\nSettings:\n\t" + showData + keyMap.keys
|
||||||
.mkString("All keys:\n\t", ", ", "")
|
.mkString("All keys:\n\t", ", ", "")
|
||||||
def showKeys(map: AttributeMap): String = map.keys.mkString("\n\t ", ",", "\n")
|
def showKeys(keys: Iterable[AttributeKey[?]]): String = keys.mkString("\n\t ", ",", "\n")
|
||||||
def showData: String = {
|
def showData: String = {
|
||||||
val scopeStrings =
|
val scopeStrings =
|
||||||
for ((scope, map) <- data.data) yield (Scope.display(scope, "<key>"), showKeys(map))
|
for (scope, keys) <- data.keys.groupMap(_.scope)(_.key)
|
||||||
|
yield (Scope.display(scope, "<key>"), showKeys(keys))
|
||||||
scopeStrings.toSeq.sorted.map(t => t._1 + t._2).mkString("\n\t")
|
scopeStrings.toSeq.sorted.map(t => t._1 + t._2).mkString("\n\t")
|
||||||
}
|
}
|
||||||
val extra: BuildUtil[Proj] = {
|
val extra: BuildUtil[Proj] = {
|
||||||
|
|
@ -86,11 +87,10 @@ abstract class TestBuild {
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy val allAttributeKeys: Set[AttributeKey[?]] = {
|
lazy val allAttributeKeys: Set[AttributeKey[?]] = {
|
||||||
val x = data.data.values.flatMap(_.keys).toSet
|
if (data.attributeKeys.isEmpty) {
|
||||||
if (x.isEmpty) {
|
|
||||||
sys.error("allAttributeKeys is empty")
|
sys.error("allAttributeKeys is empty")
|
||||||
}
|
}
|
||||||
x
|
data.attributeKeys
|
||||||
}
|
}
|
||||||
lazy val (taskAxes, zeroTaskAxis, onlyTaskAxis, multiTaskAxis) = {
|
lazy val (taskAxes, zeroTaskAxis, onlyTaskAxis, multiTaskAxis) = {
|
||||||
import collection.mutable
|
import collection.mutable
|
||||||
|
|
@ -98,11 +98,10 @@ abstract class TestBuild {
|
||||||
|
|
||||||
// task axis of Scope is set to Zero and the value of the second map is the original task axis
|
// task axis of Scope is set to Zero and the value of the second map is the original task axis
|
||||||
val taskAxesMappings =
|
val taskAxesMappings =
|
||||||
for ((scope, keys) <- data.data; key <- keys.keys)
|
for
|
||||||
yield (ScopedKey(scope.copy(task = Zero), key), scope.task): (
|
(scope, keys) <- data.keys.groupMap(_.scope)(_.key)
|
||||||
ScopedKey[?],
|
key <- keys
|
||||||
ScopeAxis[AttributeKey[?]]
|
yield (ScopedKey(scope.copy(task = Zero), key), scope.task)
|
||||||
)
|
|
||||||
|
|
||||||
val taskAxes = Relation.empty ++ taskAxesMappings
|
val taskAxes = Relation.empty ++ taskAxesMappings
|
||||||
val zero = new HashSet[ScopedKey[?]]
|
val zero = new HashSet[ScopedKey[?]]
|
||||||
|
|
@ -240,15 +239,14 @@ abstract class TestBuild {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val data = Def.makeWithCompiledMap(settings)(using env.delegates, const(Nil), display)._2
|
val data = Def.makeWithCompiledMap(settings)(using env.delegates, const(Nil), display)._2
|
||||||
val keys = data.allKeys((s, key) => ScopedKey(s, key))
|
val keyMap = data.keys.map(k => (k.key.label, k.key)).toMap[String, AttributeKey[?]]
|
||||||
val keyMap = keys.map(k => (k.key.label, k.key)).toMap[String, AttributeKey[?]]
|
|
||||||
val projectsMap = env.builds.map(b => (b.uri, b.projects.map(_.id).toSet)).toMap
|
val projectsMap = env.builds.map(b => (b.uri, b.projects.map(_.id).toSet)).toMap
|
||||||
val confs = for {
|
val confs = for {
|
||||||
b <- env.builds
|
b <- env.builds
|
||||||
p <- b.projects
|
p <- b.projects
|
||||||
} yield p.id -> p.configurations
|
} yield p.id -> p.configurations
|
||||||
val confMap = confs.toMap
|
val confMap = confs.toMap
|
||||||
Structure(env, current, data, KeyIndex(keys, projectsMap, confMap), keyMap)
|
Structure(env, current, data, KeyIndex(data.keys, projectsMap, confMap), keyMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy val mkEnv: Gen[Env] = {
|
lazy val mkEnv: Gen[Env] = {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
package sbt
|
package sbt
|
||||||
|
|
||||||
trait Import {
|
trait Import {
|
||||||
|
type Settings = Def.Settings
|
||||||
type Setting[T] = Def.Setting[T]
|
type Setting[T] = Def.Setting[T]
|
||||||
type ScopedKey[T] = Def.ScopedKey[T]
|
type ScopedKey[T] = Def.ScopedKey[T]
|
||||||
type SettingsDefinition = Def.SettingsDefinition
|
type SettingsDefinition = Def.SettingsDefinition
|
||||||
|
|
@ -146,7 +147,7 @@ trait Import {
|
||||||
// type Dag[A <: Dag[A]] = sbt.internal.util.Dag[A]
|
// type Dag[A <: Dag[A]] = sbt.internal.util.Dag[A]
|
||||||
type DelegatingPMap[K[_], V[_]] = sbt.internal.util.DelegatingPMap[K, V]
|
type DelegatingPMap[K[_], V[_]] = sbt.internal.util.DelegatingPMap[K, V]
|
||||||
val ErrorHandling = sbt.internal.util.ErrorHandling
|
val ErrorHandling = sbt.internal.util.ErrorHandling
|
||||||
type EvaluateSettings[S] = sbt.internal.util.EvaluateSettings[S]
|
// type EvaluateSettings[I <: Init] = sbt.internal.util.EvaluateSettings[I]
|
||||||
val EvaluationState = sbt.internal.util.EvaluationState
|
val EvaluationState = sbt.internal.util.EvaluationState
|
||||||
val ExitHook = sbt.internal.util.ExitHook
|
val ExitHook = sbt.internal.util.ExitHook
|
||||||
type ExitHook = sbt.internal.util.ExitHook
|
type ExitHook = sbt.internal.util.ExitHook
|
||||||
|
|
@ -168,7 +169,7 @@ trait Import {
|
||||||
type IDSet[T] = sbt.internal.util.IDSet[T]
|
type IDSet[T] = sbt.internal.util.IDSet[T]
|
||||||
val IMap = sbt.internal.util.IMap
|
val IMap = sbt.internal.util.IMap
|
||||||
type IMap[K[_], V[_]] = sbt.internal.util.IMap[K, V]
|
type IMap[K[_], V[_]] = sbt.internal.util.IMap[K, V]
|
||||||
type Init[S] = sbt.internal.util.Init[S]
|
type Init = sbt.internal.util.Init
|
||||||
type JLine = sbt.internal.util.JLine
|
type JLine = sbt.internal.util.JLine
|
||||||
// val KCons = sbt.internal.util.KCons
|
// val KCons = sbt.internal.util.KCons
|
||||||
// type KCons[H, +T <: KList[M], +M[_]] = sbt.internal.util.KCons[H, T, M]
|
// type KCons[H, +T <: KList[M], +M[_]] = sbt.internal.util.KCons[H, T, M]
|
||||||
|
|
@ -193,7 +194,6 @@ trait Import {
|
||||||
val Relation = sbt.internal.util.Relation
|
val Relation = sbt.internal.util.Relation
|
||||||
type Relation[A, B] = sbt.internal.util.Relation[A, B]
|
type Relation[A, B] = sbt.internal.util.Relation[A, B]
|
||||||
val ScalaKeywords = sbt.internal.util.ScalaKeywords
|
val ScalaKeywords = sbt.internal.util.ScalaKeywords
|
||||||
type Settings[S] = sbt.internal.util.Settings[S]
|
|
||||||
type SharedAttributeKey[T] = sbt.internal.util.SharedAttributeKey[T]
|
type SharedAttributeKey[T] = sbt.internal.util.SharedAttributeKey[T]
|
||||||
val Signals = sbt.internal.util.Signals
|
val Signals = sbt.internal.util.Signals
|
||||||
val SimpleReader = sbt.internal.util.SimpleReader
|
val SimpleReader = sbt.internal.util.SimpleReader
|
||||||
|
|
|
||||||
|
|
@ -14,32 +14,51 @@ import ConcurrentRestrictions.{ Tag, TagMap, tagsKey }
|
||||||
import sbt.util.Monad
|
import sbt.util.Monad
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines metadata `info` and a computation `work` to define a task.
|
* Combines metadata `attributes` and a computation `work` to define a task.
|
||||||
*/
|
*/
|
||||||
final case class Task[A](info: Info[A], work: Action[A]) extends TaskId[A]:
|
final class Task[A](
|
||||||
override def toString = info.name getOrElse ("Task(" + info + ")")
|
val attributes: AttributeMap,
|
||||||
override def hashCode = info.hashCode
|
val post: A => AttributeMap,
|
||||||
|
val work: Action[A]
|
||||||
|
) extends TaskId[A]:
|
||||||
|
override def toString = name.getOrElse(s"Task($attributes)")
|
||||||
|
|
||||||
|
def name: Option[String] = get(Task.Name)
|
||||||
|
def description: Option[String] = get(Task.Description)
|
||||||
|
def get[B](key: AttributeKey[B]): Option[B] = attributes.get(key)
|
||||||
|
def getOrElse[B](key: AttributeKey[B], default: => B): B = attributes.getOrElse(key, default)
|
||||||
|
|
||||||
|
def setName(name: String): Task[A] = set(Task.Name, name)
|
||||||
|
def setDescription(description: String): Task[A] = set(Task.Description, description)
|
||||||
|
def set[B](key: AttributeKey[B], value: B) =
|
||||||
|
new Task(attributes.put(key, value), post, work)
|
||||||
|
|
||||||
|
def postTransform(f: (A, AttributeMap) => AttributeMap): Task[A] =
|
||||||
|
new Task(attributes, a => f(a, post(a)), work)
|
||||||
|
|
||||||
def tag(tags: Tag*): Task[A] = tagw(tags.map(t => (t, 1))*)
|
def tag(tags: Tag*): Task[A] = tagw(tags.map(t => (t, 1))*)
|
||||||
def tagw(tags: (Tag, Int)*): Task[A] = {
|
def tagw(tags: (Tag, Int)*): Task[A] =
|
||||||
val tgs: TagMap = info.get(tagsKey).getOrElse(TagMap.empty)
|
val tgs: TagMap = get(tagsKey).getOrElse(TagMap.empty)
|
||||||
val value = tags.foldLeft(tgs)((acc, tag) => acc + tag)
|
val value = tags.foldLeft(tgs)((acc, tag) => acc + tag)
|
||||||
val nextInfo = info.set(tagsKey, value)
|
set(tagsKey, value)
|
||||||
withInfo(info = nextInfo)
|
def tags: TagMap = get(tagsKey).getOrElse(TagMap.empty)
|
||||||
}
|
|
||||||
|
|
||||||
def tags: TagMap = info.get(tagsKey).getOrElse(TagMap.empty)
|
|
||||||
def name: Option[String] = info.name
|
|
||||||
|
|
||||||
def attributes: AttributeMap = info.attributes
|
|
||||||
|
|
||||||
private[sbt] def withInfo(info: Info[A]): Task[A] =
|
|
||||||
Task(info = info, work = this.work)
|
|
||||||
end Task
|
end Task
|
||||||
|
|
||||||
object Task:
|
object Task:
|
||||||
import sbt.std.TaskExtra.*
|
import sbt.std.TaskExtra.*
|
||||||
|
|
||||||
|
def apply[A](work: Action[A]): Task[A] =
|
||||||
|
new Task[A](AttributeMap.empty, defaultAttributeMap, work)
|
||||||
|
|
||||||
|
def apply[A](attributes: AttributeMap, work: Action[A]): Task[A] =
|
||||||
|
new Task[A](attributes, defaultAttributeMap, work)
|
||||||
|
|
||||||
|
def unapply[A](task: Task[A]): Option[Action[A]] = Some(task.work)
|
||||||
|
|
||||||
|
val Name = AttributeKey[String]("name")
|
||||||
|
val Description = AttributeKey[String]("description")
|
||||||
|
val defaultAttributeMap = const(AttributeMap.empty)
|
||||||
|
|
||||||
given taskMonad: Monad[Task] with
|
given taskMonad: Monad[Task] with
|
||||||
type F[a] = Task[a]
|
type F[a] = Task[a]
|
||||||
override def pure[A1](a: () => A1): Task[A1] = toTask(a)
|
override def pure[A1](a: () => A1): Task[A1] = toTask(a)
|
||||||
|
|
@ -54,34 +73,3 @@ object Task:
|
||||||
override def flatMap[A1, A2](in: F[A1])(f: A1 => F[A2]): F[A2] = in.flatMap(f)
|
override def flatMap[A1, A2](in: F[A1])(f: A1 => F[A2]): F[A2] = in.flatMap(f)
|
||||||
override def flatten[A1](in: Task[Task[A1]]): Task[A1] = in.flatMap(identity)
|
override def flatten[A1](in: Task[Task[A1]]): Task[A1] = in.flatMap(identity)
|
||||||
end Task
|
end Task
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to provide information about a task, such as the name, description, and tags for controlling
|
|
||||||
* concurrent execution.
|
|
||||||
* @param attributes
|
|
||||||
* Arbitrary user-defined key/value pairs describing this task
|
|
||||||
* @param post
|
|
||||||
* a transformation that takes the result of evaluating this task and produces user-defined
|
|
||||||
* key/value pairs.
|
|
||||||
*/
|
|
||||||
final case class Info[T](
|
|
||||||
attributes: AttributeMap = AttributeMap.empty,
|
|
||||||
post: T => AttributeMap = Info.defaultAttributeMap
|
|
||||||
) {
|
|
||||||
import Info._
|
|
||||||
def name = attributes.get(Name)
|
|
||||||
def description = attributes.get(Description)
|
|
||||||
def setName(n: String) = set(Name, n)
|
|
||||||
def setDescription(d: String) = set(Description, d)
|
|
||||||
def set[A](key: AttributeKey[A], value: A) = copy(attributes = this.attributes.put(key, value))
|
|
||||||
def get[A](key: AttributeKey[A]): Option[A] = attributes.get(key)
|
|
||||||
def postTransform(f: (T, AttributeMap) => AttributeMap) = copy(post = (t: T) => f(t, post(t)))
|
|
||||||
|
|
||||||
override def toString = if (attributes.isEmpty) "_" else attributes.toString
|
|
||||||
}
|
|
||||||
|
|
||||||
object Info:
|
|
||||||
val Name = AttributeKey[String]("name")
|
|
||||||
val Description = AttributeKey[String]("description")
|
|
||||||
val defaultAttributeMap = const(AttributeMap.empty)
|
|
||||||
end Info
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ trait TaskExtra0 {
|
||||||
joinTasks0[Any](existToAny(in))
|
joinTasks0[Any](existToAny(in))
|
||||||
private[sbt] def joinTasks0[S](in: Seq[Task[S]]): JoinTask[S, Seq] = new JoinTask[S, Seq] {
|
private[sbt] def joinTasks0[S](in: Seq[Task[S]]): JoinTask[S, Seq] = new JoinTask[S, Seq] {
|
||||||
def join: Task[Seq[S]] =
|
def join: Task[Seq[S]] =
|
||||||
Task[Seq[S]](Info(), Action.Join(in, (s: Seq[Result[S]]) => Right(TaskExtra.all(s))))
|
Task[Seq[S]](Action.Join(in, (s: Seq[Result[S]]) => Right(TaskExtra.all(s))))
|
||||||
def reduced(f: (S, S) => S): Task[S] = TaskExtra.reduced(in.toIndexedSeq, f)
|
def reduced(f: (S, S) => S): Task[S] = TaskExtra.reduced(in.toIndexedSeq, f)
|
||||||
}
|
}
|
||||||
private[sbt] def existToAny(in: Seq[Task[?]]): Seq[Task[Any]] = in.asInstanceOf[Seq[Task[Any]]]
|
private[sbt] def existToAny(in: Seq[Task[?]]): Seq[Task[Any]] = in.asInstanceOf[Seq[Task[Any]]]
|
||||||
|
|
@ -114,8 +114,8 @@ trait TaskExtra extends TaskExtra0 {
|
||||||
final def constant[T](t: T): Task[T] = task(t)
|
final def constant[T](t: T): Task[T] = task(t)
|
||||||
|
|
||||||
final def task[T](f: => T): Task[T] = toTask(() => f)
|
final def task[T](f: => T): Task[T] = toTask(() => f)
|
||||||
final implicit def toTask[T](f: () => T): Task[T] = Task(Info(), Action.Pure(f, false))
|
final implicit def toTask[T](f: () => T): Task[T] = Task(Action.Pure(f, false))
|
||||||
final def inlineTask[T](value: T): Task[T] = Task(Info(), Action.Pure(() => value, true))
|
final def inlineTask[T](value: T): Task[T] = Task(Action.Pure(() => value, true))
|
||||||
|
|
||||||
final implicit def upcastTask[A >: B, B](t: Task[B]): Task[A] = t mapN { x =>
|
final implicit def upcastTask[A >: B, B](t: Task[B]): Task[A] = t mapN { x =>
|
||||||
x: A
|
x: A
|
||||||
|
|
@ -131,7 +131,7 @@ trait TaskExtra extends TaskExtra0 {
|
||||||
|
|
||||||
final implicit def joinTasks[S](in: Seq[Task[S]]): JoinTask[S, Seq] = new JoinTask[S, Seq] {
|
final implicit def joinTasks[S](in: Seq[Task[S]]): JoinTask[S, Seq] = new JoinTask[S, Seq] {
|
||||||
def join: Task[Seq[S]] =
|
def join: Task[Seq[S]] =
|
||||||
Task[Seq[S]](Info(), Action.Join(in, (s: Seq[Result[S]]) => Right(TaskExtra.all(s))))
|
Task[Seq[S]](Action.Join(in, (s: Seq[Result[S]]) => Right(TaskExtra.all(s))))
|
||||||
def reduced(f: (S, S) => S): Task[S] = TaskExtra.reduced(in.toIndexedSeq, f)
|
def reduced(f: (S, S) => S): Task[S] = TaskExtra.reduced(in.toIndexedSeq, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,18 +144,18 @@ trait TaskExtra extends TaskExtra0 {
|
||||||
final implicit def multInputTask[Tup <: Tuple](tasks: Tuple.Map[Tup, Task]): MultiInTask[Tup] =
|
final implicit def multInputTask[Tup <: Tuple](tasks: Tuple.Map[Tup, Task]): MultiInTask[Tup] =
|
||||||
new MultiInTask[Tup]:
|
new MultiInTask[Tup]:
|
||||||
override def flatMapN[A](f: Tup => Task[A]): Task[A] =
|
override def flatMapN[A](f: Tup => Task[A]): Task[A] =
|
||||||
Task(Info(), Action.FlatMapped(tasks, f.compose(allM)))
|
Task(Action.FlatMapped(tasks, f.compose(allM)))
|
||||||
override def flatMapR[A](f: Tuple.Map[Tup, Result] => Task[A]): Task[A] =
|
override def flatMapR[A](f: Tuple.Map[Tup, Result] => Task[A]): Task[A] =
|
||||||
Task(Info(), Action.FlatMapped(tasks, f))
|
Task(Action.FlatMapped(tasks, f))
|
||||||
|
|
||||||
override def mapN[A](f: Tup => A): Task[A] =
|
override def mapN[A](f: Tup => A): Task[A] =
|
||||||
Task(Info(), Action.Mapped(tasks, f.compose(allM)))
|
Task(Action.Mapped(tasks, f.compose(allM)))
|
||||||
override def mapR[A](f: Tuple.Map[Tup, Result] => A): Task[A] =
|
override def mapR[A](f: Tuple.Map[Tup, Result] => A): Task[A] =
|
||||||
Task(Info(), Action.Mapped(tasks, f))
|
Task(Action.Mapped(tasks, f))
|
||||||
override def flatFailure[A](f: Seq[Incomplete] => Task[A]): Task[A] =
|
override def flatFailure[A](f: Seq[Incomplete] => Task[A]): Task[A] =
|
||||||
Task(Info(), Action.FlatMapped(tasks, f.compose(anyFailM)))
|
Task(Action.FlatMapped(tasks, f.compose(anyFailM)))
|
||||||
override def mapFailure[A](f: Seq[Incomplete] => A): Task[A] =
|
override def mapFailure[A](f: Seq[Incomplete] => A): Task[A] =
|
||||||
Task(Info(), Action.Mapped(tasks, f.compose(anyFailM)))
|
Task(Action.Mapped(tasks, f.compose(anyFailM)))
|
||||||
|
|
||||||
final implicit def singleInputTask[S](in: Task[S]): SingleInTask[S] =
|
final implicit def singleInputTask[S](in: Task[S]): SingleInTask[S] =
|
||||||
new SingleInTask[S]:
|
new SingleInTask[S]:
|
||||||
|
|
@ -164,21 +164,22 @@ trait TaskExtra extends TaskExtra0 {
|
||||||
def failure: Task[Incomplete] = mapFailure(identity)
|
def failure: Task[Incomplete] = mapFailure(identity)
|
||||||
def result: Task[Result[S]] = mapR(identity)
|
def result: Task[Result[S]] = mapR(identity)
|
||||||
|
|
||||||
private def newInfo[A]: Info[A] = TaskExtra.newInfo(in.info)
|
private def newAttributes: AttributeMap = TaskExtra.newAttributes(in.attributes)
|
||||||
|
|
||||||
override def flatMapR[A](f: Result[S] => Task[A]): Task[A] =
|
override def flatMapR[A](f: Result[S] => Task[A]): Task[A] =
|
||||||
Task(
|
Task(
|
||||||
newInfo,
|
newAttributes,
|
||||||
Action.FlatMapped[A, Tuple1[S]](Tuple1(in), { case Tuple1(a) => f(a) })
|
Action.FlatMapped[A, Tuple1[S]](Tuple1(in), { case Tuple1(a) => f(a) })
|
||||||
)
|
)
|
||||||
|
|
||||||
override def mapR[A](f: Result[S] => A): Task[A] =
|
override def mapR[A](f: Result[S] => A): Task[A] =
|
||||||
Task(
|
Task(
|
||||||
newInfo,
|
newAttributes,
|
||||||
Action.Mapped[A, Tuple1[S]](Tuple1(in), { case Tuple1(a) => f(a) })
|
Action.Mapped[A, Tuple1[S]](Tuple1(in), { case Tuple1(a) => f(a) })
|
||||||
)
|
)
|
||||||
|
|
||||||
override def dependsOn(tasks: Task[?]*): Task[S] = Task(newInfo, Action.DependsOn(in, tasks))
|
override def dependsOn(tasks: Task[?]*): Task[S] =
|
||||||
|
Task(newAttributes, Action.DependsOn(in, tasks))
|
||||||
|
|
||||||
override def flatMapN[T](f: S => Task[T]): Task[T] = flatMapR(f.compose(successM))
|
override def flatMapN[T](f: S => Task[T]): Task[T] = flatMapR(f.compose(successM))
|
||||||
|
|
||||||
|
|
@ -206,8 +207,8 @@ trait TaskExtra extends TaskExtra0 {
|
||||||
def &&[T](alt: Task[T]): Task[T] = flatMapN(_ => alt)
|
def &&[T](alt: Task[T]): Task[T] = flatMapN(_ => alt)
|
||||||
|
|
||||||
final implicit def toTaskInfo[S](in: Task[S]): TaskInfo[S] = new TaskInfo[S] {
|
final implicit def toTaskInfo[S](in: Task[S]): TaskInfo[S] = new TaskInfo[S] {
|
||||||
def describedAs(s: String): Task[S] = in.copy(info = in.info.setDescription(s))
|
def describedAs(s: String): Task[S] = in.setDescription(s)
|
||||||
def named(s: String): Task[S] = in.copy(info = in.info.setName(s))
|
def named(s: String): Task[S] = in.setName(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
final implicit def pipeToProcess[Key](
|
final implicit def pipeToProcess[Key](
|
||||||
|
|
@ -327,10 +328,10 @@ object TaskExtra extends TaskExtra {
|
||||||
def incompleteDeps(incs: Seq[Incomplete]): Incomplete = Incomplete(None, causes = incs)
|
def incompleteDeps(incs: Seq[Incomplete]): Incomplete = Incomplete(None, causes = incs)
|
||||||
|
|
||||||
def select[A, B](fab: Task[Either[A, B]], f: Task[A => B]): Task[B] =
|
def select[A, B](fab: Task[Either[A, B]], f: Task[A => B]): Task[B] =
|
||||||
Task(newInfo(fab.info), Action.Selected[A, B](fab, f))
|
Task(newAttributes(fab.attributes), Action.Selected[A, B](fab, f))
|
||||||
|
|
||||||
// The "taskDefinitionKey" is used, at least, by the ".previous" functionality.
|
// The "taskDefinitionKey" is used, at least, by the ".previous" functionality.
|
||||||
// But apparently it *cannot* survive a task map/flatMap/etc. See actions/depends-on.
|
// But apparently it *cannot* survive a task map/flatMap/etc. See actions/depends-on.
|
||||||
private[sbt] def newInfo[A](info: Info[?]): Info[A] =
|
private[sbt] def newAttributes[A](attributes: AttributeMap): AttributeMap =
|
||||||
Info[A](AttributeMap(info.attributes.entries.filter(_.key.label != "taskDefinitionKey")))
|
AttributeMap(attributes.entries.filter(_.key.label != "taskDefinitionKey"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import sbt.internal.util.Types.*
|
||||||
|
|
||||||
object Transform:
|
object Transform:
|
||||||
def fromDummy[A](original: Task[A])(action: => A): Task[A] =
|
def fromDummy[A](original: Task[A])(action: => A): Task[A] =
|
||||||
Task(original.info, Action.Pure(() => action, false))
|
new Task(original.attributes, original.post, work = Action.Pure(() => action, false))
|
||||||
|
|
||||||
def fromDummyStrict[T](original: Task[T], value: T): Task[T] = fromDummy(original)(value)
|
def fromDummyStrict[T](original: Task[T], value: T): Task[T] = fromDummy(original)(value)
|
||||||
|
|
||||||
|
|
@ -57,8 +57,8 @@ object Transform:
|
||||||
case Join(in, f) => uniform(in)(f)
|
case Join(in, f) => uniform(in)(f)
|
||||||
|
|
||||||
def inline1[T](t: TaskId[T]): Option[() => T] = t match
|
def inline1[T](t: TaskId[T]): Option[() => T] = t match
|
||||||
case Task(_, Action.Pure(eval, true)) => Some(eval)
|
case Task(Action.Pure(eval, true)) => Some(eval)
|
||||||
case _ => None
|
case _ => None
|
||||||
|
|
||||||
def uniform[A1, D](tasks: Seq[Task[D]])(
|
def uniform[A1, D](tasks: Seq[Task[D]])(
|
||||||
f: Seq[Result[D]] => Either[Task[A1], A1]
|
f: Seq[Result[D]] => Either[Task[A1], A1]
|
||||||
|
|
|
||||||
|
|
@ -158,123 +158,95 @@ object AttributeKey {
|
||||||
* keys with the same label but different types. Excluding this possibility is the responsibility of
|
* keys with the same label but different types. Excluding this possibility is the responsibility of
|
||||||
* the client if desired.
|
* the client if desired.
|
||||||
*/
|
*/
|
||||||
trait AttributeMap {
|
opaque type AttributeMap = Map[AttributeKey[?], Any]
|
||||||
|
|
||||||
/**
|
|
||||||
* 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`.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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`.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
def keys: Iterable[AttributeKey[?]]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
def ++(o: AttributeMap): AttributeMap
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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`.
|
|
||||||
*/
|
|
||||||
private[sbt] def setCond[T](k: AttributeKey[T], opt: Option[T]): AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
object AttributeMap {
|
|
||||||
|
|
||||||
|
object AttributeMap:
|
||||||
/** An [[AttributeMap]] without any mappings. */
|
/** An [[AttributeMap]] without any mappings. */
|
||||||
val empty: AttributeMap = new BasicAttributeMap(Map.empty)
|
val empty: AttributeMap = Map.empty
|
||||||
|
|
||||||
/** Constructs an [[AttributeMap]] containing the given `entries`. */
|
/** Constructs an [[AttributeMap]] containing the given `entries`. */
|
||||||
def apply(entries: Iterable[AttributeEntry[?]]): AttributeMap = empty ++ 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
|
def apply(entries: AttributeEntry[?]*): AttributeMap = ++(empty)(entries)
|
||||||
|
|
||||||
/** Presents an `AttributeMap` as a natural transformation. */
|
extension (self: AttributeMap)
|
||||||
// implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = λ[AttributeKey ~> Id](map(_))
|
/**
|
||||||
}
|
* 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 = self(k).asInstanceOf[T]
|
||||||
|
|
||||||
private class BasicAttributeMap(private val backing: Map[AttributeKey[?], Any])
|
/**
|
||||||
extends AttributeMap {
|
* 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] = self.get(k).asInstanceOf[Option[T]]
|
||||||
|
|
||||||
def isEmpty: Boolean = backing.isEmpty
|
/**
|
||||||
def apply[T](k: AttributeKey[T]) = backing(k).asInstanceOf[T]
|
* Gets the value of type `T` associated with the key `k` or `default` if no value is associated. If
|
||||||
def get[T](k: AttributeKey[T]) = backing.get(k).asInstanceOf[Option[T]]
|
* a key with the same label but a different type is defined, this method will return `default`.
|
||||||
def remove[T](k: AttributeKey[T]): AttributeMap = new BasicAttributeMap(backing - k)
|
*/
|
||||||
def contains[T](k: AttributeKey[T]) = backing.contains(k)
|
def getOrElse[T](k: AttributeKey[T], default: => T): T =
|
||||||
|
self.getOrElse(k, default).asInstanceOf[T]
|
||||||
|
|
||||||
def put[T](k: AttributeKey[T], value: T): AttributeMap =
|
/**
|
||||||
new BasicAttributeMap(backing.updated(k, value: Any))
|
* 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 = self.removed(k)
|
||||||
|
|
||||||
def keys: Iterable[AttributeKey[?]] = backing.keys
|
/**
|
||||||
|
* 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 = self.contains(k)
|
||||||
|
|
||||||
def ++(o: Iterable[AttributeEntry[?]]): AttributeMap =
|
/**
|
||||||
new BasicAttributeMap(o.foldLeft(backing)((b, e) => b.updated(e.key, e.value: Any)))
|
* 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 = self.updated(k, value)
|
||||||
|
|
||||||
def ++(o: AttributeMap): AttributeMap = o match {
|
/**
|
||||||
case bam: BasicAttributeMap =>
|
* All keys with defined mappings. There may be multiple keys with the same `label`, but different
|
||||||
new BasicAttributeMap(Map(backing.toSeq ++ bam.backing.toSeq*))
|
* types.
|
||||||
case _ => o ++ this
|
*/
|
||||||
}
|
def keys: Iterable[AttributeKey[?]] = self.keys
|
||||||
|
|
||||||
def entries: Iterable[AttributeEntry[?]] =
|
/**
|
||||||
backing.collect { case (k: AttributeKey[kt], v) =>
|
* Adds the mappings in `o` to this map, with mappings in `o` taking precedence over existing
|
||||||
AttributeEntry(k, v.asInstanceOf[kt])
|
* mappings.
|
||||||
}
|
*/
|
||||||
|
def ++(o: Iterable[AttributeEntry[?]]): AttributeMap =
|
||||||
|
o.foldLeft(self)((b, e) => b.updated(e.key, e.value))
|
||||||
|
|
||||||
private[sbt] def setCond[T](k: AttributeKey[T], opt: Option[T]): AttributeMap =
|
/**
|
||||||
opt match {
|
* Combines the mappings in `o` with the mappings in this map, with mappings in `o` taking
|
||||||
case Some(v) => put(k, v)
|
* precedence over existing mappings.
|
||||||
case None => remove(k)
|
*/
|
||||||
}
|
def ++(o: AttributeMap): AttributeMap = self ++ o
|
||||||
|
|
||||||
override def toString = entries.mkString("(", ", ", ")")
|
/**
|
||||||
}
|
* All mappings in this map. The [[AttributeEntry]] type preserves the typesafety of mappings,
|
||||||
|
* although the specific types are unknown.
|
||||||
|
*/
|
||||||
|
def entries: Iterable[AttributeEntry[?]] =
|
||||||
|
self.collect { case (k: AttributeKey[x], v) => AttributeEntry(k, v.asInstanceOf[x]) }
|
||||||
|
|
||||||
|
/** `true` if there are no mappings in this map, `false` if there are. */
|
||||||
|
def isEmpty: Boolean = self.isEmpty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 =
|
||||||
|
opt match
|
||||||
|
case Some(v) => self.updated(k, v)
|
||||||
|
case None => self.removed(k)
|
||||||
|
end extension
|
||||||
|
end AttributeMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An immutable map where both key and value are String.
|
* An immutable map where both key and value are String.
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,12 @@ enum EvaluationState:
|
||||||
case Calling
|
case Calling
|
||||||
case Evaluated
|
case Evaluated
|
||||||
|
|
||||||
abstract class EvaluateSettings[ScopeType]:
|
class EvaluateSettings[I <: Init](
|
||||||
protected val init: Init[ScopeType]
|
val init: I,
|
||||||
|
executor: Executor,
|
||||||
|
compiledSettings: Seq[init.Compiled[?]],
|
||||||
|
):
|
||||||
import init._
|
import init._
|
||||||
|
|
||||||
protected def executor: Executor
|
|
||||||
protected def compiledSettings: Seq[Compiled[?]]
|
|
||||||
|
|
||||||
import EvaluationState.*
|
import EvaluationState.*
|
||||||
|
|
||||||
private val complete = new LinkedBlockingQueue[Option[Throwable]]
|
private val complete = new LinkedBlockingQueue[Option[Throwable]]
|
||||||
|
|
@ -68,7 +67,7 @@ abstract class EvaluateSettings[ScopeType]:
|
||||||
private val running = new AtomicInteger
|
private val running = new AtomicInteger
|
||||||
private val cancel = new AtomicBoolean(false)
|
private val cancel = new AtomicBoolean(false)
|
||||||
|
|
||||||
def run(implicit delegates: ScopeType => Seq[ScopeType]): Settings[ScopeType] = {
|
def run(implicit delegates: ScopeType => Seq[ScopeType]): Settings = {
|
||||||
assert(running.get() == 0, "Already running")
|
assert(running.get() == 0, "Already running")
|
||||||
startWork()
|
startWork()
|
||||||
roots.foreach(_.registerIfNew())
|
roots.foreach(_.registerIfNew())
|
||||||
|
|
@ -83,7 +82,7 @@ abstract class EvaluateSettings[ScopeType]:
|
||||||
private def getResults(implicit delegates: ScopeType => Seq[ScopeType]) =
|
private def getResults(implicit delegates: ScopeType => Seq[ScopeType]) =
|
||||||
static.toTypedSeq.foldLeft(empty) { case (ss, static.TPair(key, node)) =>
|
static.toTypedSeq.foldLeft(empty) { case (ss, static.TPair(key, node)) =>
|
||||||
if key.key.isLocal then ss
|
if key.key.isLocal then ss
|
||||||
else ss.set(key.scope, key.key, node.get)
|
else ss.set(key, node.get)
|
||||||
}
|
}
|
||||||
|
|
||||||
private lazy val getValue: [A] => INode[A] => A = [A] => (fa: INode[A]) => fa.get
|
private lazy val getValue: [A] => INode[A] => A = [A] => (fa: INode[A]) => fa.get
|
||||||
|
|
|
||||||
|
|
@ -12,53 +12,10 @@ import sbt.util.Show
|
||||||
import Util.{ nil, nilSeq }
|
import Util.{ nil, nilSeq }
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.jdk.CollectionConverters.*
|
||||||
|
|
||||||
sealed trait Settings[ScopeType]:
|
// delegates should contain the input ScopeType as the first entry
|
||||||
def data: Map[ScopeType, AttributeMap]
|
|
||||||
def keys(scope: ScopeType): Set[AttributeKey[?]]
|
|
||||||
def scopes: Set[ScopeType]
|
|
||||||
def definingScope(scope: ScopeType, key: AttributeKey[?]): Option[ScopeType]
|
|
||||||
def allKeys[A](f: (ScopeType, AttributeKey[?]) => A): Seq[A]
|
|
||||||
def get[A](scope: ScopeType, key: AttributeKey[A]): Option[A]
|
|
||||||
def getDirect[A](scope: ScopeType, key: AttributeKey[A]): Option[A]
|
|
||||||
def set[A](scope: ScopeType, key: AttributeKey[A], value: A): Settings[ScopeType]
|
|
||||||
end Settings
|
|
||||||
|
|
||||||
private final class Settings0[ScopeType](
|
|
||||||
val data: Map[ScopeType, AttributeMap],
|
|
||||||
val delegates: ScopeType => Seq[ScopeType]
|
|
||||||
) extends Settings[ScopeType]:
|
|
||||||
|
|
||||||
def scopes: Set[ScopeType] = data.keySet
|
|
||||||
def keys(scope: ScopeType) = data(scope).keys.toSet
|
|
||||||
|
|
||||||
def allKeys[A](f: (ScopeType, AttributeKey[?]) => A): Seq[A] =
|
|
||||||
data.flatMap { case (scope, map) =>
|
|
||||||
map.keys.map(k => f(scope, k))
|
|
||||||
}.toSeq
|
|
||||||
|
|
||||||
def get[A](scope: ScopeType, key: AttributeKey[A]): Option[A] =
|
|
||||||
delegates(scope).flatMap { sc =>
|
|
||||||
getDirect(sc, key)
|
|
||||||
}.headOption
|
|
||||||
|
|
||||||
def definingScope(scope: ScopeType, key: AttributeKey[?]): Option[ScopeType] =
|
|
||||||
delegates(scope).find { sc =>
|
|
||||||
getDirect(sc, key).isDefined
|
|
||||||
}
|
|
||||||
|
|
||||||
def getDirect[A](scope: ScopeType, key: AttributeKey[A]): Option[A] =
|
|
||||||
data.get(scope).flatMap(_.get(key))
|
|
||||||
|
|
||||||
def set[A](scope: ScopeType, key: AttributeKey[A], value: A): Settings[ScopeType] =
|
|
||||||
val map = data.getOrElse(scope, AttributeMap.empty)
|
|
||||||
val newData = data.updated(scope, map.put(key, value))
|
|
||||||
Settings0(newData, delegates)
|
|
||||||
|
|
||||||
end Settings0
|
|
||||||
|
|
||||||
// delegates should contain the input Scope as the first entry
|
|
||||||
// this trait is intended to be mixed into an object
|
// this trait is intended to be mixed into an object
|
||||||
trait Init[ScopeType]:
|
trait Init:
|
||||||
|
type ScopeType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Show instance used when a detailed String needs to be generated.
|
* The Show instance used when a detailed String needs to be generated.
|
||||||
|
|
@ -80,6 +37,58 @@ trait Init[ScopeType]:
|
||||||
type ScopeLocal = ScopedKey[?] => Seq[Setting[?]]
|
type ScopeLocal = ScopedKey[?] => Seq[Setting[?]]
|
||||||
type MapConstant = [a] => ScopedKey[a] => Option[a]
|
type MapConstant = [a] => ScopedKey[a] => Option[a]
|
||||||
|
|
||||||
|
sealed trait Settings:
|
||||||
|
def attributeKeys: Set[AttributeKey[?]]
|
||||||
|
def keys: Iterable[ScopedKey[?]]
|
||||||
|
def contains(key: ScopedKey[?]): Boolean
|
||||||
|
def values: Iterable[Any]
|
||||||
|
def data: Map[ScopedKey[?], Any]
|
||||||
|
def scopes: Set[ScopeType]
|
||||||
|
def getKeyValue[A](key: ScopedKey[A]): Option[(ScopedKey[A], A)]
|
||||||
|
def get[A](key: ScopedKey[A]): Option[A]
|
||||||
|
def definingKey[A](key: ScopedKey[A]): Option[ScopedKey[A]]
|
||||||
|
def getDirect[A](key: ScopedKey[A]): Option[A]
|
||||||
|
def set[A](key: ScopedKey[A], value: A): Settings
|
||||||
|
end Settings
|
||||||
|
|
||||||
|
private final class Settings0(
|
||||||
|
val scopes: Set[ScopeType],
|
||||||
|
val attributeKeys: Set[AttributeKey[?]],
|
||||||
|
// In 1.x it was a Map[Scope, AttributeMap]
|
||||||
|
// For the heap, it is better to store the ScopedKey[?] directly to avoid recreating
|
||||||
|
// abd duplicating them later.
|
||||||
|
val data: Map[ScopedKey[?], Any],
|
||||||
|
d: ScopeType => Seq[ScopeType]
|
||||||
|
) extends Settings:
|
||||||
|
def keys: Iterable[ScopedKey[?]] = data.keys
|
||||||
|
def contains(key: ScopedKey[?]): Boolean = data.contains(key)
|
||||||
|
def values: Iterable[Any] = data.values
|
||||||
|
|
||||||
|
def get[A](key: ScopedKey[A]): Option[A] =
|
||||||
|
delegates(key).flatMap(data.get).nextOption.asInstanceOf[Option[A]]
|
||||||
|
|
||||||
|
def definingKey[A](key: ScopedKey[A]): Option[ScopedKey[A]] =
|
||||||
|
delegates(key).find(data.contains)
|
||||||
|
|
||||||
|
def getKeyValue[A](key: ScopedKey[A]): Option[(ScopedKey[A], A)] =
|
||||||
|
delegates(key).flatMap { k =>
|
||||||
|
data.get(k) match
|
||||||
|
case None => None
|
||||||
|
case Some(v) => Some(k -> v.asInstanceOf[A])
|
||||||
|
}.nextOption
|
||||||
|
|
||||||
|
def getDirect[A](key: ScopedKey[A]): Option[A] = data.get(key).asInstanceOf[Option[A]]
|
||||||
|
|
||||||
|
def set[A](key: ScopedKey[A], value: A): Settings =
|
||||||
|
val newScopes = scopes + key.scope
|
||||||
|
val newAttributeKeys = attributeKeys + key.key
|
||||||
|
val newData = data.updated(key, value)
|
||||||
|
Settings0(newScopes, newAttributeKeys, newData, d)
|
||||||
|
|
||||||
|
private def delegates[A](key: ScopedKey[A]): Iterator[ScopedKey[A]] =
|
||||||
|
d(key.scope).iterator.map(s => key.copy(scope = s))
|
||||||
|
end Settings0
|
||||||
|
|
||||||
private[sbt] abstract class ValidateKeyRef {
|
private[sbt] abstract class ValidateKeyRef {
|
||||||
def apply[T](key: ScopedKey[T], selfRefOk: Boolean): ValidatedRef[T]
|
def apply[T](key: ScopedKey[T], selfRefOk: Boolean): ValidatedRef[T]
|
||||||
}
|
}
|
||||||
|
|
@ -163,16 +172,16 @@ trait Init[ScopeType]:
|
||||||
private final val nextID = new java.util.concurrent.atomic.AtomicLong
|
private final val nextID = new java.util.concurrent.atomic.AtomicLong
|
||||||
private final def nextDefaultID(): Long = nextID.incrementAndGet()
|
private final def nextDefaultID(): Long = nextID.incrementAndGet()
|
||||||
|
|
||||||
def empty(implicit delegates: ScopeType => Seq[ScopeType]): Settings[ScopeType] =
|
def empty(implicit delegates: ScopeType => Seq[ScopeType]): Settings =
|
||||||
Settings0(Map.empty, delegates)
|
Settings0(Set.empty, Set.empty, Map.empty, delegates)
|
||||||
|
|
||||||
def asTransform(s: Settings[ScopeType]): [A] => ScopedKey[A] => A =
|
def asTransform(s: Settings): [A] => ScopedKey[A] => A =
|
||||||
[A] => (sk: ScopedKey[A]) => getValue(s, sk)
|
[A] => (sk: ScopedKey[A]) => getValue(s, sk)
|
||||||
|
|
||||||
def getValue[T](s: Settings[ScopeType], k: ScopedKey[T]) =
|
def getValue[T](s: Settings, k: ScopedKey[T]) =
|
||||||
s.get(k.scope, k.key) getOrElse (throw new InvalidReference(k))
|
s.get(k).getOrElse(throw new InvalidReference(k))
|
||||||
|
|
||||||
def asFunction[A](s: Settings[ScopeType]): ScopedKey[A] => A = k => getValue(s, k)
|
def asFunction[A](s: Settings): ScopedKey[A] => A = k => getValue(s, k)
|
||||||
|
|
||||||
def mapScope(f: ScopeType => ScopeType): MapScoped =
|
def mapScope(f: ScopeType => ScopeType): MapScoped =
|
||||||
[a] => (k: ScopedKey[a]) => k.copy(scope = f(k.scope))
|
[a] => (k: ScopedKey[a]) => k.copy(scope = f(k.scope))
|
||||||
|
|
@ -197,7 +206,7 @@ trait Init[ScopeType]:
|
||||||
// inject derived settings into scopes where their dependencies are directly defined
|
// inject derived settings into scopes where their dependencies are directly defined
|
||||||
// and prepend per-scope settings
|
// and prepend per-scope settings
|
||||||
val derived = deriveAndLocal(initDefaults, mkDelegates(delegates))
|
val derived = deriveAndLocal(initDefaults, mkDelegates(delegates))
|
||||||
// group by Scope/Key, dropping dead initializations
|
// group by ScopeType/Key, dropping dead initializations
|
||||||
val sMap: ScopedMap = grouped(derived)
|
val sMap: ScopedMap = grouped(derived)
|
||||||
// delegate references to undefined values according to 'delegates'
|
// delegate references to undefined values according to 'delegates'
|
||||||
val dMap: ScopedMap =
|
val dMap: ScopedMap =
|
||||||
|
|
@ -211,13 +220,13 @@ trait Init[ScopeType]:
|
||||||
delegates: ScopeType => Seq[ScopeType],
|
delegates: ScopeType => Seq[ScopeType],
|
||||||
scopeLocal: ScopeLocal,
|
scopeLocal: ScopeLocal,
|
||||||
display: Show[ScopedKey[?]]
|
display: Show[ScopedKey[?]]
|
||||||
): Settings[ScopeType] = makeWithCompiledMap(init)._2
|
): Settings = makeWithCompiledMap(init)._2
|
||||||
|
|
||||||
def makeWithCompiledMap(init: Seq[Setting[?]])(using
|
def makeWithCompiledMap(init: Seq[Setting[?]])(using
|
||||||
delegates: ScopeType => Seq[ScopeType],
|
delegates: ScopeType => Seq[ScopeType],
|
||||||
scopeLocal: ScopeLocal,
|
scopeLocal: ScopeLocal,
|
||||||
display: Show[ScopedKey[?]]
|
display: Show[ScopedKey[?]]
|
||||||
): (CompiledMap, Settings[ScopeType]) =
|
): (CompiledMap, Settings) =
|
||||||
val cMap = compiled(init)(using delegates, scopeLocal, display)
|
val cMap = compiled(init)(using delegates, scopeLocal, display)
|
||||||
// order the initializations. cyclic references are detected here.
|
// order the initializations. cyclic references are detected here.
|
||||||
val ordered: Seq[Compiled[?]] = sort(cMap)
|
val ordered: Seq[Compiled[?]] = sort(cMap)
|
||||||
|
|
@ -235,16 +244,14 @@ trait Init[ScopeType]:
|
||||||
def compile(sMap: ScopedMap): CompiledMap =
|
def compile(sMap: ScopedMap): CompiledMap =
|
||||||
sMap match
|
sMap match
|
||||||
case m: IMap.IMap0[ScopedKey, SettingSeq] @unchecked =>
|
case m: IMap.IMap0[ScopedKey, SettingSeq] @unchecked =>
|
||||||
Par(m.backing.toVector)
|
import scala.collection.parallel.CollectionConverters.*
|
||||||
|
m.backing.par
|
||||||
.map { case (k, ss) =>
|
.map { case (k, ss) =>
|
||||||
val deps = ss.flatMap(_.dependencies).toSet
|
val deps = ss.iterator.flatMap(_.dependencies).toSet
|
||||||
(
|
k -> Compiled(k.asInstanceOf[ScopedKey[Any]], deps, ss.asInstanceOf[SettingSeq[Any]])
|
||||||
k,
|
|
||||||
Compiled(k.asInstanceOf[ScopedKey[Any]], deps, ss.asInstanceOf[SettingSeq[Any]])
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
.toVector
|
.to(Map)
|
||||||
.toMap
|
|
||||||
case _ =>
|
case _ =>
|
||||||
sMap.toTypedSeq.map { case sMap.TPair(k, ss) =>
|
sMap.toTypedSeq.map { case sMap.TPair(k, ss) =>
|
||||||
val deps = ss.flatMap(_.dependencies)
|
val deps = ss.flatMap(_.dependencies)
|
||||||
|
|
@ -324,16 +331,12 @@ trait Init[ScopeType]:
|
||||||
|
|
||||||
private def applyInits(ordered: Seq[Compiled[?]])(implicit
|
private def applyInits(ordered: Seq[Compiled[?]])(implicit
|
||||||
delegates: ScopeType => Seq[ScopeType]
|
delegates: ScopeType => Seq[ScopeType]
|
||||||
): Settings[ScopeType] =
|
): Settings =
|
||||||
val x =
|
val x =
|
||||||
java.util.concurrent.Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors)
|
java.util.concurrent.Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors)
|
||||||
try {
|
try {
|
||||||
val eval: EvaluateSettings[ScopeType] = new EvaluateSettings[ScopeType] {
|
val eval: EvaluateSettings[Init.this.type] = new EvaluateSettings(Init.this, x, ordered)
|
||||||
override val init: Init.this.type = Init.this
|
eval.run(using delegates)
|
||||||
def compiledSettings = ordered
|
|
||||||
def executor = x
|
|
||||||
}
|
|
||||||
eval.run
|
|
||||||
} finally {
|
} finally {
|
||||||
x.shutdown()
|
x.shutdown()
|
||||||
}
|
}
|
||||||
|
|
@ -416,15 +419,9 @@ trait Init[ScopeType]:
|
||||||
final class Flattened(val key: ScopedKey[?], val dependencies: Iterable[ScopedKey[?]])
|
final class Flattened(val key: ScopedKey[?], val dependencies: Iterable[ScopedKey[?]])
|
||||||
|
|
||||||
def flattenLocals(compiled: CompiledMap): Map[ScopedKey[?], Flattened] = {
|
def flattenLocals(compiled: CompiledMap): Map[ScopedKey[?], Flattened] = {
|
||||||
val locals = compiled flatMap { case (key, comp) =>
|
val locals = compiled.collect { case (key, comp) if key.key.isLocal => comp }
|
||||||
if (key.key.isLocal) Seq(comp)
|
|
||||||
else nilSeq[Compiled[?]]
|
|
||||||
}
|
|
||||||
val ordered = Dag.topologicalSort(locals)(
|
val ordered = Dag.topologicalSort(locals)(
|
||||||
_.dependencies.flatMap(dep =>
|
_.dependencies.collect { case dep if dep.key.isLocal => compiled(dep) }
|
||||||
if (dep.key.isLocal) Seq[Compiled[?]](compiled(dep))
|
|
||||||
else nilSeq[Compiled[?]]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
def flatten(
|
def flatten(
|
||||||
cmap: Map[ScopedKey[?], Flattened],
|
cmap: Map[ScopedKey[?], Flattened],
|
||||||
|
|
@ -433,7 +430,7 @@ trait Init[ScopeType]:
|
||||||
): Flattened =
|
): Flattened =
|
||||||
new Flattened(
|
new Flattened(
|
||||||
key,
|
key,
|
||||||
deps.flatMap(dep => if (dep.key.isLocal) cmap(dep).dependencies else Seq[ScopedKey[?]](dep))
|
deps.flatMap(dep => if (dep.key.isLocal) cmap(dep).dependencies else Seq(dep))
|
||||||
)
|
)
|
||||||
|
|
||||||
val empty = Map.empty[ScopedKey[?], Flattened]
|
val empty = Map.empty[ScopedKey[?], Flattened]
|
||||||
|
|
@ -442,10 +439,9 @@ trait Init[ScopeType]:
|
||||||
cmap.updated(c.key, flatten(cmap, c.key, c.dependencies))
|
cmap.updated(c.key, flatten(cmap, c.key, c.dependencies))
|
||||||
}
|
}
|
||||||
|
|
||||||
compiled flatMap { case (key, comp) =>
|
compiled.collect {
|
||||||
if (key.key.isLocal) nilSeq[(ScopedKey[?], Flattened)]
|
case (key, comp) if !key.key.isLocal =>
|
||||||
else
|
(key, flatten(flattenedLocals, key, comp.dependencies))
|
||||||
Seq[(ScopedKey[?], Flattened)]((key, flatten(flattenedLocals, key, comp.dependencies)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,7 +649,7 @@ trait Init[ScopeType]:
|
||||||
|
|
||||||
private[sbt] def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1]
|
private[sbt] def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1]
|
||||||
|
|
||||||
def evaluate(map: Settings[ScopeType]): A1
|
def evaluate(map: Settings): A1
|
||||||
def zip[A2](o: Initialize[A2]): Initialize[(A1, A2)] = zipTupled(o)(identity)
|
def zip[A2](o: Initialize[A2]): Initialize[(A1, A2)] = zipTupled(o)(identity)
|
||||||
|
|
||||||
def zipWith[A2, U](o: Initialize[A2])(f: (A1, A2) => U): Initialize[U] =
|
def zipWith[A2, U](o: Initialize[A2])(f: (A1, A2) => U): Initialize[U] =
|
||||||
|
|
@ -799,7 +795,7 @@ trait Init[ScopeType]:
|
||||||
(fa: Initialize[A]) => (fa.mapReferenced(g))
|
(fa: Initialize[A]) => (fa.mapReferenced(g))
|
||||||
private def mapConstantK(g: MapConstant): [A] => Initialize[A] => Initialize[A] = [A] =>
|
private def mapConstantK(g: MapConstant): [A] => Initialize[A] => Initialize[A] = [A] =>
|
||||||
(fa: Initialize[A]) => (fa.mapConstant(g))
|
(fa: Initialize[A]) => (fa.mapConstant(g))
|
||||||
private def evaluateK(g: Settings[ScopeType]): [A] => Initialize[A] => A = [A] =>
|
private def evaluateK(g: Settings): [A] => Initialize[A] => A = [A] =>
|
||||||
(fa: Initialize[A]) => (fa.evaluate(g))
|
(fa: Initialize[A]) => (fa.evaluate(g))
|
||||||
private def deps(ls: List[Initialize[?]]): Seq[ScopedKey[?]] =
|
private def deps(ls: List[Initialize[?]]): Seq[ScopedKey[?]] =
|
||||||
ls.flatMap(_.dependencies)
|
ls.flatMap(_.dependencies)
|
||||||
|
|
@ -820,7 +816,7 @@ trait Init[ScopeType]:
|
||||||
extends Keyed[S, A1]:
|
extends Keyed[S, A1]:
|
||||||
override final def apply[A2](g: A1 => A2): Initialize[A2] =
|
override final def apply[A2](g: A1 => A2): Initialize[A2] =
|
||||||
GetValue(scopedKey, g compose transform)
|
GetValue(scopedKey, g compose transform)
|
||||||
override final def evaluate(ss: Settings[ScopeType]): A1 = transform(getValue(ss, scopedKey))
|
override final def evaluate(ss: Settings): A1 = transform(getValue(ss, scopedKey))
|
||||||
override final def mapReferenced(g: MapScoped): Initialize[A1] =
|
override final def mapReferenced(g: MapScoped): Initialize[A1] =
|
||||||
GetValue(g(scopedKey), transform)
|
GetValue(g(scopedKey), transform)
|
||||||
|
|
||||||
|
|
@ -842,7 +838,7 @@ trait Init[ScopeType]:
|
||||||
trait KeyedInitialize[A1] extends Keyed[A1, A1]:
|
trait KeyedInitialize[A1] extends Keyed[A1, A1]:
|
||||||
override final def apply[A2](g: A1 => A2): Initialize[A2] =
|
override final def apply[A2](g: A1 => A2): Initialize[A2] =
|
||||||
GetValue(scopedKey, g)
|
GetValue(scopedKey, g)
|
||||||
override final def evaluate(ss: Settings[ScopeType]): A1 = getValue(ss, scopedKey)
|
override final def evaluate(ss: Settings): A1 = getValue(ss, scopedKey)
|
||||||
override final def mapReferenced(g: MapScoped): Initialize[A1] = g(scopedKey)
|
override final def mapReferenced(g: MapScoped): Initialize[A1] = g(scopedKey)
|
||||||
|
|
||||||
private[sbt] override final def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] =
|
private[sbt] override final def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] =
|
||||||
|
|
@ -861,7 +857,7 @@ trait Init[ScopeType]:
|
||||||
override def dependencies: Seq[ScopedKey[?]] = Nil
|
override def dependencies: Seq[ScopedKey[?]] = Nil
|
||||||
override def apply[A2](g2: ([x] => Initialize[x] => Initialize[x]) => A2): Initialize[A2] =
|
override def apply[A2](g2: ([x] => Initialize[x] => Initialize[x]) => A2): Initialize[A2] =
|
||||||
map(this)(g2)
|
map(this)(g2)
|
||||||
override def evaluate(ss: Settings[ScopeType]): [x] => Initialize[x] => Initialize[x] = f
|
override def evaluate(ss: Settings): [x] => Initialize[x] => Initialize[x] = f
|
||||||
override def mapReferenced(g: MapScoped): Initialize[[x] => Initialize[x] => Initialize[x]] =
|
override def mapReferenced(g: MapScoped): Initialize[[x] => Initialize[x] => Initialize[x]] =
|
||||||
TransformCapture(mapReferencedK(g) ∙ f)
|
TransformCapture(mapReferencedK(g) ∙ f)
|
||||||
override def mapConstant(g: MapConstant): Initialize[[x] => Initialize[x] => Initialize[x]] =
|
override def mapConstant(g: MapConstant): Initialize[[x] => Initialize[x] => Initialize[x]] =
|
||||||
|
|
@ -880,7 +876,7 @@ trait Init[ScopeType]:
|
||||||
extends Initialize[ScopedKey[A1]]:
|
extends Initialize[ScopedKey[A1]]:
|
||||||
override def dependencies: Seq[ScopedKey[?]] = Nil
|
override def dependencies: Seq[ScopedKey[?]] = Nil
|
||||||
override def apply[A2](g2: ScopedKey[A1] => A2): Initialize[A2] = map(this)(g2)
|
override def apply[A2](g2: ScopedKey[A1] => A2): Initialize[A2] = map(this)(g2)
|
||||||
override def evaluate(ss: Settings[ScopeType]): ScopedKey[A1] = key
|
override def evaluate(ss: Settings): ScopedKey[A1] = key
|
||||||
override def mapReferenced(g: MapScoped): Initialize[ScopedKey[A1]] =
|
override def mapReferenced(g: MapScoped): Initialize[ScopedKey[A1]] =
|
||||||
ValidationCapture(g(key), selfRefOk)
|
ValidationCapture(g(key), selfRefOk)
|
||||||
override def mapConstant(g: MapConstant): Initialize[ScopedKey[A1]] = this
|
override def mapConstant(g: MapConstant): Initialize[ScopedKey[A1]] = this
|
||||||
|
|
@ -898,7 +894,7 @@ trait Init[ScopeType]:
|
||||||
extends Initialize[A1]:
|
extends Initialize[A1]:
|
||||||
override def dependencies: Seq[ScopedKey[?]] = in.dependencies
|
override def dependencies: Seq[ScopedKey[?]] = in.dependencies
|
||||||
override def apply[A2](g: A1 => A2): Initialize[A2] = Bind[S, A2](s => f(s)(g), in)
|
override def apply[A2](g: A1 => A2): Initialize[A2] = Bind[S, A2](s => f(s)(g), in)
|
||||||
override def evaluate(ss: Settings[ScopeType]): A1 = f(in.evaluate(ss)).evaluate(ss)
|
override def evaluate(ss: Settings): A1 = f(in.evaluate(ss)).evaluate(ss)
|
||||||
override def mapReferenced(g: MapScoped) =
|
override def mapReferenced(g: MapScoped) =
|
||||||
Bind[S, A1](s => f(s).mapReferenced(g), in.mapReferenced(g))
|
Bind[S, A1](s => f(s).mapReferenced(g), in.mapReferenced(g))
|
||||||
|
|
||||||
|
|
@ -927,7 +923,7 @@ trait Init[ScopeType]:
|
||||||
case Some(i) => Right(Optional(i.validateKeyReferenced(g).toOption, f))
|
case Some(i) => Right(Optional(i.validateKeyReferenced(g).toOption, f))
|
||||||
|
|
||||||
override def mapConstant(g: MapConstant): Initialize[A1] = Optional(a map mapConstantK(g)[S], f)
|
override def mapConstant(g: MapConstant): Initialize[A1] = Optional(a map mapConstantK(g)[S], f)
|
||||||
override def evaluate(ss: Settings[ScopeType]): A1 =
|
override def evaluate(ss: Settings): A1 =
|
||||||
f(a.flatMap { i => trapBadRef(evaluateK(ss)(i)) })
|
f(a.flatMap { i => trapBadRef(evaluateK(ss)(i)) })
|
||||||
|
|
||||||
// proper solution is for evaluate to be deprecated or for external use only and a new internal method returning Either be used
|
// proper solution is for evaluate to be deprecated or for external use only and a new internal method returning Either be used
|
||||||
|
|
@ -946,7 +942,7 @@ trait Init[ScopeType]:
|
||||||
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] = Right(this)
|
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] = Right(this)
|
||||||
override def apply[A2](g: A1 => A2): Initialize[A2] = Value[A2](() => g(value()))
|
override def apply[A2](g: A1 => A2): Initialize[A2] = Value[A2](() => g(value()))
|
||||||
override def mapConstant(g: MapConstant): Initialize[A1] = this
|
override def mapConstant(g: MapConstant): Initialize[A1] = this
|
||||||
override def evaluate(map: Settings[ScopeType]): A1 = value()
|
override def evaluate(map: Settings): A1 = value()
|
||||||
private[sbt] override def processAttributes[A2](init: A2)(f: (A2, AttributeMap) => A2): A2 =
|
private[sbt] override def processAttributes[A2](init: A2)(f: (A2, AttributeMap) => A2): A2 =
|
||||||
init
|
init
|
||||||
end Value
|
end Value
|
||||||
|
|
@ -958,7 +954,7 @@ trait Init[ScopeType]:
|
||||||
Right(this)
|
Right(this)
|
||||||
override def apply[A2](g: Set[ScopeType] => A2) = map(this)(g)
|
override def apply[A2](g: Set[ScopeType] => A2) = map(this)(g)
|
||||||
override def mapConstant(g: MapConstant): Initialize[Set[ScopeType]] = this
|
override def mapConstant(g: MapConstant): Initialize[Set[ScopeType]] = this
|
||||||
override def evaluate(map: Settings[ScopeType]): Set[ScopeType] = map.scopes
|
override def evaluate(map: Settings): Set[ScopeType] = map.scopes
|
||||||
private[sbt] override def processAttributes[A2](init: A2)(f: (A2, AttributeMap) => A2): A2 =
|
private[sbt] override def processAttributes[A2](init: A2)(f: (A2, AttributeMap) => A2): A2 =
|
||||||
init
|
init
|
||||||
end StaticScopes
|
end StaticScopes
|
||||||
|
|
@ -971,7 +967,7 @@ trait Init[ScopeType]:
|
||||||
override def mapConstant(g: MapConstant): Initialize[A2] =
|
override def mapConstant(g: MapConstant): Initialize[A2] =
|
||||||
Uniform(f, inputs.map(_.mapConstant(g)))
|
Uniform(f, inputs.map(_.mapConstant(g)))
|
||||||
override def apply[A3](g: A2 => A3): Initialize[A3] = Uniform(g.compose(f), inputs)
|
override def apply[A3](g: A2 => A3): Initialize[A3] = Uniform(g.compose(f), inputs)
|
||||||
override def evaluate(ss: Settings[ScopeType]): A2 = f(inputs.map(_.evaluate(ss)))
|
override def evaluate(ss: Settings): A2 = f(inputs.map(_.evaluate(ss)))
|
||||||
|
|
||||||
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A2] =
|
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A2] =
|
||||||
val tx = inputs.map(_.validateKeyReferenced(g))
|
val tx = inputs.map(_.validateKeyReferenced(g))
|
||||||
|
|
@ -997,7 +993,7 @@ trait Init[ScopeType]:
|
||||||
|
|
||||||
override def apply[A2](g: A1 => A2): Initialize[A2] = Apply(g compose f, inputs)
|
override def apply[A2](g: A1 => A2): Initialize[A2] = Apply(g compose f, inputs)
|
||||||
|
|
||||||
override def evaluate(ss: Settings[ScopeType]): A1 = f(inputs.unmap(evaluateK(ss)))
|
override def evaluate(ss: Settings): A1 = f(inputs.unmap(evaluateK(ss)))
|
||||||
|
|
||||||
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] =
|
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] =
|
||||||
val tx: Tuple.Map[Tup, ValidatedInit] = inputs.transform(validateKeyReferencedK(g))
|
val tx: Tuple.Map[Tup, ValidatedInit] = inputs.transform(validateKeyReferencedK(g))
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ object SettingsTest extends Properties("settings") {
|
||||||
checkKey(chk, Some(expected), eval)
|
checkKey(chk, Some(expected), eval)
|
||||||
}
|
}
|
||||||
|
|
||||||
def checkKey[T](key: ScopedKey[T], expected: Option[T], settings: Settings[Scope]) = {
|
def checkKey[T](key: ScopedKey[T], expected: Option[T], settings: Def.Settings) = {
|
||||||
val value = settings.get(key.scope, key.key)
|
val value = settings.get(key.scope, key.key)
|
||||||
("Key: " + key) |:
|
("Key: " + key) |:
|
||||||
("Value: " + value) |:
|
("Value: " + value) |:
|
||||||
|
|
@ -199,7 +199,7 @@ object SettingsTest extends Properties("settings") {
|
||||||
(value == expected)
|
(value == expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
def evaluate(settings: Seq[Setting[_]]): Settings[Scope] =
|
def evaluate(settings: Seq[Setting[_]]): Def.Settings =
|
||||||
try {
|
try {
|
||||||
makeWithCompiledMap(settings)(delegates, scopeLocal, showFullKey)._2
|
makeWithCompiledMap(settings)(delegates, scopeLocal, showFullKey)._2
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ final case class Scope(nestIndex: Int, idAtIndex: Int = 0)
|
||||||
// Lots of type constructors would become binary, which as you may know requires lots of type lambdas
|
// Lots of type constructors would become binary, which as you may know requires lots of type lambdas
|
||||||
// when you want a type function with only one parameter.
|
// when you want a type function with only one parameter.
|
||||||
// That would be a general pain.)
|
// That would be a general pain.)
|
||||||
case class SettingsExample() extends Init[Scope] {
|
case class SettingsExample() extends Init {
|
||||||
|
type ScopeType = Scope
|
||||||
// Provides a way of showing a Scope+AttributeKey[_]
|
// Provides a way of showing a Scope+AttributeKey[_]
|
||||||
val showFullKey: Show[ScopedKey[?]] = Show[ScopedKey[?]]((key: ScopedKey[?]) => {
|
val showFullKey: Show[ScopedKey[?]] = Show[ScopedKey[?]]((key: ScopedKey[?]) => {
|
||||||
s"${key.scope.nestIndex}(${key.scope.idAtIndex})/${key.key.label}"
|
s"${key.scope.nestIndex}(${key.scope.idAtIndex})/${key.key.label}"
|
||||||
|
|
@ -64,7 +65,7 @@ case class SettingsUsage(val settingsExample: SettingsExample) {
|
||||||
// "compiles" and applies the settings.
|
// "compiles" and applies the settings.
|
||||||
// This can be split into multiple steps to access intermediate results if desired.
|
// This can be split into multiple steps to access intermediate results if desired.
|
||||||
// The 'inspect' command operates on the output of 'compile', for example.
|
// The 'inspect' command operates on the output of 'compile', for example.
|
||||||
val applied: Settings[Scope] =
|
val applied: Settings =
|
||||||
makeWithCompiledMap(mySettings)(using delegates, scopeLocal, showFullKey)._2
|
makeWithCompiledMap(mySettings)(using delegates, scopeLocal, showFullKey)._2
|
||||||
|
|
||||||
// Show results.
|
// Show results.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue