Remove support for project delegation from setting system.

This provides a small performance improvement during delegation stage of settings processing.
This commit doesn't remove the deprecated methods in Project yet.
It also removes delegation of the extra axis (currently unused, so no effect on users).
This commit is contained in:
Mark Harrah
2014-01-14 16:18:28 -05:00
parent 7d4b7e7ee3
commit 2bf28fffae
4 changed files with 84 additions and 85 deletions
@@ -2,18 +2,16 @@ package sbt
sealed trait DelegateIndex
{
def project(ref: ProjectRef): Seq[ScopeAxis[ResolvedReference]]
def config(ref: ProjectRef, conf: ConfigKey): Seq[ScopeAxis[ConfigKey]]
def config(ref: ResolvedReference, conf: ConfigKey): Seq[ScopeAxis[ConfigKey]]
// def task(ref: ProjectRef, task: ScopedKey[_]): Seq[ScopeAxis[ScopedKey[_]]]
// def extra(ref: ProjectRef, e: AttributeMap): Seq[ScopeAxis[AttributeMap]]
}
private final class DelegateIndex0(refs: Map[ProjectRef, ProjectDelegates]) extends DelegateIndex
private final class DelegateIndex0(refs: Map[ResolvedReference, ProjectDelegates]) extends DelegateIndex
{
def project(ref: ProjectRef): Seq[ScopeAxis[ResolvedReference]] = refs.get(ref) match { case Some(pd) => pd.refs; case None => Nil }
def config(ref: ProjectRef, conf: ConfigKey): Seq[ScopeAxis[ConfigKey]] =
def config(ref: ResolvedReference, conf: ConfigKey): Seq[ScopeAxis[ConfigKey]] =
refs.get(ref) match {
case Some(pd) => pd.confs.get(conf) match { case Some(cs) => cs; case None => Select(conf) :: Global :: Nil }
case None => Select(conf) :: Global :: Nil
}
}
private final class ProjectDelegates(val ref: ProjectRef, val refs: Seq[ScopeAxis[ResolvedReference]], val confs: Map[ConfigKey, Seq[ScopeAxis[ConfigKey]]])
private final class ProjectDelegates(val confs: Map[ConfigKey, Seq[ScopeAxis[ConfigKey]]])
+51 -48
View File
@@ -29,7 +29,7 @@ object Scope
def replaceThis(thisScope: Scope): Scope => Scope = (scope: Scope) =>
Scope(subThis(thisScope.project, scope.project), subThis(thisScope.config, scope.config), subThis(thisScope.task, scope.task), subThis(thisScope.extra, scope.extra))
def subThis[T](sub: ScopeAxis[T], into: ScopeAxis[T]): ScopeAxis[T] =
if(into == This) sub else into
@@ -39,7 +39,7 @@ object Scope
case _: Select[_] => scope
case _ => scope.copy(task = Select(key))
}
def mapReference(f: Reference => Reference): Scope => Scope =
{
case Scope(Select(ref), a,b,c) => Scope(Select(f(ref)), a,b,c)
@@ -83,7 +83,7 @@ object Scope
case br: BuildReference => resolveBuildRef(current, br)
case pr: ProjectReference => resolveProjectRef(current, rootProject, pr)
}
def resolveProjectRef(current: URI, rootProject: URI => String, ref: ProjectReference): ProjectRef =
ref match
{
@@ -103,7 +103,7 @@ object Scope
def display(scope: Scope, sep: String): String = displayMasked(scope, sep, showProject, ScopeMask())
def displayMasked(scope: Scope, sep: String, mask: ScopeMask): String = displayMasked(scope, sep, showProject, mask)
def display(scope: Scope, sep: String, showProject: Reference => String): String = displayMasked(scope, sep, showProject, ScopeMask())
def displayMasked(scope: Scope, sep: String, showProject: Reference => String, mask: ScopeMask): String =
def displayMasked(scope: Scope, sep: String, showProject: Reference => String, mask: ScopeMask): String =
{
import scope.{project, config, task, extra}
val configPrefix = config.foldStrict(display, "*:", ".:")
@@ -130,7 +130,7 @@ object Scope
(Scope(pref, conf, This, This), transformTaskName(key))
}
val ScopedKeyRegex = """((\w+)\/)?((\w+)\:)?([\w\-]+)""".r
def transformTaskName(s: String) =
{
val parts = s.split("-+")
@@ -143,32 +143,30 @@ object Scope
configurations: Proj => Seq[ConfigKey],
resolve: Reference => ResolvedReference,
rootProject: URI => String,
projectInherit: ProjectRef => Seq[ProjectRef],
configInherit: (ResolvedReference, ConfigKey) => Seq[ConfigKey],
taskInherit: AttributeKey[_] => Seq[AttributeKey[_]],
extraInherit: (ResolvedReference, AttributeMap) => Seq[AttributeMap]): Scope => Seq[Scope] =
taskInherit: AttributeKey[_] => Seq[AttributeKey[_]]): Scope => Seq[Scope] =
{
val index = delegates(refs, configurations, projectInherit, configInherit)
scope => indexedDelegates(resolve, index, rootProject, taskInherit, extraInherit)(scope)
val index = delegates(refs, rootProject, configurations, configInherit)
scope => indexedDelegates(resolve, index, rootProject, taskInherit)(scope)
}
def indexedDelegates(
resolve: Reference => ResolvedReference,
index: DelegateIndex,
rootProject: URI => String,
taskInherit: AttributeKey[_] => Seq[AttributeKey[_]],
extraInherit: (ResolvedReference, AttributeMap) => Seq[AttributeMap])(rawScope: Scope): Seq[Scope] =
taskInherit: AttributeKey[_] => Seq[AttributeKey[_]])(rawScope: Scope): Seq[Scope] =
{
val scope = Scope.replaceThis(GlobalScope)(rawScope)
def linearizeTask(t: AttributeKey[_]): Seq[ScopeAxis[AttributeKey[_]]] =
linearize[AttributeKey[_]](t)(taskInherit)
def nonProjectScopes(resolvedProj: ResolvedReference)(px: ScopeAxis[ResolvedReference]) =
{
val p = px.toOption getOrElse resolvedProj
val configProj = p match { case pr: ProjectRef => pr; case br: BuildRef => ProjectRef(br.build, rootProject(br.build)) }
val cLin = scope.config match { case Select(conf) => index.config(configProj, conf); case _ => withGlobalAxis(scope.config) }
val tLin = scope.task match { case t @ Select(task) => linearize(t)(taskInherit); case _ => withGlobalAxis(scope.task) }
val eLin = withGlobalAxis(scope.extra)
for(c <- cLin; t <- tLin; e <- eLin) yield Scope(px, c, t, e)
val cLin = scope.config match { case Select(conf) => index.config(p, conf); case _ => withGlobalAxis(scope.config) }
val tLin = scope.task match { case t @ Select(task) => linearizeTask(task); case _ => withGlobalAxis(scope.task) }
for(c <- cLin; t <- tLin) yield Scope(px, c, t, scope.extra)
}
scope.project match
{
@@ -178,7 +176,7 @@ object Scope
val projAxes: Seq[ScopeAxis[ResolvedReference]] =
resolvedProj match
{
case pr: ProjectRef => index.project(pr)
case pr: ProjectRef => Select(pr) :: Select(BuildRef(pr.build)) :: Global :: Nil
case br: BuildRef => Select(br) :: Global :: Nil
}
projAxes flatMap nonProjectScopes(resolvedProj)
@@ -187,46 +185,51 @@ object Scope
def withGlobalAxis[T](base: ScopeAxis[T]): Seq[ScopeAxis[T]] = if(base.isSelect) base :: Global :: Nil else Global :: Nil
def withGlobalScope(base: Scope): Seq[Scope] = if(base == GlobalScope) GlobalScope :: Nil else base :: GlobalScope :: Nil
def withRawBuilds(ps: Seq[ScopeAxis[ProjectRef]]): Seq[ScopeAxis[ResolvedReference]] =
ps ++ (ps flatMap rawBuild).distinct :+ Global
def rawBuild(ps: ScopeAxis[ProjectRef]): Seq[ScopeAxis[BuildRef]] = ps match { case Select(ref) => Select(BuildRef(ref.build)) :: Nil; case _ => Nil }
def delegates[Proj](
private[this] def delegates[Proj](
refs: Seq[(ProjectRef, Proj)],
rootProject: URI => String,
configurations: Proj => Seq[ConfigKey],
projectInherit: ProjectRef => Seq[ProjectRef],
configInherit: (ResolvedReference, ConfigKey) => Seq[ConfigKey]): DelegateIndex =
{
val pDelegates = refs map { case (ref, project) =>
(ref, delegateIndex(ref, configurations(project))(projectInherit, configInherit) )
val index = new ProjectDelegates(configurations(project).map( c => axisDelegates(configInherit, ref, c) ).toMap)
(ref, index)
} toMap ;
new DelegateIndex0(pDelegates)
}
private[this] def delegateIndex(ref: ProjectRef, confs: Seq[ConfigKey])(projectInherit: ProjectRef => Seq[ProjectRef], configInherit: (ResolvedReference, ConfigKey) => Seq[ConfigKey]): ProjectDelegates =
{
val refDelegates = withRawBuilds(linearize(Select(ref), false)(projectInherit))
val configs = confs map { c => axisDelegates(configInherit, ref, c) }
new ProjectDelegates(ref, refDelegates, configs.toMap)
}
def axisDelegates[T](direct: (ResolvedReference, T) => Seq[T], ref: ResolvedReference, init: T): (T, Seq[ScopeAxis[T]]) =
( init, linearize(Select(init))(direct(ref, _)) )
def linearize[T](axis: ScopeAxis[T], appendGlobal: Boolean = true)(inherit: T => Seq[T]): Seq[ScopeAxis[T]] =
axis match
{
case Select(x) => topologicalSort[T](x, appendGlobal)(inherit)
case Global | This => if(appendGlobal) Global :: Nil else Nil
val buildURIs = refs.map(_._1.build).distinct
val bDelegates = for(build <- buildURIs) yield {
val ref = ProjectRef(build, rootProject(build))
(BuildRef(build), pDelegates(ref))
}
def topologicalSort[T](node: T, appendGlobal: Boolean)(dependencies: T => Seq[T]): Seq[ScopeAxis[T]] =
{
val o = Dag.topologicalSortUnchecked(node)(dependencies).map(Select.apply)
if(appendGlobal) o ::: Global :: Nil else o
new DelegateIndex0(pDelegates ++ bDelegates)
}
def axisDelegates[T](direct: (ResolvedReference, T) => Seq[T], ref: ResolvedReference, init: T): (T, Seq[ScopeAxis[T]]) =
( init, linearize(init)(direct(ref, _)) )
def globalProjectDelegates(scope: Scope): Seq[Scope] =
if(scope == GlobalScope)
GlobalScope :: Nil
else
for( c <- withGlobalAxis(scope.config); t <- withGlobalAxis(scope.task); e <- withGlobalAxis(scope.extra) ) yield Scope(Global, c, t, e)
for( c <- withGlobalAxis(scope.config); t <- withGlobalAxis(scope.task) ) yield Scope(Global, c, t, scope.extra)
// inlined topologicalSort for performance
private[this] def linearize[T](node: T)(dependencies: T => Seq[T]): Seq[ScopeAxis[T]] =
{
val discovered = new java.util.HashSet[T]
// always include Global at the end
var finished: List[ScopeAxis[T]] = Global :: Nil
def visitAll(nodes: Seq[T]) = nodes foreach visit
def visit(node : T){
if (!discovered.contains(node)) {
discovered.add(node)
visitAll(dependencies(node))
finished ::= Select(node);
}
}
visit(node)
finished
}
}
+12 -17
View File
@@ -76,7 +76,7 @@ object Load
config.copy(injectSettings = config.injectSettings.copy(projectLoaded = compiled))
}
def buildGlobalSettings(base: File, files: Seq[File], config: sbt.LoadBuildConfiguration): ClassLoader => Seq[Setting[_]] =
{
{
val eval = mkEval(data(config.classpath), base, defaultEvalOptions)
val imports = BuildUtil.baseImports ++ BuildUtil.importAllRoot(config.globalPluginNames)
loader => EvaluateConfigurations(eval, files, imports)(loader).settings
@@ -104,10 +104,8 @@ object Load
(_: ResolvedProject).configurations.map(c => ConfigKey(c.name)),
resolveRef,
rootProject,
project => projectInherit(lb, project),
(project, config) => configInherit(lb, project, config, rootProject),
task => task.extend,
(project, extra) => Nil
task => task.extend
)
}
def configInherit(lb: sbt.LoadedBuild, ref: ResolvedReference, config: ConfigKey, rootProject: URI => String): Seq[ConfigKey] =
@@ -119,9 +117,6 @@ object Load
def configInheritRef(lb: sbt.LoadedBuild, ref: ProjectRef, config: ConfigKey): Seq[ConfigKey] =
configurationOpt(lb.units, ref.build, ref.project, config).toList.flatMap(_.extendsConfigs).map(c => ConfigKey(c.name))
def projectInherit(lb: sbt.LoadedBuild, ref: ProjectRef): Seq[ProjectRef] =
getProject(lb.units, ref.build, ref.project).delegates
// build, load, and evaluate all units.
// 1) Compile all plugin definitions
// 2) Evaluate plugin definitions to obtain and compile plugins and get the resulting classpath for the build definition
@@ -211,7 +206,7 @@ object Load
def buildConfigurations(loaded: sbt.LoadedBuild, rootProject: URI => String, injectSettings: InjectSettings): Seq[Setting[_]] =
{
((loadedBuild in GlobalScope :== loaded) +:
transformProjectOnly(loaded.root, rootProject, injectSettings.global)) ++
transformProjectOnly(loaded.root, rootProject, injectSettings.global)) ++
inScope(GlobalScope)( pluginGlobalSettings(loaded) ) ++
loaded.units.toSeq.flatMap { case (uri, build) =>
val plugins = build.unit.plugins.plugins
@@ -245,7 +240,7 @@ object Load
def transformSettings(thisScope: Scope, uri: URI, rootProject: URI => String, settings: Seq[Setting[_]]): Seq[Setting[_]] =
Project.transform(Scope.resolveScope(thisScope, uri, rootProject), settings)
def projectScope(project: Reference): Scope = Scope(Select(project), Global, Global, Global)
def lazyEval(unit: sbt.BuildUnit): () => Eval =
{
lazy val eval = mkEval(unit)
@@ -454,7 +449,7 @@ Time.complete("default builds")
new sbt.BuildUnit(uri, normBase, loadedDefs, plugs)
}
private[this] def autoID(localBase: File, context: PluginManagement.Context, existingIDs: Seq[String]): String =
private[this] def autoID(localBase: File, context: PluginManagement.Context, existingIDs: Seq[String]): String =
{
def normalizeID(f: File) = Project.normalizeProjectID(f.getName) match {
case Right(id) => id
@@ -469,11 +464,11 @@ Time.complete("default builds")
if(existingIDs.contains(tryID)) Build.defaultID(localBase) else tryID
}
private[this] def autoIDError(base: File, reason: String): String =
private[this] def autoIDError(base: File, reason: String): String =
"Could not derive root project ID from directory " + base.getAbsolutePath + ":\n" +
reason + "\nRename the directory or explicitly define a root project."
private[this] def projectsFromBuild(b: Build, base: File): Seq[Project] =
private[this] def projectsFromBuild(b: Build, base: File): Seq[Project] =
b.projectDefinitions(base).map(resolveBase(base))
private[this] def loadTransitive(newProjects: Seq[Project], buildBase: File, imports: Seq[String], plugins: sbt.LoadedPlugins, eval: () => Eval, injectSettings: InjectSettings, acc: Seq[Project], memoSettings: mutable.Map[File, LoadedSbtFile]): Seq[Project] =
@@ -499,7 +494,7 @@ Time.complete("default builds")
else
loadTransitive(nextProjects, buildBase, imports, plugins, eval, injectSettings, loadedProjects, memoSettings)
}
private[this] def loadSettings(auto: AddSettings, projectBase: File, buildImports: Seq[String], loadedPlugins: sbt.LoadedPlugins, eval: ()=>Eval, injectSettings: InjectSettings, memoSettings: mutable.Map[File, LoadedSbtFile]): LoadedSbtFile =
{
lazy val defaultSbtFiles = configurationSources(projectBase)
@@ -586,7 +581,7 @@ Time.complete("default builds")
def pluginDefinitionLoader(config: sbt.LoadBuildConfiguration, dependencyClasspath: Seq[Attributed[File]]): (Seq[Attributed[File]], ClassLoader) =
pluginDefinitionLoader(config, dependencyClasspath, Nil)
def pluginDefinitionLoader(config: sbt.LoadBuildConfiguration, pluginData: PluginData): (Seq[Attributed[File]], ClassLoader) =
pluginDefinitionLoader(config, pluginData.dependencyClasspath, pluginData.definitionClasspath)
pluginDefinitionLoader(config, pluginData.dependencyClasspath, pluginData.definitionClasspath)
def pluginDefinitionLoader(config: sbt.LoadBuildConfiguration, depcp: Seq[Attributed[File]], defcp: Seq[Attributed[File]]): (Seq[Attributed[File]], ClassLoader) =
{
val definitionClasspath =
@@ -686,7 +681,7 @@ Time.complete("default builds")
def initialSession(structure: sbt.BuildStructure, rootEval: () => Eval): SessionSettings =
new SessionSettings(structure.root, projectMap(structure, Map.empty), structure.settings, Map.empty, Nil, rootEval)
def projectMap(structure: sbt.BuildStructure, current: Map[URI, String]): Map[URI, String] =
{
val units = structure.units
@@ -715,7 +710,7 @@ Time.complete("default builds")
def getImports(unit: sbt.BuildUnit): Seq[String] = BuildUtil.getImports(unit)
def referenced[PR <: ProjectReference](definitions: Seq[ProjectDefinition[PR]]): Seq[PR] = definitions flatMap { _.referenced }
@deprecated("LoadedBuildUnit is now top-level", "0.13.0")
type LoadedBuildUnit = sbt.LoadedBuildUnit
@@ -727,7 +722,7 @@ Time.complete("default builds")
@deprecated("LoadBuildConfiguration is now top-level", "0.13.0")
type LoadBuildConfiguration = sbt.LoadBuildConfiguration
@deprecated("LoadBuildConfiguration is now top-level", "0.13.0")
@deprecated("LoadBuildConfiguration is now top-level", "0.13.0")
val LoadBuildConfiguration = sbt.LoadBuildConfiguration
final class EvaluatedConfigurations(val eval: Eval, val settings: Seq[Setting[_]])
+17 -14
View File
@@ -105,7 +105,6 @@ object TestBuild
def rootProject(uri: URI): String = buildMap(uri).root.id
def inheritConfig(ref: ResolvedReference, config: ConfigKey) = projectFor(ref).confMap(config.name).extended map toConfigKey
def inheritTask(task: AttributeKey[_]) = taskMap.get(task) match { case None => Nil; case Some(t) => t.delegates map getKey }
def inheritProject(ref: ProjectRef) = project(ref).delegates
def resolve(ref: Reference) = Scope.resolveReference(builds.head.uri, rootProject, ref)
lazy val delegates: Scope => Seq[Scope] =
Scope.delegates(
@@ -113,10 +112,8 @@ object TestBuild
(_: Proj).configurations.map(toConfigKey),
resolve,
uri => buildMap(uri).root.id,
inheritProject,
inheritConfig,
inheritTask,
(ref, mp) => Nil
inheritTask
)
lazy val allFullScopes: Seq[Scope] =
for {
@@ -135,10 +132,9 @@ object TestBuild
val root = projects.head
val projectMap = mapBy(projects)(_.id)
}
final class Proj(val id: String, val delegates: Seq[ProjectRef], val configurations: Seq[Config])
final class Proj(val id: String, val configurations: Seq[Config])
{
override def toString = "Project " + id + "\n Delegates:\n " + delegates.mkString("\n ") +
"\n Configurations:\n " + configurations.mkString("\n ")
override def toString = "Project " + id + "\n Configurations:\n " + configurations.mkString("\n ")
val confMap = mapBy(configurations)(_.name)
}
@@ -196,7 +192,7 @@ object TestBuild
{
implicit val cGen = genConfigs(idGen, MaxDepsGen, MaxConfigsGen)
implicit val tGen = genTasks(idGen, MaxDepsGen, MaxTasksGen)
implicit val pGen = (uri: URI) => genProjects(uri)(idGen, MaxDepsGen, MaxProjectsGen, cGen)
implicit val pGen = (uri: URI) => genProjects(uri)(idGen, MaxProjectsGen, cGen)
envGen(buildGen(uriGen, pGen), tGen)
}
@@ -217,12 +213,19 @@ object TestBuild
def nGen[T](igen: Gen[Int])(implicit g: Gen[T]): Gen[List[T]] = igen flatMap { ig => listOfN(ig, g) }
implicit def genProjects(build: URI)(implicit genID: Gen[String], maxDeps: Gen[Int], count: Gen[Int], confs: Gen[Seq[Config]]): Gen[Seq[Proj]] =
genAcyclic(maxDeps, genID, count) { (id: String) =>
for(cs <- confs) yield { (deps: Seq[Proj]) =>
new Proj(id, deps.map{dep => ProjectRef(build, dep.id) }, cs)
}
}
implicit def genProjects(build: URI)(implicit genID: Gen[String], count: Gen[Int], confs: Gen[Seq[Config]]): Gen[Seq[Proj]] =
{
def projects(size: Int, ids: List[String]): Seq[Gen[Proj]] =
for(id <- ids) yield
for(cs <- confs) yield
new Proj(id, cs)
for {
size <- count
ids <- listOfN(size, genID)
projs <- sequence(projects(size, ids))
} yield projs
}
def genConfigs(implicit genName: Gen[String], maxDeps: Gen[Int], count: Gen[Int]): Gen[Seq[Config]] =
genAcyclicDirect[Config,String](maxDeps, genName, count)( (key, deps) => new Config(key, deps) )
def genTasks(implicit genName: Gen[String], maxDeps: Gen[Int], count: Gen[Int]): Gen[Seq[Taskk]] =