summaryrefslogtreecommitdiff
path: root/core/src/main/scala/mill/util/OSet.scala
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-01-13 13:00:21 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-01-13 14:37:24 -0800
commit57501fca3b6c2c64d32744e6d534b9de3a6674f6 (patch)
tree912a22fb405c971f4a4b75d737a35e522d6a420e /core/src/main/scala/mill/util/OSet.scala
parent91102940a0bcdd7efc1d13e43510c4a0e406ead2 (diff)
downloadmill-57501fca3b6c2c64d32744e6d534b9de3a6674f6.tar.gz
mill-57501fca3b6c2c64d32744e6d534b9de3a6674f6.tar.bz2
mill-57501fca3b6c2c64d32744e6d534b9de3a6674f6.zip
Migrate most classpath-related code onto `Loose.OSet` abstraction, to enforce deduplication
Diffstat (limited to 'core/src/main/scala/mill/util/OSet.scala')
-rw-r--r--core/src/main/scala/mill/util/OSet.scala192
1 files changed, 99 insertions, 93 deletions
diff --git a/core/src/main/scala/mill/util/OSet.scala b/core/src/main/scala/mill/util/OSet.scala
index 52b47cde..a4fcc406 100644
--- a/core/src/main/scala/mill/util/OSet.scala
+++ b/core/src/main/scala/mill/util/OSet.scala
@@ -3,108 +3,114 @@ package mill.util
import scala.collection.mutable
-
-/**
- * A collection with enforced uniqueness, fast contains and deterministic
- * ordering. Raises an exception if a duplicate is found; call
- * `toSeq.distinct` if you explicitly want to make it swallow duplicates
- */
-trait OSet[V] extends TraversableOnce[V]{
- def contains(v: V): Boolean
- def items: Iterator[V]
- def indexed: IndexedSeq[V]
- def flatMap[T](f: V => TraversableOnce[T]): OSet[T]
- def map[T](f: V => T): OSet[T]
- def filter(f: V => Boolean): OSet[V]
- def withFilter(f: V => Boolean): OSet[V]
- def collect[T](f: PartialFunction[V, T]): OSet[T]
- def zipWithIndex: OSet[(V, Int)]
- def reverse: OSet[V]
- def zip[T](other: OSet[T]): OSet[(V, T)]
-}
-
-object OSet{
- implicit def jsonFormat[T: upickle.default.ReadWriter]: upickle.default.ReadWriter[OSet[T]] =
- upickle.default.ReadWriter[OSet[T]] (
- oset => upickle.default.writeJs(oset.toList),
- {case json => OSet.from(upickle.default.readJs[Seq[T]](json))}
- )
- def apply[V](items: V*) = from(items)
-
- def from[V](items: TraversableOnce[V]): OSet[V] = {
- val set = new OSet.Mutable[V]()
- items.foreach(set.append)
- set
+object Strict extends OSetWrapper(true)
+object Loose extends OSetWrapper(false)
+sealed class OSetWrapper(strictUniqueness: Boolean){
+ /**
+ * A collection with enforced uniqueness, fast contains and deterministic
+ * ordering. Raises an exception if a duplicate is found; call
+ * `toSeq.distinct` if you explicitly want to make it swallow duplicates
+ */
+ trait OSet[V] extends TraversableOnce[V]{
+ def contains(v: V): Boolean
+ def items: Iterator[V]
+ def indexed: IndexedSeq[V]
+ def flatMap[T](f: V => TraversableOnce[T]): OSet[T]
+ def map[T](f: V => T): OSet[T]
+ def filter(f: V => Boolean): OSet[V]
+ def withFilter(f: V => Boolean): OSet[V]
+ def collect[T](f: PartialFunction[V, T]): OSet[T]
+ def zipWithIndex: OSet[(V, Int)]
+ def reverse: OSet[V]
+ def zip[T](other: OSet[T]): OSet[(V, T)]
+ def ++[T >: V](other: TraversableOnce[T]): OSet[T]
}
+ object OSet{
+ def empty[V]: OSet[V] = new OSet.Mutable[V]
+ implicit def jsonFormat[T: upickle.default.ReadWriter]: upickle.default.ReadWriter[OSet[T]] =
+ upickle.default.ReadWriter[OSet[T]] (
+ oset => upickle.default.writeJs(oset.toList),
+ {case json => OSet.from(upickle.default.readJs[Seq[T]](json))}
+ )
+ def apply[V](items: V*) = from(items)
+
+ def from[V](items: TraversableOnce[V]): OSet[V] = {
+ val set = new OSet.Mutable[V]()
+ items.foreach(set.append)
+ set
+ }
- class Mutable[V]() extends OSet[V]{
- private[this] val set0 = mutable.LinkedHashSet.empty[V]
- def contains(v: V) = set0.contains(v)
- def append(v: V) = if (!contains(v)){
- set0.add(v)
+ class Mutable[V]() extends OSet[V]{
- }else {
- throw new Exception("Duplicated item inserted into OrderedSet: " + v)
- }
- def appendAll(vs: Seq[V]) = vs.foreach(append)
- def items = set0.iterator
- def indexed: IndexedSeq[V] = items.toIndexedSeq
- def set: collection.Set[V] = set0
-
- def map[T](f: V => T): OSet[T] = {
- val output = new OSet.Mutable[T]
- for(i <- items) output.append(f(i))
- output
- }
- def flatMap[T](f: V => TraversableOnce[T]): OSet[T] = {
- val output = new OSet.Mutable[T]
- for(i <- items) for(i0 <- f(i)) output.append(i0)
- output
- }
- def filter(f: V => Boolean): OSet[V] = {
- val output = new OSet.Mutable[V]
- for(i <- items) if (f(i)) output.append(i)
- output
- }
- def withFilter(f: V => Boolean): OSet[V] = filter(f)
+ private[this] val set0 = mutable.LinkedHashSet.empty[V]
+ def contains(v: V) = set0.contains(v)
+ def append(v: V) = if (!contains(v)){
+ set0.add(v)
- def collect[T](f: PartialFunction[V, T]) = this.filter(f.isDefinedAt).map(x => f(x))
+ }else if (strictUniqueness){
+ throw new Exception("Duplicated item inserted into OrderedSet: " + v)
+ }
+ def appendAll(vs: Seq[V]) = vs.foreach(append)
+ def items = set0.iterator
+ def indexed: IndexedSeq[V] = items.toIndexedSeq
+ def set: collection.Set[V] = set0
+
+ def map[T](f: V => T): OSet[T] = {
+ val output = new OSet.Mutable[T]
+ for(i <- items) output.append(f(i))
+ output
+ }
+ def flatMap[T](f: V => TraversableOnce[T]): OSet[T] = {
+ val output = new OSet.Mutable[T]
+ for(i <- items) for(i0 <- f(i)) output.append(i0)
+ output
+ }
+ def filter(f: V => Boolean): OSet[V] = {
+ val output = new OSet.Mutable[V]
+ for(i <- items) if (f(i)) output.append(i)
+ output
+ }
+ def withFilter(f: V => Boolean): OSet[V] = filter(f)
- def zipWithIndex = {
- var i = 0
- this.map{ x =>
- i += 1
- (x, i-1)
+ def collect[T](f: PartialFunction[V, T]) = this.filter(f.isDefinedAt).map(x => f(x))
+
+ def zipWithIndex = {
+ var i = 0
+ this.map{ x =>
+ i += 1
+ (x, i-1)
+ }
}
- }
- def reverse = OSet.from(indexed.reverseIterator)
-
- def zip[T](other: OSet[T]) = OSet.from(items.zip(other.items))
-
- // Members declared in scala.collection.GenTraversableOnce
- def isTraversableAgain: Boolean = items.isTraversableAgain
- def toIterator: Iterator[V] = items.toIterator
- def toStream: Stream[V] = items.toStream
-
- // Members declared in scala.collection.TraversableOnce
- def copyToArray[B >: V](xs: Array[B],start: Int,len: Int): Unit = items.copyToArray(xs, start, len)
- def exists(p: V => Boolean): Boolean = items.exists(p)
- def find(p: V => Boolean): Option[V] = items.find(p)
- def forall(p: V => Boolean): Boolean = items.forall(p)
- def foreach[U](f: V => U): Unit = items.foreach(f)
- def hasDefiniteSize: Boolean = items.hasDefiniteSize
- def isEmpty: Boolean = items.isEmpty
- def seq: scala.collection.TraversableOnce[V] = items
- def toTraversable: Traversable[V] = items.toTraversable
-
- override def hashCode() = items.hashCode()
- override def equals(other: Any) = other match{
- case s: OSet[_] => items.sameElements(s.items)
- case _ => super.equals(other)
+ def reverse = OSet.from(indexed.reverseIterator)
+
+ def zip[T](other: OSet[T]) = OSet.from(items.zip(other.items))
+ def ++[T >: V](other: TraversableOnce[T]) = OSet.from(items ++ other)
+
+ // Members declared in scala.collection.GenTraversableOnce
+ def isTraversableAgain: Boolean = items.isTraversableAgain
+ def toIterator: Iterator[V] = items.toIterator
+ def toStream: Stream[V] = items.toStream
+
+ // Members declared in scala.collection.TraversableOnce
+ def copyToArray[B >: V](xs: Array[B], start: Int,len: Int): Unit = items.copyToArray(xs, start, len)
+ def exists(p: V => Boolean): Boolean = items.exists(p)
+ def find(p: V => Boolean): Option[V] = items.find(p)
+ def forall(p: V => Boolean): Boolean = items.forall(p)
+ def foreach[U](f: V => U): Unit = items.foreach(f)
+ def hasDefiniteSize: Boolean = items.hasDefiniteSize
+ def isEmpty: Boolean = items.isEmpty
+ def seq: scala.collection.TraversableOnce[V] = items
+ def toTraversable: Traversable[V] = items.toTraversable
+
+ override def hashCode() = items.map(_.hashCode()).sum
+ override def equals(other: Any) = other match{
+ case s: OSet[_] => items.sameElements(s.items)
+ case _ => super.equals(other)
+ }
+ override def toString = items.mkString("OSet(", ", ", ")")
}
- override def toString = items.mkString("OSet(", ", ", ")")
}
}