Skip to content

Commit

Permalink
Enable warnings in build.sc, overhaul Agg to avoid triggering spuri…
Browse files Browse the repository at this point in the history
…ous deprecation warnings (#2519)

Seems like all the `IterableOnce` method implementations were deprecated
at some point, and you need to pull in `IterableOps` to have
non-deprecated versions

If we want to start making use of `@deprecated` in 0.11.0, we need to
make sure people see the warnings, and that they're not drowned in a sea
of noise

Pull request: #2519
  • Loading branch information
lihaoyi authored May 15, 2023
1 parent 65fbd53 commit 0579050
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 38 deletions.
112 changes: 75 additions & 37 deletions main/api/src/mill/api/AggWrapper.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package mill.api

import scala.annotation.nowarn
import scala.collection.mutable
import scala.collection.{IterableFactory, IterableOps, mutable}
import scala.language.implicitConversions

object Strict extends AggWrapper(true)
Expand All @@ -14,26 +13,37 @@ private[mill] sealed class AggWrapper(strictUniqueness: Boolean) {
* ordering. Raises an exception if a duplicate is found; call
* `toSeq.distinct` if you explicitly want to make it swallow duplicates
*/
trait Agg[V] extends IterableOnce[V] {
trait Agg[V]
extends IterableOnce[V]
with IterableOps[V, Agg, Agg[V]] {

override def iterableFactory: IterableFactory[Agg]

override def fromSpecific(coll: IterableOnce[V]): Agg[V] = fromSpecific0(coll)
protected def fromSpecific0(coll: IterableOnce[V]): Agg[V]

override def newSpecificBuilder: scala.collection.mutable.Builder[V, Agg[V]] =
newSpecificBuilder0
protected def newSpecificBuilder0: scala.collection.mutable.Builder[V, Agg[V]]

def contains(v: V): Boolean
def items: Iterator[V]
def indexed: IndexedSeq[V]
def flatMap[T](f: V => IterableOnce[T]): Agg[T]
def map[T](f: V => T): Agg[T]
def filter(f: V => Boolean): Agg[V]
def withFilter(f: V => Boolean): Agg[V]

def collect[T](f: PartialFunction[V, T]): Agg[T]
def zipWithIndex: Agg[(V, Int)]
def reverse: Agg[V]
def zip[T](other: Agg[T]): Agg[(V, T)]
def ++[T >: V](other: IterableOnce[T]): Agg[T]
def length: Int
def isEmpty: Boolean
def nonEmpty: Boolean = !isEmpty
def foreach[U](f: V => U): Unit
}

object Agg {
object Agg extends IterableFactory[Agg] {
def empty[V]: Agg[V] = new Agg.Mutable[V]
implicit def jsonFormat[T: upickle.default.ReadWriter]: upickle.default.ReadWriter[Agg[T]] =
upickle.default
Expand All @@ -43,79 +53,107 @@ private[mill] sealed class AggWrapper(strictUniqueness: Boolean) {
Agg.from(_)
)

def apply[V](items: V*): Agg[V] = from(items)
implicit def from[V](items: IterableOnce[V]): Agg[V] = Mutable.from(items)
object Mutable {
implicit def from[V](items: IterableOnce[V]): Mutable[V] = {
val set = new Agg.Mutable[V]()
items.iterator.foreach(set.append)
set
}

def newBuilder[V] = new mutable.Builder[V, Mutable[V]] {
var mutable = new Agg.Mutable[V]()
def clear(): Unit = { mutable = new Agg.Mutable[V]() }
def result(): Mutable[V] = mutable

implicit def from[V](items: IterableOnce[V]): Agg[V] = {
val set = new Agg.Mutable[V]()
items.iterator.foreach(set.append)
set
def addOne(elem: V): this.type = {
mutable.append(elem)
this
}
}
}

class Mutable[V]() extends Agg[V] {
def iterableFactory: IterableFactory[Mutable] = new IterableFactory[Mutable] {
def from[A](source: IterableOnce[A]): Mutable[A] = Mutable.from(source)
def empty[A]: Mutable[A] = new Mutable[A]()
def newBuilder[A]: mutable.Builder[A, Mutable[A]] = Mutable.newBuilder[A]
}

protected def fromSpecific0(coll: IterableOnce[V]): Mutable[V] = from(coll)
protected def newSpecificBuilder0: mutable.Builder[V, Agg[V]] = {
Mutable.newBuilder[V]
}

private[this] val set0 = mutable.LinkedHashSet.empty[V]
def contains(v: V): Boolean = set0.contains(v)
def append(v: V): AnyVal =

def contains(v: V) = set0.contains(v)
def coll = this

override def toIterable: Iterable[V] = set0.toIterable
def append(v: V): AnyVal = {
if (!contains(v)) {
set0.add(v)

} else if (strictUniqueness) {
throw new Exception("Duplicated item inserted into OrderedSet: " + v)
}
}

def appendAll(vs: Seq[V]): Unit = vs.foreach(append)
def items: Iterator[V] = set0.iterator
def indexed: IndexedSeq[V] = items.toIndexedSeq
def set: collection.Set[V] = set0

def map[T](f: V => T): Agg[T] = {
override def map[T](f: V => T): Mutable[T] = {
val output = new Agg.Mutable[T]
for (i <- items) output.append(f(i))
output
}
def flatMap[T](f: V => IterableOnce[T]): Agg[T] = {

override def flatMap[T](f: V => IterableOnce[T]): Mutable[T] = {
val output = new Agg.Mutable[T]
for (i <- items) for (i0 <- f(i).iterator) output.append(i0)
output
}
def filter(f: V => Boolean): Agg[V] = {

override def filter(f: V => Boolean): Mutable[V] = {
val output = new Agg.Mutable[V]
for (i <- items) if (f(i)) output.append(i)
output
}
def withFilter(f: V => Boolean): Agg[V] = filter(f)

def collect[T](f: PartialFunction[V, T]): Agg[T] =
this.filter(f.isDefinedAt).map(x => f(x))
protected def withFilter0(f: V => Boolean): collection.WithFilter[V, Mutable] =
new collection.WithFilter[V, Mutable] {
lazy val filtered = filter(f)
override def map[B](f: V => B): Mutable[B] = filtered.map(f)

def zipWithIndex: Agg[(V, Int)] = {
var i = 0
this.map { x =>
i += 1
(x, i - 1)
override def flatMap[B](f: V => IterableOnce[B]): Mutable[B] = filtered.flatMap(f)

override def foreach[U](f: V => U): Unit = filtered.foreach(f)

override def withFilter(q: V => Boolean): collection.WithFilter[V, Mutable] =
filtered.withFilter0(f)
}
}

def reverse: Agg[V] = Agg.from(indexed.reverseIterator)
override def reverse: Mutable[V] = Mutable.from(indexed.reverseIterator)

def zip[T](other: Agg[T]): Agg[(V, T)] = Agg.from(items.zip(other.items))
def ++[T >: V](other: IterableOnce[T]): Agg[T] = Agg.from(items ++ other)
def zip[T](other: Agg[T]): Mutable[(V, T)] = Mutable.from(items.zip(other.items))
def length: Int = set0.size

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 isEmpty: Boolean = items.isEmpty
def seq: scala.collection.IterableOnce[V] = items
override def exists(p: V => Boolean): Boolean = items.exists(p)
override def find(p: V => Boolean): Option[V] = items.find(p)
override def forall(p: V => Boolean): Boolean = items.forall(p)
override def foreach[U](f: V => U): Unit = items.foreach(f)
override def isEmpty: Boolean = items.isEmpty
def iterator: Iterator[V] = items

override def hashCode(): Int = items.map(_.hashCode()).sum
override def equals(other: Any): Boolean = other match {
case s: Agg[_] => items.sameElements(s.items)
case _ => super.equals(other)
}
override def toString: String = items.mkString("Agg(", ", ", ")")

}

override def newBuilder[A]: mutable.Builder[A, Agg[A]] = Mutable.newBuilder[A]
}
}
2 changes: 1 addition & 1 deletion runner/src/mill/runner/MillBuildRootModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class MillBuildRootModule()(implicit
super.scalacOptions() ++
Seq(
"-Xplugin:" + lineNumberPluginClasspath().map(_.path).mkString(","),
"-nowarn",
"-deprecation",
// Make sure we abort of the plugin is not found, to ensure any
// classpath/plugin-discovery issues are surfaced early rather than
// after hours of debugging
Expand Down

0 comments on commit 0579050

Please sign in to comment.