mirror of https://github.com/sbt/sbt.git
[2.x] fix: Use correct configuration identifier for display (#8698)
**Problem** The configuration name translation in logging was incorrect. When a configuration like MultiJvm (id="MultiJvm", name="multi-jvm") was displayed, it showed "Multi-jvm" instead of "MultiJvm" because the display logic was guessing the identifier by capitalizing the ivy config name. **Solution** This fix: - Adds configNameToIdent reverse mapping in ConfigIndex to look up the correct Configuration.id from the ivy config name - Adds toConfigIdent method in KeyIndex trait for display lookup - Updates Scope.display to accept a config name lookup function - Updates showLoadingKey and showContextKey to use the index lookup Fixes #5211 Generated-by: Claude
This commit is contained in:
parent
47e7133260
commit
4e0180d759
|
|
@ -733,6 +733,7 @@ lazy val mainProj = (project in file("main"))
|
||||||
exclude[DirectMissingMethodProblem]("sbt.coursierint.LMCoursier.coursierConfiguration"),
|
exclude[DirectMissingMethodProblem]("sbt.coursierint.LMCoursier.coursierConfiguration"),
|
||||||
exclude[IncompatibleMethTypeProblem]("sbt.internal.Compiler.scalaInstanceTask"),
|
exclude[IncompatibleMethTypeProblem]("sbt.internal.Compiler.scalaInstanceTask"),
|
||||||
exclude[ReversedMissingMethodProblem]("sbt.ScriptedRun.invoke"),
|
exclude[ReversedMissingMethodProblem]("sbt.ScriptedRun.invoke"),
|
||||||
|
exclude[ReversedMissingMethodProblem]("sbt.internal.KeyIndex.toConfigIdent"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.dependsOn(lmCore, lmIvy, lmCoursierShadedPublishing)
|
.dependsOn(lmCore, lmIvy, lmCoursierShadedPublishing)
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,12 @@ object Def extends BuildSyntax with Init with InitializeImplicits:
|
||||||
|
|
||||||
private[sbt] def showShortKey(
|
private[sbt] def showShortKey(
|
||||||
keyNameColor: Option[String],
|
keyNameColor: Option[String],
|
||||||
|
): Show[ScopedKey[?]] =
|
||||||
|
showShortKey(keyNameColor, Scope.guessConfigIdent)
|
||||||
|
|
||||||
|
private[sbt] def showShortKey(
|
||||||
|
keyNameColor: Option[String],
|
||||||
|
configNameToIdent: String => String,
|
||||||
): Show[ScopedKey[?]] = {
|
): Show[ScopedKey[?]] = {
|
||||||
def displayShort(
|
def displayShort(
|
||||||
project: Reference
|
project: Reference
|
||||||
|
|
@ -117,7 +123,8 @@ object Def extends BuildSyntax with Init with InitializeImplicits:
|
||||||
Scope.display(
|
Scope.display(
|
||||||
key.scope,
|
key.scope,
|
||||||
withColor(key.key.label, keyNameColor),
|
withColor(key.key.label, keyNameColor),
|
||||||
ref => displayShort(ref)
|
ref => displayShort(ref),
|
||||||
|
configNameToIdent
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,9 @@ object Scope:
|
||||||
|
|
||||||
def display(config: ConfigKey): String = guessConfigIdent(config.name) + " /"
|
def display(config: ConfigKey): String = guessConfigIdent(config.name) + " /"
|
||||||
|
|
||||||
|
def display(config: ConfigKey, configNameToIdent: String => String): String =
|
||||||
|
configNameToIdent(config.name) + " /"
|
||||||
|
|
||||||
private[sbt] val configIdents: Map[String, String] =
|
private[sbt] val configIdents: Map[String, String] =
|
||||||
Map(
|
Map(
|
||||||
"scala-tool" -> "ScalaTool",
|
"scala-tool" -> "ScalaTool",
|
||||||
|
|
@ -191,6 +194,14 @@ object Scope:
|
||||||
def display(scope: Scope, sep: String, showProject: Reference => String): String =
|
def display(scope: Scope, sep: String, showProject: Reference => String): String =
|
||||||
displayMasked(scope, sep, showProject, ScopeMask())
|
displayMasked(scope, sep, showProject, ScopeMask())
|
||||||
|
|
||||||
|
def display(
|
||||||
|
scope: Scope,
|
||||||
|
sep: String,
|
||||||
|
showProject: Reference => String,
|
||||||
|
configNameToIdent: String => String
|
||||||
|
): String =
|
||||||
|
displayMasked(scope, sep, showProject, ScopeMask(), showZeroConfig = false, configNameToIdent)
|
||||||
|
|
||||||
private[sbt] def displayPedantic(scope: Scope, sep: String): String =
|
private[sbt] def displayPedantic(scope: Scope, sep: String): String =
|
||||||
displayMasked(scope, sep, showProject, ScopeMask(), true)
|
displayMasked(scope, sep, showProject, ScopeMask(), true)
|
||||||
|
|
||||||
|
|
@ -237,25 +248,35 @@ object Scope:
|
||||||
showProject: Reference => String,
|
showProject: Reference => String,
|
||||||
mask: ScopeMask,
|
mask: ScopeMask,
|
||||||
showZeroConfig: Boolean
|
showZeroConfig: Boolean
|
||||||
): String = {
|
): String =
|
||||||
|
displayMasked(scope, sep, showProject, mask, showZeroConfig, guessConfigIdent)
|
||||||
|
|
||||||
|
def displayMasked(
|
||||||
|
scope: Scope,
|
||||||
|
sep: String,
|
||||||
|
showProject: Reference => String,
|
||||||
|
mask: ScopeMask,
|
||||||
|
showZeroConfig: Boolean,
|
||||||
|
configNameToIdent: String => String
|
||||||
|
): String =
|
||||||
import scope.{ project, config, task, extra }
|
import scope.{ project, config, task, extra }
|
||||||
extra.toOption.flatMap(_.get(customShowString)).getOrElse {
|
extra.toOption
|
||||||
val zeroConfig = if (showZeroConfig) "Zero /" else ""
|
.flatMap(_.get(customShowString))
|
||||||
val configPrefix = config.foldStrict(display, zeroConfig, "./")
|
.getOrElse:
|
||||||
val taskPrefix = task.foldStrict(_.label + " /", "", "./")
|
val zeroConfig = if showZeroConfig then "Zero /" else ""
|
||||||
val extras = extra.foldStrict(_.entries.map(_.toString).toList, nil, nil)
|
val configPrefix = config.foldStrict(c => display(c, configNameToIdent), zeroConfig, "./")
|
||||||
val postfix = if (extras.isEmpty) "" else extras.mkString("(", ", ", ")")
|
val taskPrefix = task.foldStrict(_.label + " /", "", "./")
|
||||||
if (scope == GlobalScope) "Global / " + sep + postfix
|
val extras = extra.foldStrict(_.entries.map(_.toString).toList, nil, nil)
|
||||||
else
|
val postfix = if extras.isEmpty then "" else extras.mkString("(", ", ", ")")
|
||||||
mask.concatShow(
|
if scope == GlobalScope then "Global / " + sep + postfix
|
||||||
appendSpace(projectPrefix(project, showProject)),
|
else
|
||||||
appendSpace(configPrefix),
|
mask.concatShow(
|
||||||
appendSpace(taskPrefix),
|
appendSpace(projectPrefix(project, showProject)),
|
||||||
sep,
|
appendSpace(configPrefix),
|
||||||
postfix
|
appendSpace(taskPrefix),
|
||||||
)
|
sep,
|
||||||
}
|
postfix
|
||||||
}
|
)
|
||||||
|
|
||||||
private[sbt] def appendSpace(s: String): String =
|
private[sbt] def appendSpace(s: String): String =
|
||||||
if (s == "") ""
|
if (s == "") ""
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
package sbt
|
package sbt
|
||||||
|
|
||||||
import sbt.BasicCommandStrings.{ StashOnFailure, networkExecPrefix }
|
import sbt.BasicCommandStrings.{ StashOnFailure, networkExecPrefix }
|
||||||
import sbt.ProjectExtra.extract
|
import sbt.ProjectExtra.*
|
||||||
import sbt.internal.{ ConsoleChannel, FastTrackCommands, ShutdownHooks, SysProp, TaskProgress }
|
import sbt.internal.{ ConsoleChannel, FastTrackCommands, ShutdownHooks, SysProp, TaskProgress }
|
||||||
import sbt.internal.langserver.ErrorCodes
|
import sbt.internal.langserver.ErrorCodes
|
||||||
import sbt.internal.nio.CheckBuildSources.CheckBuildSourcesKey
|
import sbt.internal.nio.CheckBuildSources.CheckBuildSourcesKey
|
||||||
|
|
@ -156,7 +156,13 @@ private[sbt] object MainLoop:
|
||||||
state.get(Keys.superShellSleep.key).getOrElse(SysProp.supershellSleep.millis)
|
state.get(Keys.superShellSleep.key).getOrElse(SysProp.supershellSleep.millis)
|
||||||
val superShellThreshold =
|
val superShellThreshold =
|
||||||
state.get(Keys.superShellThreshold.key).getOrElse(SysProp.supershellThreshold)
|
state.get(Keys.superShellThreshold.key).getOrElse(SysProp.supershellThreshold)
|
||||||
val taskProgress = new TaskProgress(superShellSleep, superShellThreshold, state.log)
|
val taskProgress =
|
||||||
|
new TaskProgress(
|
||||||
|
superShellSleep,
|
||||||
|
superShellThreshold,
|
||||||
|
state.log,
|
||||||
|
Project.configNameToIdent(state)
|
||||||
|
)
|
||||||
val gcMonitor = if (SysProp.gcMonitor) Some(new sbt.internal.GCMonitor(state.log)) else None
|
val gcMonitor = if (SysProp.gcMonitor) Some(new sbt.internal.GCMonitor(state.log)) else None
|
||||||
try {
|
try {
|
||||||
ErrorHandling.wideConvert {
|
ErrorHandling.wideConvert {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import Def.{ Flattened, Initialize, ScopedKey, Setting }
|
||||||
import sbt.internal.{
|
import sbt.internal.{
|
||||||
Load,
|
Load,
|
||||||
BuildStructure,
|
BuildStructure,
|
||||||
|
KeyIndex,
|
||||||
LoadedBuild,
|
LoadedBuild,
|
||||||
LoadedBuildUnit,
|
LoadedBuildUnit,
|
||||||
SettingGraph,
|
SettingGraph,
|
||||||
|
|
@ -199,31 +200,69 @@ trait ProjectExtra extends Scoped.Syntax:
|
||||||
showContextKey(state, None)
|
showContextKey(state, None)
|
||||||
|
|
||||||
def showContextKey(state: State, keyNameColor: Option[String]): Show[ScopedKey[?]] =
|
def showContextKey(state: State, keyNameColor: Option[String]): Show[ScopedKey[?]] =
|
||||||
if (isProjectLoaded(state)) showContextKey2(session(state), keyNameColor)
|
if isProjectLoaded(state) then
|
||||||
|
val se = session(state)
|
||||||
|
val st = structure(state)
|
||||||
|
showContextKey2(se, st.index.keyIndex, keyNameColor)
|
||||||
else Def.showFullKey
|
else Def.showFullKey
|
||||||
|
|
||||||
// @deprecated("Use showContextKey2 which doesn't take the unused structure param", "1.1.1")
|
|
||||||
// def showContextKey(
|
|
||||||
// session: SessionSettings,
|
|
||||||
// structure: BuildStructure,
|
|
||||||
// keyNameColor: Option[String] = None
|
|
||||||
// ): Show[ScopedKey[_]] =
|
|
||||||
// showContextKey2(session, keyNameColor)
|
|
||||||
|
|
||||||
def showContextKey2(
|
def showContextKey2(
|
||||||
session: SessionSettings,
|
session: SessionSettings,
|
||||||
keyNameColor: Option[String] = None
|
keyNameColor: Option[String] = None
|
||||||
): Show[ScopedKey[?]] =
|
): Show[ScopedKey[?]] =
|
||||||
Def.showRelativeKey2(session.current, keyNameColor)
|
Def.showRelativeKey2(session.current, keyNameColor)
|
||||||
|
|
||||||
|
def showContextKey2(
|
||||||
|
session: SessionSettings,
|
||||||
|
keyIndex: KeyIndex,
|
||||||
|
keyNameColor: Option[String]
|
||||||
|
): Show[ScopedKey[?]] =
|
||||||
|
val current = session.current
|
||||||
|
val configNameToIdent: String => String = name => keyIndex.toConfigIdent(Some(current))(name)
|
||||||
|
Show[ScopedKey[?]]: key =>
|
||||||
|
val color: String => String = Def.withColor(_, keyNameColor)
|
||||||
|
key.scope.extra.toOption
|
||||||
|
.flatMap(_.get(Scope.customShowString).map(color))
|
||||||
|
.getOrElse:
|
||||||
|
Scope.display(
|
||||||
|
key.scope,
|
||||||
|
color(key.key.label),
|
||||||
|
ref => Def.displayRelative2(current, ref),
|
||||||
|
configNameToIdent
|
||||||
|
)
|
||||||
|
|
||||||
def showLoadingKey(
|
def showLoadingKey(
|
||||||
loaded: LoadedBuild,
|
loaded: LoadedBuild,
|
||||||
keyNameColor: Option[String] = None
|
keyNameColor: Option[String] = None
|
||||||
): Show[ScopedKey[?]] =
|
): Show[ScopedKey[?]] =
|
||||||
Def.showRelativeKey2(
|
val configNameToIdent = buildConfigNameToIdent(loaded)
|
||||||
ProjectRef(loaded.root, loaded.units(loaded.root).rootProjects.head),
|
val current = ProjectRef(loaded.root, loaded.units(loaded.root).rootProjects.head)
|
||||||
keyNameColor
|
Show[ScopedKey[?]]: key =>
|
||||||
)
|
val color: String => String = Def.withColor(_, keyNameColor)
|
||||||
|
key.scope.extra.toOption
|
||||||
|
.flatMap(_.get(Scope.customShowString).map(color))
|
||||||
|
.getOrElse:
|
||||||
|
Scope.display(
|
||||||
|
key.scope,
|
||||||
|
color(key.key.label),
|
||||||
|
ref => Def.displayRelative2(current, ref),
|
||||||
|
configNameToIdent
|
||||||
|
)
|
||||||
|
|
||||||
|
private[sbt] def configNameToIdent(state: State): String => String =
|
||||||
|
if isProjectLoaded(state) then buildConfigNameToIdent(structure(state).units)
|
||||||
|
else Scope.guessConfigIdent
|
||||||
|
|
||||||
|
private def buildConfigNameToIdent(loaded: LoadedBuild): String => String =
|
||||||
|
buildConfigNameToIdent(loaded.units)
|
||||||
|
|
||||||
|
private def buildConfigNameToIdent(units: Map[URI, LoadedBuildUnit]): String => String =
|
||||||
|
val configMap = (for
|
||||||
|
(_, unit) <- units.iterator
|
||||||
|
(_, project) <- unit.defined.iterator
|
||||||
|
config <- project.configurations.iterator
|
||||||
|
yield config.name -> config.id).toMap
|
||||||
|
name => configMap.getOrElse(name, Scope.guessConfigIdent(name))
|
||||||
|
|
||||||
def getOrError[T](state: State, key: AttributeKey[T], msg: String): T =
|
def getOrError[T](state: State, key: AttributeKey[T], msg: String): T =
|
||||||
state.get(key).getOrElse(sys.error(msg))
|
state.get(key).getOrElse(sys.error(msg))
|
||||||
|
|
@ -253,11 +292,11 @@ trait ProjectExtra extends Scoped.Syntax:
|
||||||
val se = Project.session(state)
|
val se = Project.session(state)
|
||||||
val st = Project.structure(state)
|
val st = Project.structure(state)
|
||||||
val currentRef = internal.ProjectNavigation.effectiveCurrentRef(state)
|
val currentRef = internal.ProjectNavigation.effectiveCurrentRef(state)
|
||||||
Extracted(st, se, currentRef)(using Project.showContextKey2(se))
|
Extracted(st, se, currentRef)(using Project.showContextKey2(se, st.index.keyIndex, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def extract(se: SessionSettings, st: BuildStructure): Extracted =
|
private[sbt] def extract(se: SessionSettings, st: BuildStructure): Extracted =
|
||||||
Extracted(st, se, se.current)(using Project.showContextKey2(se))
|
Extracted(st, se, se.current)(using Project.showContextKey2(se, st.index.keyIndex, None))
|
||||||
|
|
||||||
def getProjectForReference(ref: Reference, structure: BuildStructure): Option[ResolvedProject] =
|
def getProjectForReference(ref: Reference, structure: BuildStructure): Option[ResolvedProject] =
|
||||||
ref match
|
ref match
|
||||||
|
|
@ -401,7 +440,7 @@ trait ProjectExtra extends Scoped.Syntax:
|
||||||
case None => ""
|
case None => ""
|
||||||
|
|
||||||
val (definingKey, providedBy) = structure.data.definingKey(key) match
|
val (definingKey, providedBy) = structure.data.definingKey(key) match
|
||||||
case Some(k) => k -> s"Provided by:\n\t${Scope.display(k.scope, key.key.label)}\n"
|
case Some(k) => k -> s"Provided by:\n\t${display.show(ScopedKey(k.scope, key.key))}\n"
|
||||||
case None => key -> ""
|
case None => key -> ""
|
||||||
val comp =
|
val comp =
|
||||||
Def.compiled(structure.settings, actual)(using
|
Def.compiled(structure.settings, actual)(using
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,12 @@ import scala.collection.mutable
|
||||||
import scala.collection.immutable.VectorBuilder
|
import scala.collection.immutable.VectorBuilder
|
||||||
import scala.concurrent.duration.*
|
import scala.concurrent.duration.*
|
||||||
|
|
||||||
private[sbt] abstract class AbstractTaskExecuteProgress extends ExecuteProgress {
|
private[sbt] abstract class AbstractTaskExecuteProgress(
|
||||||
|
configNameToIdent: String => String = Scope.guessConfigIdent
|
||||||
|
) extends ExecuteProgress {
|
||||||
import AbstractTaskExecuteProgress.Timer
|
import AbstractTaskExecuteProgress.Timer
|
||||||
|
|
||||||
private val showScopedKey = Def.showShortKey(None)
|
private val showScopedKey = Def.showShortKey(None, configNameToIdent)
|
||||||
private val anonOwners = new ConcurrentHashMap[TaskId[?], TaskId[?]]
|
private val anonOwners = new ConcurrentHashMap[TaskId[?], TaskId[?]]
|
||||||
private val calledBy = new ConcurrentHashMap[TaskId[?], TaskId[?]]
|
private val calledBy = new ConcurrentHashMap[TaskId[?], TaskId[?]]
|
||||||
private val timings = new ConcurrentHashMap[TaskId[?], Timer]
|
private val timings = new ConcurrentHashMap[TaskId[?], Timer]
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,13 @@ object KeyIndex {
|
||||||
val data = ids map { id =>
|
val data = ids map { id =>
|
||||||
val configs = configurations.getOrElse(id, Seq())
|
val configs = configurations.getOrElse(id, Seq())
|
||||||
val configIdentToName = configs.map(config => config.id -> config.name).toMap
|
val configIdentToName = configs.map(config => config.id -> config.name).toMap
|
||||||
Option(id) -> new ConfigIndex(Map.empty, configIdentToName, emptyAKeyIndex)
|
val configNameToIdent = configs.map(config => config.name -> config.id).toMap
|
||||||
|
Option(id) -> new ConfigIndex(
|
||||||
|
Map.empty,
|
||||||
|
configIdentToName,
|
||||||
|
configNameToIdent,
|
||||||
|
emptyAKeyIndex
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Option(uri) -> new ProjectIndex(data.toMap)
|
Option(uri) -> new ProjectIndex(data.toMap)
|
||||||
}
|
}
|
||||||
|
|
@ -66,6 +72,11 @@ object KeyIndex {
|
||||||
case Some(idx) => idx.fromConfigIdent(proj)(configIdent)
|
case Some(idx) => idx.fromConfigIdent(proj)(configIdent)
|
||||||
case _ => Scope.unguessConfigIdent(configIdent)
|
case _ => Scope.unguessConfigIdent(configIdent)
|
||||||
}
|
}
|
||||||
|
private[sbt] def toConfigIdent(proj: Option[ResolvedReference])(configName: String): String =
|
||||||
|
indices.find(idx => idx.exists(proj)) match {
|
||||||
|
case Some(idx) => idx.toConfigIdent(proj)(configName)
|
||||||
|
case _ => Scope.guessConfigIdent(configName)
|
||||||
|
}
|
||||||
def tasks(proj: Option[ResolvedReference], conf: Option[String]) = concat(_.tasks(proj, conf))
|
def tasks(proj: Option[ResolvedReference], conf: Option[String]) = concat(_.tasks(proj, conf))
|
||||||
def tasks(proj: Option[ResolvedReference], conf: Option[String], key: String) =
|
def tasks(proj: Option[ResolvedReference], conf: Option[String], key: String) =
|
||||||
concat(_.tasks(proj, conf, key))
|
concat(_.tasks(proj, conf, key))
|
||||||
|
|
@ -79,7 +90,8 @@ object KeyIndex {
|
||||||
private[sbt] def getOr[A, B](m: Map[A, B], key: A, or: B): B = m.getOrElse(key, or)
|
private[sbt] def getOr[A, B](m: Map[A, B], key: A, or: B): B = m.getOrElse(key, or)
|
||||||
private[sbt] def keySet[A, B](m: Map[Option[A], B]): Set[A] = m.keys.flatten.toSet
|
private[sbt] def keySet[A, B](m: Map[Option[A], B]): Set[A] = m.keys.flatten.toSet
|
||||||
private[sbt] val emptyAKeyIndex = new AKeyIndex(Relation.empty)
|
private[sbt] val emptyAKeyIndex = new AKeyIndex(Relation.empty)
|
||||||
private[sbt] val emptyConfigIndex = new ConfigIndex(Map.empty, Map.empty, emptyAKeyIndex)
|
private[sbt] val emptyConfigIndex =
|
||||||
|
new ConfigIndex(Map.empty, Map.empty, Map.empty, emptyAKeyIndex)
|
||||||
private[sbt] val emptyProjectIndex = new ProjectIndex(Map.empty)
|
private[sbt] val emptyProjectIndex = new ProjectIndex(Map.empty)
|
||||||
private[sbt] val emptyBuildIndex = new BuildIndex(Map.empty)
|
private[sbt] val emptyBuildIndex = new BuildIndex(Map.empty)
|
||||||
|
|
||||||
|
|
@ -115,6 +127,7 @@ trait KeyIndex {
|
||||||
): Set[String]
|
): Set[String]
|
||||||
private[sbt] def configIdents(project: Option[ResolvedReference]): Set[String]
|
private[sbt] def configIdents(project: Option[ResolvedReference]): Set[String]
|
||||||
private[sbt] def fromConfigIdent(proj: Option[ResolvedReference])(configIdent: String): String
|
private[sbt] def fromConfigIdent(proj: Option[ResolvedReference])(configIdent: String): String
|
||||||
|
private[sbt] def toConfigIdent(proj: Option[ResolvedReference])(configName: String): String
|
||||||
}
|
}
|
||||||
trait ExtendableKeyIndex extends KeyIndex {
|
trait ExtendableKeyIndex extends KeyIndex {
|
||||||
def add(scoped: ScopedKey[?]): ExtendableKeyIndex
|
def add(scoped: ScopedKey[?]): ExtendableKeyIndex
|
||||||
|
|
@ -135,11 +148,13 @@ private[sbt] case class IdentifiableConfig(name: String, ident: Option[String])
|
||||||
/*
|
/*
|
||||||
* data contains the mapping between a configuration name and its keys.
|
* data contains the mapping between a configuration name and its keys.
|
||||||
* configIdentToName contains the mapping between a configuration ident and its name
|
* configIdentToName contains the mapping between a configuration ident and its name
|
||||||
|
* configNameToIdent contains the reverse mapping from name to ident for display purposes
|
||||||
* noConfigKeys contains the keys without a configuration.
|
* noConfigKeys contains the keys without a configuration.
|
||||||
*/
|
*/
|
||||||
private[sbt] final class ConfigIndex(
|
private[sbt] final class ConfigIndex(
|
||||||
val data: Map[String, AKeyIndex],
|
val data: Map[String, AKeyIndex],
|
||||||
val configIdentToName: Map[String, String],
|
val configIdentToName: Map[String, String],
|
||||||
|
val configNameToIdent: Map[String, String],
|
||||||
val noConfigKeys: AKeyIndex
|
val noConfigKeys: AKeyIndex
|
||||||
) {
|
) {
|
||||||
def add(
|
def add(
|
||||||
|
|
@ -157,18 +172,22 @@ private[sbt] final class ConfigIndex(
|
||||||
config: IdentifiableConfig,
|
config: IdentifiableConfig,
|
||||||
task: Option[AttributeKey[?]],
|
task: Option[AttributeKey[?]],
|
||||||
key: AttributeKey[?]
|
key: AttributeKey[?]
|
||||||
): ConfigIndex = {
|
): ConfigIndex =
|
||||||
val keyIndex = data.getOrElse(config.name, emptyAKeyIndex)
|
val keyIndex = data.getOrElse(config.name, emptyAKeyIndex)
|
||||||
val configIdent = config.ident.getOrElse(Scope.guessConfigIdent(config.name))
|
val configIdent = config.ident.getOrElse(Scope.guessConfigIdent(config.name))
|
||||||
|
// Only add to configNameToIdent if not already present to preserve correct mappings from base()
|
||||||
|
val updatedNameToIdent =
|
||||||
|
if configNameToIdent.contains(config.name) then configNameToIdent
|
||||||
|
else configNameToIdent.updated(config.name, configIdent)
|
||||||
new ConfigIndex(
|
new ConfigIndex(
|
||||||
data.updated(config.name, keyIndex.add(task, key)),
|
data.updated(config.name, keyIndex.add(task, key)),
|
||||||
configIdentToName.updated(configIdent, config.name),
|
configIdentToName.updated(configIdent, config.name),
|
||||||
|
updatedNameToIdent,
|
||||||
noConfigKeys
|
noConfigKeys
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
def addKeyWithoutConfig(task: Option[AttributeKey[?]], key: AttributeKey[?]): ConfigIndex = {
|
def addKeyWithoutConfig(task: Option[AttributeKey[?]], key: AttributeKey[?]): ConfigIndex = {
|
||||||
new ConfigIndex(data, configIdentToName, noConfigKeys.add(task, key))
|
new ConfigIndex(data, configIdentToName, configNameToIdent, noConfigKeys.add(task, key))
|
||||||
}
|
}
|
||||||
|
|
||||||
def keyIndex(conf: Option[String]): AKeyIndex = conf match {
|
def keyIndex(conf: Option[String]): AKeyIndex = conf match {
|
||||||
|
|
@ -179,8 +198,13 @@ private[sbt] final class ConfigIndex(
|
||||||
def configs: Set[String] = data.keySet
|
def configs: Set[String] = data.keySet
|
||||||
private[sbt] lazy val idents: Set[String] = configIdentToName.keySet
|
private[sbt] lazy val idents: Set[String] = configIdentToName.keySet
|
||||||
|
|
||||||
// guess Configuration name from an identifier.
|
// Looks up the display identifier for a configuration name.
|
||||||
// There's a guessing involved because we could have scoped key that Project is not aware of.
|
// Falls back to guessing if the name is not in the index.
|
||||||
|
private[sbt] def toConfigIdent(name: String): String =
|
||||||
|
configNameToIdent.getOrElse(name, Scope.guessConfigIdent(name))
|
||||||
|
|
||||||
|
// Looks up the configuration name from an identifier.
|
||||||
|
// Falls back to guessing if the identifier is not in the index.
|
||||||
private[sbt] def fromConfigIdent(ident: String): String =
|
private[sbt] def fromConfigIdent(ident: String): String =
|
||||||
configIdentToName.getOrElse(ident, Scope.unguessConfigIdent(ident))
|
configIdentToName.getOrElse(ident, Scope.unguessConfigIdent(ident))
|
||||||
}
|
}
|
||||||
|
|
@ -224,6 +248,9 @@ private[sbt] final class KeyIndex0(val data: BuildIndex) extends ExtendableKeyIn
|
||||||
private[sbt] def fromConfigIdent(proj: Option[ResolvedReference])(configIdent: String): String =
|
private[sbt] def fromConfigIdent(proj: Option[ResolvedReference])(configIdent: String): String =
|
||||||
confIndex(proj).fromConfigIdent(configIdent)
|
confIndex(proj).fromConfigIdent(configIdent)
|
||||||
|
|
||||||
|
private[sbt] def toConfigIdent(proj: Option[ResolvedReference])(configName: String): String =
|
||||||
|
confIndex(proj).toConfigIdent(configName)
|
||||||
|
|
||||||
def tasks(proj: Option[ResolvedReference], conf: Option[String]): Set[AttributeKey[?]] =
|
def tasks(proj: Option[ResolvedReference], conf: Option[String]): Set[AttributeKey[?]] =
|
||||||
keyIndex(proj, conf).tasks
|
keyIndex(proj, conf).tasks
|
||||||
def tasks(
|
def tasks(
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,9 @@ import sbt.util.Logger
|
||||||
private[sbt] class TaskProgress(
|
private[sbt] class TaskProgress(
|
||||||
sleepDuration: FiniteDuration,
|
sleepDuration: FiniteDuration,
|
||||||
threshold: FiniteDuration,
|
threshold: FiniteDuration,
|
||||||
logger: Logger
|
logger: Logger,
|
||||||
) extends AbstractTaskExecuteProgress
|
configNameToIdent: String => String = Scope.guessConfigIdent
|
||||||
|
) extends AbstractTaskExecuteProgress(configNameToIdent)
|
||||||
with ExecuteProgress
|
with ExecuteProgress
|
||||||
with AutoCloseable {
|
with AutoCloseable {
|
||||||
private val lastTaskCount = new AtomicInteger(0)
|
private val lastTaskCount = new AtomicInteger(0)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
// intentionally empty - CheckPlugin provides settings
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package sbt
|
||||||
|
|
||||||
|
import sbt.*
|
||||||
|
import Keys.*
|
||||||
|
|
||||||
|
object CheckPlugin extends AutoPlugin:
|
||||||
|
override def requires = plugins.JvmPlugin
|
||||||
|
override def trigger = allRequirements
|
||||||
|
|
||||||
|
lazy val MultiJvm = config("multi-jvm")
|
||||||
|
lazy val test1 = taskKey[Unit]("")
|
||||||
|
|
||||||
|
override def projectConfigurations = Seq(MultiJvm)
|
||||||
|
override def projectSettings = Seq(
|
||||||
|
MultiJvm / test1 := {},
|
||||||
|
commands += Command.command("checkShortKeyDisplay") { state =>
|
||||||
|
val configNameToIdent = Project.configNameToIdent(state)
|
||||||
|
val show = Def.showShortKey(None, configNameToIdent)
|
||||||
|
val displayed = show.show((MultiJvm / test1).scopedKey)
|
||||||
|
if !displayed.contains("MultiJvm") then
|
||||||
|
sys.error(s"Expected 'MultiJvm' in short key display but got: '$displayed'")
|
||||||
|
state.log.info(s"Config display check passed: $displayed")
|
||||||
|
state
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Verify that custom configuration MultiJvm displays correctly
|
||||||
|
# instead of the guessed Multi-jvm (#5211)
|
||||||
|
> checkShortKeyDisplay
|
||||||
Loading…
Reference in New Issue