diff --git a/main/Act.scala b/main/Act.scala index 938e5b593..dbe9fa62d 100644 --- a/main/Act.scala +++ b/main/Act.scala @@ -131,8 +131,9 @@ object Act def key(index: KeyIndex, proj: Option[ResolvedReference], conf: Option[String], task: Option[AttributeKey[_]], keyMap: Map[String,AttributeKey[_]]): Parser[AttributeKey[_]] = { + def dropHyphenated(keys: Set[String]): Set[String] = keys.filterNot(Util.hasHyphen) def keyParser(keys: Set[String]): Parser[AttributeKey[_]] = - token(ID !!! "Expected key" examples keys) flatMap { keyString=> + token(ID !!! "Expected key" examples dropHyphenated(keys)) flatMap { keyString=> getKey(keyMap, keyString, idFun) } keyParser(index.keys(proj, conf, task)) @@ -155,9 +156,11 @@ object Act def taskAxis(d: Option[String], tasks: Set[AttributeKey[_]], allKnown: Map[String, AttributeKey[_]]): Parser[ParsedAxis[AttributeKey[_]]] = { - val knownKeys: Map[String, AttributeKey[_]] = tasks.toSeq.map(key => (key.label, key)).toMap - val valid = allKnown ++ knownKeys - val suggested = knownKeys.keySet + val taskSeq = tasks.toSeq + def taskKeys(f: AttributeKey[_] => String): Seq[(String, AttributeKey[_])] = taskSeq.map(key => (f(key), key)) + val normKeys = taskKeys(_.label) + val valid = allKnown ++ normKeys ++ taskKeys(_.rawLabel) + val suggested = normKeys.map(_._1).toSet val keyP = filterStrings(examples(ID, suggested, "key"), valid.keySet, "key") map valid (token(value(keyP) | GlobalString ^^^ ParsedGlobal ) <~ token("::".id) ) ?? Omitted } diff --git a/main/EvaluateConfigurations.scala b/main/EvaluateConfigurations.scala index 87ba3570b..ecc4c1c2f 100644 --- a/main/EvaluateConfigurations.scala +++ b/main/EvaluateConfigurations.scala @@ -125,9 +125,12 @@ object Index settings.flatMap(s => if(s.key.key.isLocal) Nil else s.key +: s.dependencies).filter(!_.key.isLocal).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)(_.rawLabel) ++ stringToKeyMap0(settings)(_.label) + + private[this] def stringToKeyMap0(settings: Set[AttributeKey[_]])(label: AttributeKey[_] => String): Map[String, AttributeKey[_]] = { - val multiMap = settings.groupBy(_.label) + val multiMap = settings.groupBy(label) val duplicates = multiMap collect { case (k, xs) if xs.size > 1 => (k, xs.map(_.manifest)) } collect { case (k, xs) if xs.size > 1 => (k, xs) } if(duplicates.isEmpty) multiMap.collect { case (k, v) if validID(k) => (k, v.head) } toMap; diff --git a/main/KeyIndex.scala b/main/KeyIndex.scala index 5183476d9..1e3c41699 100644 --- a/main/KeyIndex.scala +++ b/main/KeyIndex.scala @@ -62,7 +62,7 @@ trait ExtendableKeyIndex extends KeyIndex // task axis <-> key private final class AKeyIndex(val data: Relation[ Option[AttributeKey[_]], String]) { - def add(task: Option[AttributeKey[_]], key: AttributeKey[_]): AKeyIndex = new AKeyIndex(data + (task, key.label)) + def add(task: Option[AttributeKey[_]], key: AttributeKey[_]): AKeyIndex = new AKeyIndex(data + (task, key.rawLabel) + (task, key.label)) def keys(task: Option[AttributeKey[_]]): Set[String] = data.forward(task) def allKeys: Set[String] = data._2s.toSet def tasks: Set[AttributeKey[_]] = data._1s.flatten.toSet diff --git a/main/Main.scala b/main/Main.scala index 84ae3d741..866398193 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -163,7 +163,7 @@ object BuiltinCommands val extracted = Project.extract(s) import extracted._ val index = structure.index - index.keyIndex.keys(Some(currentRef)).toSeq map index.keyMap + index.keyIndex.keys(Some(currentRef)).toSeq.map(index.keyMap).distinct } def sortByLabel(keys: Seq[AttributeKey[_]]): Seq[AttributeKey[_]] = keys.sortBy(_.label) diff --git a/main/SettingCompletions.scala b/main/SettingCompletions.scala index 53d96081f..42e47e2bd 100644 --- a/main/SettingCompletions.scala +++ b/main/SettingCompletions.scala @@ -285,7 +285,7 @@ private[sbt] object SettingCompletions /** Transforms the hypenated key label `k` into camel-case and quotes it with backticks if it is a Scala keyword. * This is intended to be an estimate of the Scala identifier that may be used to reference the keyword in the default sbt context. */ - def keyScalaID(k: String): String = Util.quoteIfKeyword(Util.hypenToCamel(k)) + def keyScalaID(k: String): String = Util.quoteIfKeyword(Util.hyphenToCamel(k)) /** Transforms the configuration name `c` so that the first letter is capitalized and the name is quoted with backticks if it is a Scala keyword. * This is intended to be an estimate of the Scala identifier that may be used to reference the keyword in the default sbt context. */ diff --git a/util/collection/Attributes.scala b/util/collection/Attributes.scala index 0376ca76c..227e2fdd7 100644 --- a/util/collection/Attributes.scala +++ b/util/collection/Attributes.scala @@ -11,6 +11,8 @@ import scala.reflect.Manifest // a single AttributeKey instance cannot conform to AttributeKey[T] for different Ts sealed trait AttributeKey[T] { def manifest: Manifest[T] + @deprecated("Should only be used for compatibility during the transition from hyphenated labels to camelCase labels.", "0.13.0") + def rawLabel: String def label: String def description: Option[String] def extend: Seq[AttributeKey[_]] @@ -48,13 +50,15 @@ object AttributeKey private[this] def make[T](name: String, description0: Option[String], extend0: Seq[AttributeKey[_]], rank0: Int)(implicit mf: Manifest[T]): AttributeKey[T] = new SharedAttributeKey[T] { def manifest = mf - def label = name + def rawLabel = name + val label = Util.hyphenToCamel(name) def description = description0 def extend = extend0 def rank = rank0 } private[sbt] def local[T](implicit mf: Manifest[T]): AttributeKey[T] = new AttributeKey[T] { def manifest = mf + def rawLabel = LocalLabel def label = LocalLabel def description = None def extend = Nil diff --git a/util/collection/Util.scala b/util/collection/Util.scala index 5aede5f0d..f4f6fbb50 100644 --- a/util/collection/Util.scala +++ b/util/collection/Util.scala @@ -26,8 +26,14 @@ object Util def pairID[A,B] = (a: A, b: B) => (a,b) private[this] lazy val Hypen = """-(\p{javaLowerCase})""".r - def hypenToCamel(s: String): String = - Hypen.replaceAllIn(s, _.group(1).toUpperCase) + def hasHyphen(s: String): Boolean = s.indexOf('-') >= 0 + @deprecated("Use the properly spelled version: hyphenToCamel", "0.13.0") + def hypenToCamel(s: String): String = hyphenToCamel(s) + def hyphenToCamel(s: String): String = + if(hasHyphen(s)) + Hypen.replaceAllIn(s, _.group(1).toUpperCase) + else + s private[this] lazy val Camel = """(\p{javaLowerCase})(\p{javaUpperCase})""".r def camelToHypen(s: String): String =