try out simplified display of scoped keys

This commit is contained in:
Mark Harrah 2011-08-04 07:20:25 -04:00
parent 70113c88fa
commit a19d5a799c
12 changed files with 93 additions and 67 deletions

View File

@ -3,7 +3,7 @@
*/
package sbt
import Project.ScopedKey
import Project.{ScopedKey, showContextKey}
import Keys.{sessionSettings, thisProject}
import Load.BuildStructure
import complete.{DefaultParsers, Parser}
@ -143,8 +143,9 @@ object Act
private[this] def actParser0(state: State) =
{
val extracted = Project extract state
import extracted.{showKey, structure}
showParser.flatMap { show =>
scopedKeyParser(extracted) flatMap Aggregation.valueParser(state, extracted.structure, show)
scopedKeyParser(extracted) flatMap Aggregation.valueParser(state, structure, show)
}
}
def showParser = token( ("show" ~ Space) ^^^ true) ?? false

View File

@ -60,21 +60,21 @@ final object Aggregation
case Some(current) => Scope.resolveBuildOnly(current, ref)
}
def printSettings[T](xs: Seq[KeyValue[T]], log: Logger) =
def printSettings[T](xs: Seq[KeyValue[T]], log: Logger)(implicit display: Show[ScopedKey[_]]) =
xs match
{
case KeyValue(_,x) :: Nil => log.info(x.toString)
case _ => xs foreach { case KeyValue(key, value) => log.info(Project.display(key) + "\n\t" + value.toString) }
case _ => xs foreach { case KeyValue(key, value) => log.info(display(key) + "\n\t" + value.toString) }
}
type Values[T] = Seq[KeyValue[T]]
def seqParser[T](ps: Values[Parser[T]]): Parser[Seq[KeyValue[T]]] = seq(ps.map { case KeyValue(k,p) => p.map(v => KeyValue(k,v) ) })
def applyTasks[T](s: State, structure: BuildStructure, ps: Values[Parser[Task[T]]], show: Boolean): Parser[() => State] =
def applyTasks[T](s: State, structure: BuildStructure, ps: Values[Parser[Task[T]]], show: Boolean)(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
Command.applyEffect(seqParser(ps)) { ts =>
runTasks(s, structure, ts, Dummies(KNil, HNil), show)
s
}
def runTasks[HL <: HList, T](s: State, structure: Load.BuildStructure, ts: Values[Task[T]], extra: Dummies[HL], show: Boolean)
def runTasks[HL <: HList, T](s: State, structure: Load.BuildStructure, ts: Values[Task[T]], extra: Dummies[HL], show: Boolean)(implicit display: Show[ScopedKey[_]])
{
import EvaluateTask._
import std.TaskExtra._
@ -129,7 +129,7 @@ final object Aggregation
}
final case class Dummies[HL <: HList](tasks: KList[Task,HL], values: HL)
def applyDynamicTasks[I](s: State, structure: BuildStructure, inputs: Values[InputDynamic[I]], show: Boolean): Parser[() => State] =
def applyDynamicTasks[I](s: State, structure: BuildStructure, inputs: Values[InputDynamic[I]], show: Boolean)(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
{
val parsers = inputs.map { case KeyValue(k,t) => KeyValue(k, t parser s) }
Command.applyEffect(seqParser(parsers)) { parseds =>
@ -141,10 +141,10 @@ final object Aggregation
s
}
}
def valueParser(s: State, structure: BuildStructure, show: Boolean)(key: ScopedKey[_]): Parser[() => State] =
def valueParser(s: State, structure: BuildStructure, show: Boolean)(key: ScopedKey[_])(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
getTasks(key, structure, true).toList match
{
case Nil => failure("No such setting/task: " + (Project display key))
case Nil => failure("No such setting/task: " + display(key))
case xs @ KeyValue(_, _: InputStatic[t]) :: _ => applyTasks(s, structure, maps(xs.asInstanceOf[Values[InputStatic[t]]])(_.parser(s)), show)
case xs @ KeyValue(_, _: InputDynamic[t]) :: _ => applyDynamicTasks(s, structure, xs.asInstanceOf[Values[InputDynamic[t]]], show)
case xs @ KeyValue(_, _: Task[t]) :: _ => applyTasks(s, structure, maps(xs.asInstanceOf[Values[Task[t]]])(x => success(x)), show)

View File

@ -199,7 +199,7 @@ object Index
object BuildStreams
{
import Load.{BuildStructure, LoadedBuildUnit}
import Project.display
import Project.displayFull
import std.{TaskExtra,Transform}
import Path._
import BuildPaths.outputDirectory
@ -209,7 +209,7 @@ object BuildStreams
final val StreamsDirectory = "streams"
def mkStreams(units: Map[URI, LoadedBuildUnit], root: URI, data: Settings[Scope]): Streams =
std.Streams( path(units, root, data), display, LogManager.construct(data) )
std.Streams( path(units, root, data), displayFull, LogManager.construct(data) )
def path(units: Map[URI, LoadedBuildUnit], root: URI, data: Settings[Scope])(scoped: ScopedKey[_]): File =
resolvePath( projectPath(units, root, scoped, data), nonProjectPath(scoped) )
@ -221,7 +221,7 @@ object BuildStreams
axis match
{
case Global => GlobalPath
case This => error("Unresolved This reference for " + label + " in " + display(scoped))
case This => error("Unresolved This reference for " + label + " in " + Project.displayFull(scoped))
case Select(t) => show(t)
}
def nonProjectPath[T](scoped: ScopedKey[T]): Seq[String] =
@ -240,8 +240,8 @@ object BuildStreams
case Global => refTarget(GlobalScope, units(root).localBase, data) / GlobalPath
case Select(br @ BuildRef(uri)) => refTarget(br, units(uri).localBase, data) / BuildUnitPath
case Select(pr @ ProjectRef(uri, id)) => refTarget(pr, units(uri).defined(id).base, data)
case Select(pr) => error("Unresolved project reference (" + pr + ") in " + display(scoped))
case This => error("Unresolved project reference (This) in " + display(scoped))
case Select(pr) => error("Unresolved project reference (" + pr + ") in " + displayFull(scoped))
case This => error("Unresolved project reference (This) in " + displayFull(scoped))
}
def refTarget(ref: ResolvedReference, fallbackBase: File, data: Settings[Scope]): File =

View File

@ -218,7 +218,7 @@ object Defaults extends BuildCommon
override def watchPaths(s: State) = EvaluateTask.evaluateTask(Project structure s, key, s, base) match {
case Some(Value(ps)) => ps
case Some(Inc(i)) => throw i
case None => error("key not found: " + Project.display(key))
case None => error("key not found: " + Project.displayFull(key))
}
}
}
@ -244,14 +244,16 @@ object Defaults extends BuildCommon
definedTests <<= TaskData.writeRelated(detectTests)(_.map(_.name).distinct) triggeredBy compile,
testListeners in GlobalScope :== Nil,
testOptions in GlobalScope :== Nil,
executeTests <<= (streams in test, loadedTestFrameworks, parallelExecution in test, testOptions in test, testLoader, definedTests, resolvedScoped) flatMap {
(s, frameworkMap, par, options, loader, discovered, scoped) => Tests(frameworkMap, loader, discovered, options, par, noTestsMessage(ScopedKey(scoped.scope, test.key)), s.log)
executeTests <<= (streams in test, loadedTestFrameworks, parallelExecution in test, testOptions in test, testLoader, definedTests, resolvedScoped, state) flatMap {
(s, frameworkMap, par, options, loader, discovered, scoped, st) =>
implicit val display = Project.showContextKey(st)
Tests(frameworkMap, loader, discovered, options, par, noTestsMessage(ScopedKey(scoped.scope, test.key)), s.log)
},
test <<= (executeTests, streams) map { (results, s) => Tests.showResults(s.log, results) },
testOnly <<= testOnlyTask
)
private[this] def noTestsMessage(scoped: ScopedKey[_]): String =
"No tests to run for " + Project.display(scoped)
private[this] def noTestsMessage(scoped: ScopedKey[_])(implicit display: Show[ScopedKey[_]]): String =
"No tests to run for " + display(scoped)
lazy val TaskGlobal: Scope = ThisScope.copy(task = Global)
def testTaskOptions(key: Scoped): Seq[Setting[_]] = inTask(key)( Seq(
@ -276,10 +278,11 @@ object Defaults extends BuildCommon
def testOnlyTask =
InputTask( TaskData(definedTests)(testOnlyParser)(Nil) ) { result =>
(streams, loadedTestFrameworks, parallelExecution in testOnly, testOptions in testOnly, testLoader, definedTests, resolvedScoped, result) flatMap {
case (s, frameworks, par, opts, loader, discovered, scoped, (tests, frameworkOptions)) =>
(streams, loadedTestFrameworks, parallelExecution in testOnly, testOptions in testOnly, testLoader, definedTests, resolvedScoped, result, state) flatMap {
case (s, frameworks, par, opts, loader, discovered, scoped, (tests, frameworkOptions), st) =>
val filter = selectedFilter(tests)
val modifiedOpts = Tests.Filter(filter) +: Tests.Argument(frameworkOptions : _*) +: opts
implicit val display = Project.showContextKey(st)
Tests(frameworks, loader, discovered, modifiedOpts, par, noTestsMessage(scoped), s.log) map { results =>
Tests.showResults(s.log, results)
}

View File

@ -102,7 +102,7 @@ object EvaluateTask
case _ => c.toString
}
def name(node: Task[_]): String =
node.info.name orElse transformNode(node).map(Project.display) getOrElse ("<anon-" + System.identityHashCode(node).toHexString + ">")
node.info.name orElse transformNode(node).map(Project.displayFull) getOrElse ("<anon-" + System.identityHashCode(node).toHexString + ">")
def liftAnonymous: Incomplete => Incomplete = {
case i @ Incomplete(node, tpe, None, causes, None) =>
causes.find( inc => !inc.node.isDefined && (inc.message.isDefined || inc.directCause.isDefined)) match {

View File

@ -120,7 +120,7 @@ object Load
lazy val rootEval = lazyEval(loaded.units(loaded.root).unit)
val settings = finalTransforms(buildConfigurations(loaded, getRootProject(projects), rootEval, config.injectSettings))
val delegates = config.delegates(loaded)
val data = Project.makeSettings(settings, delegates, config.scopeLocal)
val data = Project.makeSettings(settings, delegates, config.scopeLocal)( Project.showLoadingKey( loaded ) )
val index = structureIndex(data, settings)
val streams = mkStreams(projects, loaded.root, data)
(rootEval, new BuildStructure(projects, loaded.root, settings, data, index, streams, delegates, config.scopeLocal))
@ -150,7 +150,7 @@ object Load
case resolvedScoped.key => Some(defining.asInstanceOf[T])
case parseResult.key =>
import std.TaskExtra._
val getResult = InputTask.inputMap map { m => m get defining getOrElse error("No parsed value for " + Project.display(defining) + "\n" + m) }
val getResult = InputTask.inputMap map { m => m get defining getOrElse error("No parsed value for " + Project.displayFull(defining) + "\n" + m) }
Some(getResult.asInstanceOf[T])
case _ => None
}
@ -169,7 +169,7 @@ object Load
}
// Reevaluates settings after modifying them. Does not recompile or reload any build components.
def reapply(newSettings: Seq[Setting[_]], structure: BuildStructure): BuildStructure =
def reapply(newSettings: Seq[Setting[_]], structure: BuildStructure)(implicit display: Show[ScopedKey[_]]): BuildStructure =
{
val transformed = finalTransforms(newSettings)
val newData = Project.makeSettings(transformed, structure.delegates, structure.scopeLocal)

View File

@ -315,7 +315,7 @@ object BuiltinCommands
def reapply(newSession: SessionSettings, structure: Load.BuildStructure, s: State): State =
{
logger(s).info("Reapplying settings...")
val newStructure = Load.reapply(newSession.mergeSettings, structure)
val newStructure = Load.reapply(newSession.mergeSettings, structure)( Project.showContextKey(newSession, structure) )
Project.setProject(newSession, newStructure, s)
}
def set = Command.single(SetCommand, setBrief, setDetailed) { (s, arg) =>
@ -327,14 +327,14 @@ object BuiltinCommands
reapply(newSession, structure, s)
}
def inspect = Command(InspectCommand, inspectBrief, inspectDetailed)(inspectParser) { case (s,(actual,sk)) =>
val detailString = Project.details(Project.structure(s), actual, sk.scope, sk.key)
val detailString = Project.details(Project.structure(s), actual, sk.scope, sk.key)( Project.showContextKey(s) )
logger(s).info(detailString)
s
}
def lastGrep = Command(LastGrepCommand, lastGrepBrief, lastGrepDetailed)(lastGrepParser) {
case (s, (pattern,Some(sk))) =>
val (str, ref) = extractLast(s)
Output.lastGrep(sk, str, pattern)
val (str, ref, display) = extractLast(s)
Output.lastGrep(sk, str, pattern)(display)
s
case (s, (pattern, None)) =>
Output.lastGrep(CommandSupport.globalLogging(s).backing, pattern)
@ -342,7 +342,7 @@ object BuiltinCommands
}
def extractLast(s: State) = {
val ext = Project.extract(s)
(ext.structure, Select(ext.currentRef))
(ext.structure, Select(ext.currentRef), ext.showKey)
}
def inspectParser = (s: State) => token((Space ~> ("actual" ^^^ true)) ?? false) ~ spacedKeyParser(s)
val spacedKeyParser = (s: State) => Act.requireSession(s, token(Space) ~> Act.scopedKeyParser(s))
@ -350,8 +350,8 @@ object BuiltinCommands
def lastGrepParser(s: State) = Act.requireSession(s, (token(Space) ~> token(NotSpace, "<pattern>")) ~ optSpacedKeyParser(s))
def last = Command(LastCommand, lastBrief, lastDetailed)(optSpacedKeyParser) {
case (s,Some(sk)) =>
val (str, ref) = extractLast(s)
Output.last(sk, str)
val (str, ref, display) = extractLast(s)
Output.last(sk, str)(display)
s
case (s, None) =>
Output.last( CommandSupport.globalLogging(s).backing )

View File

@ -30,10 +30,10 @@ object Output
}
final val DefaultTail = "> "
def last(key: ScopedKey[_], structure: BuildStructure): Unit = printLines( flatLines(lastLines(key, structure))(idFun) )
def last(key: ScopedKey[_], structure: BuildStructure)(implicit display: Show[ScopedKey[_]]): Unit = printLines( flatLines(lastLines(key, structure))(idFun) )
def last(file: File, tailDelim: String = DefaultTail): Unit = printLines(tailLines(file, tailDelim))
def lastGrep(key: ScopedKey[_], structure: BuildStructure, patternString: String): Unit =
def lastGrep(key: ScopedKey[_], structure: BuildStructure, patternString: String)(implicit display: Show[ScopedKey[_]]): Unit =
{
val pattern = Pattern compile patternString
val lines = flatLines( lastLines(key, structure) )(_ flatMap showMatches(pattern))
@ -44,12 +44,12 @@ object Output
def grep(lines: Seq[String], patternString: String): Seq[String] =
lines flatMap showMatches(Pattern compile patternString)
def flatLines(outputs: Seq[KeyValue[Seq[String]]])(f: Seq[String] => Seq[String]): Seq[String] =
def flatLines(outputs: Seq[KeyValue[Seq[String]]])(f: Seq[String] => Seq[String])(implicit display: Show[ScopedKey[_]]): Seq[String] =
{
val single = outputs.size == 1
outputs flatMap { case KeyValue(key, lines) =>
val flines = f(lines)
if(!single) bold(Project.display(key)) +: flines else flines
if(!single) bold(display(key)) +: flines else flines
}
}
def printLines(lines: Seq[String]) = lines foreach println

View File

@ -61,14 +61,14 @@ sealed trait Project extends ProjectDefinition[ProjectReference]
}
sealed trait ResolvedProject extends ProjectDefinition[ProjectRef]
final case class Extracted(structure: BuildStructure, session: SessionSettings, currentRef: ProjectRef)
final case class Extracted(structure: BuildStructure, session: SessionSettings, currentRef: ProjectRef)(implicit val showKey: Show[ScopedKey[_]])
{
def rootProject = structure.rootProject
lazy val currentUnit = structure units currentRef.build
lazy val currentProject = currentUnit defined currentRef.project
lazy val currentLoader: ClassLoader = currentUnit.loader
def get[T](key: ScopedTask[T]): Task[T] = get(key.task)
def get[T](key: ScopedSetting[T]): T = getOrError(inCurrent(key), key.key)
def get[T](key: ScopedSetting[T]) = getOrError(inCurrent(key), key.key)
def getOpt[T](key: ScopedSetting[T]): Option[T] = structure.data.get(inCurrent(key), key.key)
private[this] def inCurrent[T](key: ScopedSetting[T]): Scope = if(key.scope.project == This) key.scope.copy(project = Select(currentRef)) else key.scope
def evalTask[T](key: ScopedTask[T], state: State): T =
@ -80,10 +80,10 @@ final case class Extracted(structure: BuildStructure, session: SessionSettings,
val result = getOrError(rkey.scope, rkey.key, value)
processResult(result, ConsoleLogger())
}
private def getOrError[T](scope: Scope, key: AttributeKey[_], value: Option[T]): T =
value getOrElse error(Project.display(ScopedKey(scope, key)) + " is undefined.")
private def getOrError[T](scope: Scope, key: AttributeKey[T]): T =
structure.data.get(scope, key) getOrElse error(Project.display(ScopedKey(scope, key)) + " is undefined.")
private def getOrError[T](scope: Scope, key: AttributeKey[_], value: Option[T])(implicit display: Show[ScopedKey[_]]): T =
value getOrElse error(display(ScopedKey(scope, key)) + " is undefined.")
private def getOrError[T](scope: Scope, key: AttributeKey[T])(implicit display: Show[ScopedKey[_]]): T =
structure.data.get(scope, key) getOrElse error(display(ScopedKey(scope, key)) + " is undefined.")
def append(settings: Seq[Setting[_]], state: State): State =
{
@ -99,6 +99,21 @@ final case class ClasspathDependency(project: ProjectReference, configuration: O
object Project extends Init[Scope] with ProjectExtra
{
lazy val showFullKey: Show[ScopedKey[_]] = new Show[ScopedKey[_]] { def apply(key: ScopedKey[_]) = displayFull(key) }
def showContextKey(state: State): Show[ScopedKey[_]] =
if(isProjectLoaded(state)) showContextKey( session(state), structure(state) ) else showFullKey
def showContextKey(session: SessionSettings, structure: BuildStructure): Show[ScopedKey[_]] = showRelativeKey(session.current, structure.allProjects.size > 1)
def showLoadingKey(loaded: Load.LoadedBuild): Show[ScopedKey[_]] = showRelativeKey( ProjectRef(loaded.root, loaded.units(loaded.root).rootProjects.head), loaded.allProjectRefs.size > 1 )
def showRelativeKey(current: ProjectRef, multi: Boolean): Show[ScopedKey[_]] = new Show[ScopedKey[_]] {
def apply(key: ScopedKey[_]) = Scope.display(key.scope, key.key.label, ref => displayRelative(current, multi, ref))
}
def displayRelative(current: ProjectRef, multi: Boolean, project: Reference): String = project match {
case BuildRef(current.build) => "{.}/"
case `current` => if(multi) current.project + "/" else ""
case ProjectRef(current.build, x) => x + "/"
case _ => display(project)
}
private abstract class ProjectDef[PR <: ProjectReference](val id: String, val base: File, aggregate0: => Seq[PR], dependencies0: => Seq[ClasspathDep[PR]], delegates0: => Seq[PR],
settings0: => Seq[Setting[_]], val configurations: Seq[Configuration]) extends ProjectDefinition[PR]
{
@ -130,7 +145,7 @@ object Project extends Init[Scope] with ProjectExtra
def isProjectLoaded(state: State): Boolean = (state has sessionSettings) && (state has stateBuildStructure)
def extract(state: State): Extracted = extract( session(state), structure(state) )
def extract(se: SessionSettings, st: BuildStructure): Extracted = Extracted(st, se, se.current)
def extract(se: SessionSettings, st: BuildStructure): Extracted = Extracted(st, se, se.current)( showContextKey(se, st) )
def getProjectForReference(ref: Reference, structure: BuildStructure): Option[ResolvedProject] =
ref match { case pr: ProjectRef => getProject(pr, structure); case _ => None }
@ -172,10 +187,10 @@ object Project extends Init[Scope] with ProjectExtra
}
def setCond[T](key: AttributeKey[T], vopt: Option[T], attributes: AttributeMap): AttributeMap =
vopt match { case Some(v) => attributes.put(key, v); case None => attributes.remove(key) }
def makeSettings(settings: Seq[Setting[_]], delegates: Scope => Seq[Scope], scopeLocal: ScopedKey[_] => Seq[Setting[_]]) =
translateCyclic( make(settings)(delegates, scopeLocal) )
def makeSettings(settings: Seq[Setting[_]], delegates: Scope => Seq[Scope], scopeLocal: ScopedKey[_] => Seq[Setting[_]])(implicit display: Show[ScopedKey[_]]) =
translateCyclic( make(settings)(delegates, scopeLocal, display) )
def display(scoped: ScopedKey[_]): String = Scope.display(scoped.scope, scoped.key.label)
def displayFull(scoped: ScopedKey[_]): String = Scope.display(scoped.scope, scoped.key.label)
def display(ref: Reference): String =
ref match
{
@ -219,7 +234,7 @@ object Project extends Init[Scope] with ProjectExtra
def delegates(structure: BuildStructure, scope: Scope, key: AttributeKey[_]): Seq[ScopedKey[_]] =
structure.delegates(scope).map(d => ScopedKey(d, key))
def details(structure: BuildStructure, actual: Boolean, scope: Scope, key: AttributeKey[_]): String =
def details(structure: BuildStructure, actual: Boolean, scope: Scope, key: AttributeKey[_])(implicit display: Show[ScopedKey[_]]): String =
{
val scoped = ScopedKey(scope,key)
lazy val clazz = key.manifest.erasure
@ -242,12 +257,12 @@ object Project extends Init[Scope] with ProjectExtra
case Some(sc) => "Provided by:\n\t" + Scope.display(sc, key.label) + "\n"
case None => ""
}
val cMap = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal)
val cMap = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display)
val related = cMap.keys.filter(k => k.key == key && k.scope != scope)
val depends = cMap.get(scoped) match { case Some(c) => c.dependencies.toSet; case None => Set.empty }
val reverse = reverseDependencies(cMap, scoped)
def printScopes(label: String, scopes: Iterable[ScopedKey[_]]) =
if(scopes.isEmpty) "" else scopes.map(display).mkString(label + ":\n\t", "\n\t", "\n")
if(scopes.isEmpty) "" else scopes.map(display.apply).mkString(label + ":\n\t", "\n\t", "\n")
value + "\n" +
description +
@ -257,22 +272,22 @@ object Project extends Init[Scope] with ProjectExtra
printScopes("Delegates", delegates(structure, scope, key)) +
printScopes("Related", related)
}
def graphSettings(structure: BuildStructure, basedir: File)
def graphSettings(structure: BuildStructure, basedir: File)(implicit display: Show[ScopedKey[_]])
{
def graph(actual: Boolean, name: String) = graphSettings(structure, actual, name, new File(basedir, name + ".dot"))
graph(true, "actual_dependencies")
graph(false, "declared_dependencies")
}
def graphSettings(structure: BuildStructure, actual: Boolean, graphName: String, file: File)
def graphSettings(structure: BuildStructure, actual: Boolean, graphName: String, file: File)(implicit display: Show[ScopedKey[_]])
{
val rel = relation(structure, actual)
val keyToString = (key: ScopedKey[_]) => Project display key
val keyToString = display.apply _
DotGraph.generateGraph(file, graphName, rel, keyToString, keyToString)
}
def relation(structure: BuildStructure, actual: Boolean) =
def relation(structure: BuildStructure, actual: Boolean)(implicit display: Show[ScopedKey[_]]) =
{
type Rel = Relation[ScopedKey[_], ScopedKey[_]]
val cMap = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal)
val cMap = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display)
((Relation.empty: Rel) /: cMap) { case (r, (key, value)) =>
r + (key, value.dependencies)
}

View File

@ -98,16 +98,17 @@ object Scope
}
def display(config: ConfigKey): String = config.name + ":"
def display(scope: Scope, sep: String): String =
def display(scope: Scope, sep: String): String = display(scope, sep, ref => Project.display(ref) + "/")
def display(scope: Scope, sep: String, showProject: Reference => String): String =
{
import scope.{project, config, task, extra}
val projectPrefix = project.foldStrict(Project.display, "*", ".")
val projectPrefix = project.foldStrict(showProject, "*/", "./")
val configPrefix = config.foldStrict(display, "*:", ".:")
val taskPostfix = task.foldStrict(x => ("for " + x.label) :: Nil, Nil, Nil)
val extraPostfix = extra.foldStrict(_.entries.map( _.toString ).toList, Nil, Nil)
val extras = taskPostfix ::: extraPostfix
val postfix = if(extras.isEmpty) "" else extras.mkString("(", ", ", ")")
projectPrefix + "/" + configPrefix + sep + postfix
projectPrefix + configPrefix + sep + postfix
}
def parseScopedKey(command: String): (Scope, String) =

View File

@ -41,7 +41,8 @@ private final class Settings0[Scope](val data: Map[Scope, AttributeMap], val del
// this trait is intended to be mixed into an object
trait Init[Scope]
{
def display(skey: ScopedKey[_]): String
/** The Show instance used when a detailed String needs to be generated. It is typically used when no context is available.*/
def showFullKey: Show[ScopedKey[_]]
final case class ScopedKey[T](scope: Scope, key: AttributeKey[T])
@ -72,23 +73,23 @@ trait Init[Scope]
def asTransform(s: Settings[Scope]): ScopedKey ~> Id = new (ScopedKey ~> Id) {
def apply[T](k: ScopedKey[T]): T = getValue(s, k)
}
def getValue[T](s: Settings[Scope], k: ScopedKey[T]) = s.get(k.scope, k.key) getOrElse error("Internal settings error: invalid reference to " + display(k))
def getValue[T](s: Settings[Scope], k: ScopedKey[T]) = s.get(k.scope, k.key) getOrElse error("Internal settings error: invalid reference to " + showFullKey(k))
def asFunction[T](s: Settings[Scope]): ScopedKey[T] => T = k => getValue(s, k)
def compiled(init: Seq[Setting[_]], actual: Boolean = true)(implicit delegates: Scope => Seq[Scope], scopeLocal: ScopeLocal): CompiledMap =
def compiled(init: Seq[Setting[_]], actual: Boolean = true)(implicit delegates: Scope => Seq[Scope], scopeLocal: ScopeLocal, display: Show[ScopedKey[_]]): CompiledMap =
{
// prepend per-scope settings
val withLocal = addLocal(init)(scopeLocal)
// group by Scope/Key, dropping dead initializations
val sMap: ScopedMap = grouped(withLocal)
// delegate references to undefined values according to 'delegates'
val dMap: ScopedMap = if(actual) delegate(sMap)(delegates) else sMap
val dMap: ScopedMap = if(actual) delegate(sMap)(delegates, display) else sMap
// merge Seq[Setting[_]] into Compiled
compile(dMap)
}
def make(init: Seq[Setting[_]])(implicit delegates: Scope => Seq[Scope], scopeLocal: ScopeLocal): Settings[Scope] =
def make(init: Seq[Setting[_]])(implicit delegates: Scope => Seq[Scope], scopeLocal: ScopeLocal, display: Show[ScopedKey[_]]): Settings[Scope] =
{
val cMap = compiled(init)(delegates, scopeLocal)
val cMap = compiled(init)(delegates, scopeLocal, display)
// order the initializations. cyclic references are detected here.
val ordered: Seq[Compiled] = sort(cMap)
// evaluation: apply the initializations.
@ -116,7 +117,7 @@ trait Init[Scope]
def addLocal(init: Seq[Setting[_]])(implicit scopeLocal: ScopeLocal): Seq[Setting[_]] =
init.flatMap( _.dependsOn flatMap scopeLocal ) ++ init
def delegate(sMap: ScopedMap)(implicit delegates: Scope => Seq[Scope]): ScopedMap =
def delegate(sMap: ScopedMap)(implicit delegates: Scope => Seq[Scope], display: Show[ScopedKey[_]]): ScopedMap =
{
def refMap(refKey: ScopedKey[_], isFirst: Boolean) = new ValidateRef { def apply[T](k: ScopedKey[T]) =
delegateForKey(sMap, k, delegates(k.scope), refKey, isFirst)
@ -156,7 +157,7 @@ trait Init[Scope]
map.set(key.scope, key.key, value)
}
def showUndefined(u: Undefined, sMap: ScopedMap, delegates: Scope => Seq[Scope]): String =
def showUndefined(u: Undefined, sMap: ScopedMap, delegates: Scope => Seq[Scope])(implicit display: Show[ScopedKey[_]]): String =
{
val guessed = guessIntendedScope(sMap, delegates, u.referencedKey)
display(u.referencedKey) + " from " + display(u.definingKey) + guessed.map(g => "\n Did you mean " + display(g) + " ?").toList.mkString
@ -178,7 +179,7 @@ trait Init[Scope]
final class Uninitialized(val undefined: Seq[Undefined], msg: String) extends Exception(msg)
final class Undefined(val definingKey: ScopedKey[_], val referencedKey: ScopedKey[_])
def Undefined(definingKey: ScopedKey[_], referencedKey: ScopedKey[_]): Undefined = new Undefined(definingKey, referencedKey)
def Uninitialized(sMap: ScopedMap, delegates: Scope => Seq[Scope], keys: Seq[Undefined]): Uninitialized =
def Uninitialized(sMap: ScopedMap, delegates: Scope => Seq[Scope], keys: Seq[Undefined])(implicit display: Show[ScopedKey[_]]): Uninitialized =
{
assert(!keys.isEmpty)
val suffix = if(keys.length > 1) "s" else ""
@ -187,7 +188,7 @@ trait Init[Scope]
}
final class Compiled(val key: ScopedKey[_], val dependencies: Iterable[ScopedKey[_]], val eval: Settings[Scope] => Settings[Scope])
{
override def toString = display(key)
override def toString = showFullKey(key)
}
sealed trait Initialize[T]

View File

@ -0,0 +1,5 @@
package sbt
trait Show[T] {
def apply(t: T): String
}