mirror of https://github.com/sbt/sbt.git
106 lines
3.8 KiB
Scala
106 lines
3.8 KiB
Scala
/* sbt -- Simple Build Tool
|
|
* Copyright 2010 Mark Harrah
|
|
*/
|
|
package sbt
|
|
|
|
import Types._
|
|
import scala.reflect.Manifest
|
|
|
|
// T must be invariant to work properly.
|
|
// Because it is sealed and the only instances go through AttributeKey.apply,
|
|
// a single AttributeKey instance cannot conform to AttributeKey[T] for different Ts
|
|
sealed trait AttributeKey[T] {
|
|
def manifest: Manifest[T]
|
|
def label: String
|
|
def description: Option[String]
|
|
def extend: Seq[AttributeKey[_]]
|
|
override final def toString = label
|
|
override final def hashCode = label.hashCode
|
|
override final def equals(o: Any) = (this eq o.asInstanceOf[AnyRef]) || (o match {
|
|
case a: AttributeKey[t] => a.label == this.label && a.manifest == this.manifest
|
|
case _ => false
|
|
})
|
|
}
|
|
object AttributeKey
|
|
{
|
|
def apply[T](name: String)(implicit mf: Manifest[T]): AttributeKey[T] = new AttributeKey[T] {
|
|
def manifest = mf
|
|
def label = name
|
|
def description = None
|
|
def extend = Nil
|
|
}
|
|
def apply[T](name: String, description0: String)(implicit mf: Manifest[T]): AttributeKey[T] = new AttributeKey[T] {
|
|
def manifest = mf
|
|
def label = name
|
|
def description = Some(description0)
|
|
def extend = Nil
|
|
}
|
|
def apply[T](name: String, description0: String, extend0: Seq[AttributeKey[_]])(implicit mf: Manifest[T]): AttributeKey[T] = new AttributeKey[T] {
|
|
def manifest = mf
|
|
def label = name
|
|
def description = Some(description0)
|
|
def extend = extend0
|
|
}
|
|
}
|
|
|
|
trait AttributeMap
|
|
{
|
|
def apply[T](k: AttributeKey[T]): T
|
|
def get[T](k: AttributeKey[T]): Option[T]
|
|
def remove[T](k: AttributeKey[T]): AttributeMap
|
|
def contains[T](k: AttributeKey[T]): Boolean
|
|
def put[T](k: AttributeKey[T], value: T): AttributeMap
|
|
def keys: Iterable[AttributeKey[_]]
|
|
def ++(o: Iterable[AttributeEntry[_]]): AttributeMap
|
|
def ++(o: AttributeMap): AttributeMap
|
|
def entries: Iterable[AttributeEntry[_]]
|
|
def isEmpty: Boolean
|
|
}
|
|
object AttributeMap
|
|
{
|
|
val empty: AttributeMap = new BasicAttributeMap(Map.empty)
|
|
def apply(entries: Iterable[AttributeEntry[_]]): AttributeMap = empty ++ entries
|
|
def apply(entries: AttributeEntry[_]*): AttributeMap = empty ++ entries
|
|
implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = new (AttributeKey ~> Id) {
|
|
def apply[T](key: AttributeKey[T]): T = map(key)
|
|
}
|
|
}
|
|
private class BasicAttributeMap(private val backing: Map[AttributeKey[_], Any]) extends AttributeMap
|
|
{
|
|
def isEmpty: Boolean = backing.isEmpty
|
|
def apply[T](k: AttributeKey[T]) = backing(k).asInstanceOf[T]
|
|
def get[T](k: AttributeKey[T]) = backing.get(k).asInstanceOf[Option[T]]
|
|
def remove[T](k: AttributeKey[T]): AttributeMap = new BasicAttributeMap( backing - k )
|
|
def contains[T](k: AttributeKey[T]) = backing.contains(k)
|
|
def put[T](k: AttributeKey[T], value: T): AttributeMap = new BasicAttributeMap( backing.updated(k, value) )
|
|
def keys: Iterable[AttributeKey[_]] = backing.keys
|
|
def ++(o: Iterable[AttributeEntry[_]]): AttributeMap =
|
|
{
|
|
val newBacking = (backing /: o) { case (b, AttributeEntry(key, value)) => b.updated(key, value) }
|
|
new BasicAttributeMap(newBacking)
|
|
}
|
|
def ++(o: AttributeMap): AttributeMap =
|
|
o match {
|
|
case bam: BasicAttributeMap => new BasicAttributeMap(backing ++ bam.backing)
|
|
case _ => o ++ this
|
|
}
|
|
def entries: Iterable[AttributeEntry[_]] =
|
|
for( (k: AttributeKey[kt], v) <- backing) yield AttributeEntry(k, v.asInstanceOf[kt])
|
|
override def toString = entries.mkString("(", ", ", ")")
|
|
}
|
|
|
|
// type inference required less generality
|
|
final case class AttributeEntry[T](key: AttributeKey[T], value: T)
|
|
{
|
|
override def toString = key.label + ": " + value
|
|
}
|
|
|
|
final case class Attributed[D](data: D)(val metadata: AttributeMap)
|
|
{
|
|
def put[T](key: AttributeKey[T], value: T): Attributed[D] = Attributed(data)(metadata.put(key, value))
|
|
}
|
|
object Attributed
|
|
{
|
|
implicit def blankSeq[T](in: Seq[T]): Seq[Attributed[T]] = in map blank
|
|
implicit def blank[T](data: T): Attributed[T] = Attributed(data)(AttributeMap.empty)
|
|
} |