sbt/main/KeyIndex.scala

70 lines
2.5 KiB
Scala

/* sbt -- Simple Build Tool
* Copyright 2011 Mark Harrah
*/
package sbt
import java.net.URI
import Project.ScopedKey
object KeyIndex
{
def empty: ExtendableKeyIndex = new KeyIndex0(Map.empty)
def apply(known: Seq[ScopedKey[_]]): ExtendableKeyIndex =
(empty /: known) { _ add _ }
def combine(indices: Seq[KeyIndex]): KeyIndex = new KeyIndex {
def buildURIs = concat(_.buildURIs)
def projects(uri: URI) = concat(_.projects(uri))
def configs(proj: ProjectRef) = concat(_.configs(proj))
def keys(proj: ProjectRef, conf: Option[String]) = concat(_.keys(proj, conf))
def concat[T](f: KeyIndex => Set[T]): Set[T] =
(Set.empty[T] /: indices)( (s,k) => s ++ f(k) )
}
}
trait KeyIndex
{
def buildURIs: Set[URI]
def projects(uri: URI): Set[String]
def configs(proj: ProjectRef): Set[String]
def keys(proj: ProjectRef, conf: Option[String]): Set[String]
}
trait ExtendableKeyIndex extends KeyIndex
{
def add(scoped: ScopedKey[_]): ExtendableKeyIndex
}
private final class KeyIndex0(val data: Map[URI, Map[String, Map[ Option[String], Set[String]] ]]) extends ExtendableKeyIndex
{
def buildURIs: Set[URI] = data.keys.toSet
def projects(uri: URI): Set[String] = get(data, uri).keys.toSet
def configs(project: ProjectRef): Set[String] = confMap(project).keys.flatten.toSet
def keys(project: ProjectRef, conf: Option[String]): Set[String] = get(confMap(project), conf)
def confMap(proj: ProjectRef): Map[Option[String], Set[String]] =
proj match
{
case ProjectRef(Some(uri), Some(id)) => get( get(data, uri), id)
case _ => Map.empty
}
private[this] def get[A,B,C](m: Map[A,Map[B,C]], key: A): Map[B,C] = getOr(m, key, Map.empty)
private[this] def get[A,B](m: Map[A,Set[B]], key: A): Set[B] = getOr(m, key, Set.empty)
private[this] def getOr[A,B](m: Map[A,B], key: A, or: B): B = m.getOrElse(key, or)
def add(scoped: ScopedKey[_]): ExtendableKeyIndex =
scoped.scope match
{
case Scope(Select(ProjectRef(Some(uri), Some(id))), config, _, _) => add(uri, id, config, scoped.key)
case _ => this
}
def add(uri: URI, id: String, config: ScopeAxis[ConfigKey], key: AttributeKey[_]): ExtendableKeyIndex =
add(uri, id, config match { case Select(c) => Some(c.name); case _ => None }, key)
def add(uri: URI, id: String, config: Option[String], key: AttributeKey[_]): ExtendableKeyIndex =
{
val projectMap = get(data, uri)
val configMap = get(projectMap, id)
val newSet = get(configMap, config) + key.label
val newProjectMap = projectMap.updated(id, configMap.updated(config, newSet))
new KeyIndex0( data.updated(uri, newProjectMap) )
}
}