From dd7107383db8921167547a1e1a24d8a359b7e30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Mon, 23 Jul 2018 11:36:13 +0200 Subject: [PATCH 1/3] Fix broken .travis.yml --- .travis.yml | 21 ++++++++++--------- build.sbt | 8 +++---- .../scala/collection/JdkVersionTest.scala | 4 ++++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 938f39c5..98d2b23a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,12 @@ +# slower instance startup, but needed to work around https://github.com/travis-ci/travis-ci/issues/9713 +sudo: true + language: scala +addons: + apt: + packages: + - openjdk-6-jdk scala: - 2.11.12 - 2.12.6 @@ -40,18 +47,12 @@ matrix: # 2.13.0-M4 is not available in Scala.js 1.0.0-M3 - scala: 2.13.0-M4 env: SCALAJS_VERSION=1.0.0-M3 - - # run migration test include: - - scala: 2.12.6 - jdk: oraclejdk8 - env: TEST_SCALAFIX=true - - addons: - apt: - packages: - - openjdk-6-jdk - jdk: openjdk6 + # run migration test + - jdk: oraclejdk8 + scala: 2.12.6 + env: TEST_SCALAFIX=true # | jdk | scala | scala target | scala target version | scalafix test | # | ----------- | --------- | ------------ | -------------------- |---------------| diff --git a/build.sbt b/build.sbt index 53c4c1b3..bca893c1 100644 --- a/build.sbt +++ b/build.sbt @@ -33,8 +33,8 @@ lazy val compat = crossProject(JSPlatform, JVMPlatform) .jvmSettings( OsgiKeys.exportPackage := Seq(s"scala.collection.compat.*;version=${version.value}"), libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - javaHome := { - val oldValue = javaHome.value + javaHome in Compile := { + val oldValue = (javaHome in Compile).value val isOnCi = sys.env.get("CI").isDefined if (isOnCi) { @@ -44,12 +44,12 @@ lazy val compat = crossProject(JSPlatform, JVMPlatform) case "openjdk6" => "/usr/lib/jvm/java-6-openjdk-amd64" case "oraclejdk8" => "/usr/lib/jvm/java-8-oracle" } - println(s"using JAVA_HOME: $ciJavaHome") Some(file(ciJavaHome)) } else oldValue - } + }, + javaHome in Test := (javaHome in Compile).value ) .jsSettings( scalacOptions += { diff --git a/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala b/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala index 48e58269..e61f4a9c 100644 --- a/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala +++ b/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala @@ -11,6 +11,10 @@ class JdkVersionTest { if (isOnCi) { val travisJdkVersion = sys.env("TRAVIS_JDK_VERSION") val jdkVersion = sys.props("java.specification.version") + + println(s"travisJdkVersion: $travisJdkVersion") + println(s"jdkVersion: $jdkVersion") + if (travisJdkVersion == "openjdk6") { assertEquals(jdkVersion, "1.8") } else if (travisJdkVersion == "oraclejdk8") { From de157d0f6cb14001d2ab362b6367582d58c4f34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Mon, 23 Jul 2018 14:24:02 +0200 Subject: [PATCH 2/3] Split compat package object for 2.11 and 2.12 mutable.TreeMap and mutable.ListMap are not available in 2.11. It's not possible to put implicit classes in a shared trait. We have to duplicate a bit the api --- .../scala/collection/compat/package.scala | 3 + .../collection/compat/PackageShared.scala | 196 ++++++++++++++++++ .../scala/collection/compat/package.scala | 111 ---------- .../scala/collection/compat/package.scala | 17 ++ 4 files changed, 216 insertions(+), 111 deletions(-) create mode 100644 compat/src/main/scala-2.11/scala/collection/compat/package.scala create mode 100644 compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala delete mode 100644 compat/src/main/scala-2.11_2.12/scala/collection/compat/package.scala create mode 100644 compat/src/main/scala-2.12/scala/collection/compat/package.scala diff --git a/compat/src/main/scala-2.11/scala/collection/compat/package.scala b/compat/src/main/scala-2.11/scala/collection/compat/package.scala new file mode 100644 index 00000000..479401e5 --- /dev/null +++ b/compat/src/main/scala-2.11/scala/collection/compat/package.scala @@ -0,0 +1,3 @@ +package scala.collection + +package object compat extends compat.PackageShared diff --git a/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala new file mode 100644 index 00000000..72780986 --- /dev/null +++ b/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala @@ -0,0 +1,196 @@ +package scala.collection.compat + +import scala.collection.generic._ +import scala.reflect.ClassTag +import scala.collection.{MapLike, GenTraversable, BitSet} +import scala.collection.{immutable => i, mutable => m} +import scala.{collection => c} + +/** The collection compatibility API */ +private[compat] trait PackageShared { + import CompatImpl._ + + implicit def genericCompanionToCBF[A, CC[X] <: GenTraversable[X]]( + fact: GenericCompanion[CC]): CanBuildFrom[Any, A, CC[A]] = + simpleCBF(fact.newBuilder[A]) + + implicit def sortedSetCompanionToCBF[ + A: Ordering, + CC[X] <: c.SortedSet[X] with c.SortedSetLike[X, CC[X]]]( + fact: SortedSetFactory[CC]): CanBuildFrom[Any, A, CC[A]] = + simpleCBF(fact.newBuilder[A]) + + implicit def arrayCompanionToCBF[A: ClassTag]( + fact: Array.type): CanBuildFrom[Any, A, Array[A]] = + simpleCBF(Array.newBuilder[A]) + + implicit def mapFactoryToCBF[ + K, + V, + CC[A, B] <: Map[A, B] with MapLike[A, B, CC[A, B]]]( + fact: MapFactory[CC]): CanBuildFrom[Any, (K, V), CC[K, V]] = + simpleCBF(fact.newBuilder[K, V]) + + implicit def sortedMapFactoryToCBF[ + K: Ordering, + V, + CC[A, B] <: c.SortedMap[A, B] with c.SortedMapLike[A, B, CC[A, B]]]( + fact: SortedMapFactory[CC]): CanBuildFrom[Any, (K, V), CC[K, V]] = + simpleCBF(fact.newBuilder[K, V]) + + implicit def bitSetFactoryToCBF( + fact: BitSetFactory[BitSet]): CanBuildFrom[Any, Int, BitSet] = + simpleCBF(fact.newBuilder) + + implicit def immutableBitSetFactoryToCBF(fact: BitSetFactory[i.BitSet]) + : CanBuildFrom[Any, Int, ImmutableBitSetCC[Int]] = + simpleCBF(fact.newBuilder) + + implicit def mutableBitSetFactoryToCBF(fact: BitSetFactory[m.BitSet]) + : CanBuildFrom[Any, Int, MutableBitSetCC[Int]] = + simpleCBF(fact.newBuilder) + + implicit class IterableFactoryExtensionMethods[CC[X] <: GenTraversable[X]]( + private val fact: GenericCompanion[CC]) { + def from[A](source: TraversableOnce[A]): CC[A] = + fact.apply(source.toSeq: _*) + } + + implicit class MapFactoryExtensionMethods[ + CC[A, B] <: Map[A, B] with MapLike[A, B, CC[A, B]]]( + private val fact: MapFactory[CC]) { + def from[K, V](source: TraversableOnce[(K, V)]): CC[K, V] = + fact.apply(source.toSeq: _*) + } + + implicit class BitSetFactoryExtensionMethods[ + C <: scala.collection.BitSet with scala.collection.BitSetLike[C]]( + private val fact: BitSetFactory[C]) { + def fromSpecific(source: TraversableOnce[Int]): C = + fact.apply(source.toSeq: _*) + } + + private[compat] def build[T, CC](builder: m.Builder[T, CC], + source: TraversableOnce[T]): CC = { + builder ++= source + builder.result() + } + + implicit def toImmutableSortedMapExtensions(fact: i.SortedMap.type): ImmutableSortedMapExtensions = + new ImmutableSortedMapExtensions(fact) + + implicit def toImmutableListMapExtensions(fact: i.ListMap.type): ImmutableListMapExtensions = + new ImmutableListMapExtensions(fact) + + implicit def toImmutableHashMapExtensions(fact: i.HashMap.type): ImmutableHashMapExtensions = + new ImmutableHashMapExtensions(fact) + + implicit def toImmutableTreeMapExtensions(fact: i.TreeMap.type): ImmutableTreeMapExtensions = + new ImmutableTreeMapExtensions(fact) + + implicit def toImmutableIntMapExtensions(fact: i.IntMap.type): ImmutableIntMapExtensions = + new ImmutableIntMapExtensions(fact) + + implicit def toImmutableLongMapExtensions(fact: i.LongMap.type): ImmutableLongMapExtensions = + new ImmutableLongMapExtensions(fact) + + implicit def toMutableLongMapExtensions(fact: m.LongMap.type): MutableLongMapExtensions = + new MutableLongMapExtensions(fact) + + implicit def toMutableHashMapExtensions(fact: m.HashMap.type): MutableHashMapExtensions = + new MutableHashMapExtensions(fact) + + implicit def toMutableListMapExtensions(fact: m.ListMap.type): MutableListMapExtensions = + new MutableListMapExtensions(fact) + + implicit def toMutableMapExtensions(fact: m.Map.type): MutableMapExtensions = + new MutableMapExtensions(fact) + + implicit def toStreamExtensionMethods[A](stream: Stream[A]): StreamExtensionMethods[A] = + new StreamExtensionMethods[A](stream) + + implicit def toSortedExtensionMethods[K, V <: Sorted[K, V]](fact: Sorted[K, V]): SortedExtensionMethods[K, V] = + new SortedExtensionMethods[K, V](fact) + + implicit def toIteratorExtensionMethods[A](self: Iterator[A]): IteratorExtensionMethods[A] = + new IteratorExtensionMethods[A](self) + + implicit def toTraversableOnceExtensionMethods[A](self: TraversableOnce[A]): TraversableOnceExtensionMethods[A] = + new TraversableOnceExtensionMethods[A](self) + + // This really belongs into scala.collection but there's already a package object + // in scala-library so we can't add to it + type IterableOnce[+X] = c.TraversableOnce[X] + val IterableOnce = c.TraversableOnce +} + +class ImmutableSortedMapExtensions(private val fact: i.SortedMap.type) extends AnyVal { + def from[K: Ordering, V](source: TraversableOnce[(K, V)]): i.SortedMap[K, V] = + build(i.SortedMap.newBuilder[K, V], source) +} + +class ImmutableListMapExtensions(private val fact: i.ListMap.type) extends AnyVal { + def from[K, V](source: TraversableOnce[(K, V)]): i.ListMap[K, V] = + build(i.ListMap.newBuilder[K, V], source) +} + +class ImmutableHashMapExtensions(private val fact: i.HashMap.type) extends AnyVal { + def from[K, V](source: TraversableOnce[(K, V)]): i.HashMap[K, V] = + build(i.HashMap.newBuilder[K, V], source) +} + +class ImmutableTreeMapExtensions(private val fact: i.TreeMap.type) extends AnyVal { + def from[K: Ordering, V](source: TraversableOnce[(K, V)]): i.TreeMap[K, V] = + build(i.TreeMap.newBuilder[K, V], source) +} + +class ImmutableIntMapExtensions(private val fact: i.IntMap.type) extends AnyVal { + def from[V](source: TraversableOnce[(Int, V)]): i.IntMap[V] = + build(i.IntMap.canBuildFrom[Int, V](), source) +} + +class ImmutableLongMapExtensions(private val fact: i.LongMap.type) extends AnyVal { + def from[V](source: TraversableOnce[(Long, V)]): i.LongMap[V] = + build(i.LongMap.canBuildFrom[Long, V](), source) +} + +class MutableLongMapExtensions(private val fact: m.LongMap.type) extends AnyVal { + def from[V](source: TraversableOnce[(Long, V)]): m.LongMap[V] = + build(m.LongMap.canBuildFrom[Long, V](), source) +} + +class MutableHashMapExtensions(private val fact: m.HashMap.type) extends AnyVal { + def from[K, V](source: TraversableOnce[(K, V)]): m.HashMap[K, V] = + build(m.HashMap.canBuildFrom[K, V](), source) +} + +class MutableListMapExtensions(private val fact: m.ListMap.type) extends AnyVal { + def from[K, V](source: TraversableOnce[(K, V)]): m.ListMap[K, V] = + build(m.ListMap.canBuildFrom[K, V](), source) +} + +class MutableMapExtensions(private val fact: m.Map.type) extends AnyVal { + def from[K, V](source: TraversableOnce[(K, V)]): m.Map[K, V] = + build(m.Map.canBuildFrom[K, V](), source) +} + +class StreamExtensionMethods[A](private val stream: Stream[A]) extends AnyVal { + def lazyAppendedAll(as: => TraversableOnce[A]): Stream[A] = stream.append(as) +} + +class SortedExtensionMethods[K, T <: Sorted[K, T]](private val fact: Sorted[K, T]) { + def rangeFrom(from: K): T = fact.from(from) + def rangeTo(to: K): T = fact.to(to) + def rangeUntil(until: K): T = fact.until(until) +} + +class IteratorExtensionMethods[A](private val self: c.Iterator[A]) extends AnyVal { + def sameElements[B >: A](that: c.TraversableOnce[B]): Boolean = { + self.sameElements(that.iterator) + } + def concat[B >: A](that: c.TraversableOnce[B]): c.TraversableOnce[B] = self ++ that +} + +class TraversableOnceExtensionMethods[A](private val self: c.TraversableOnce[A]) extends AnyVal { + def iterator: Iterator[A] = self.toIterator +} diff --git a/compat/src/main/scala-2.11_2.12/scala/collection/compat/package.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/package.scala deleted file mode 100644 index 3587e63e..00000000 --- a/compat/src/main/scala-2.11_2.12/scala/collection/compat/package.scala +++ /dev/null @@ -1,111 +0,0 @@ -package scala.collection - -import scala.collection.generic._ -import scala.reflect.ClassTag -import scala.collection.{immutable => i, mutable => m} - -/** The collection compatibility API */ -package object compat { - import CompatImpl._ - - implicit def genericCompanionToCBF[A, CC[X] <: GenTraversable[X]](fact: GenericCompanion[CC]): CanBuildFrom[Any, A, CC[A]] = - simpleCBF(fact.newBuilder[A]) - - implicit def sortedSetCompanionToCBF[A : Ordering, CC[X] <: SortedSet[X] with SortedSetLike[X, CC[X]]](fact: SortedSetFactory[CC]): CanBuildFrom[Any, A, CC[A]] = - simpleCBF(fact.newBuilder[A]) - - implicit def arrayCompanionToCBF[A : ClassTag](fact: Array.type): CanBuildFrom[Any, A, Array[A]] = - simpleCBF(Array.newBuilder[A]) - - implicit def mapFactoryToCBF[K, V, CC[A, B] <: Map[A, B] with MapLike[A, B, CC[A, B]]](fact: MapFactory[CC]): CanBuildFrom[Any, (K, V), CC[K, V]] = - simpleCBF(fact.newBuilder[K, V]) - - implicit def sortedMapFactoryToCBF[K : Ordering, V, CC[A, B] <: SortedMap[A, B] with SortedMapLike[A, B, CC[A, B]]](fact: SortedMapFactory[CC]): CanBuildFrom[Any, (K, V), CC[K, V]] = - simpleCBF(fact.newBuilder[K, V]) - - implicit def bitSetFactoryToCBF(fact: BitSetFactory[BitSet]): CanBuildFrom[Any, Int, BitSet] = - simpleCBF(fact.newBuilder) - - implicit def immutableBitSetFactoryToCBF(fact: BitSetFactory[i.BitSet]): CanBuildFrom[Any, Int, ImmutableBitSetCC[Int]] = - simpleCBF(fact.newBuilder) - - implicit def mutableBitSetFactoryToCBF(fact: BitSetFactory[m.BitSet]): CanBuildFrom[Any, Int, MutableBitSetCC[Int]] = - simpleCBF(fact.newBuilder) - - implicit class IterableFactoryExtensionMethods[CC[X] <: GenTraversable[X]](private val fact: GenericCompanion[CC]) { - def from[A](source: TraversableOnce[A]): CC[A] = fact.apply(source.toSeq: _*) - } - - implicit class MapFactoryExtensionMethods[CC[A, B] <: Map[A, B] with MapLike[A, B, CC[A, B]]](private val fact: MapFactory[CC]) { - def from[K, V](source: TraversableOnce[(K, V)]): CC[K, V] = fact.apply(source.toSeq: _*) - } - - implicit class BitSetFactoryExtensionMethods[C <: scala.collection.BitSet with scala.collection.BitSetLike[C]](private val fact: BitSetFactory[C]) { - def fromSpecific(source: TraversableOnce[Int]): C = fact.apply(source.toSeq: _*) - } - - private def build[T, CC](builder: m.Builder[T, CC], source: TraversableOnce[T]): CC = { - builder ++= source - builder.result() - } - - implicit class ImmutableSortedMapExtensions(private val fact: i.SortedMap.type) extends AnyVal { - def from[K: Ordering, V](source: TraversableOnce[(K, V)]): i.SortedMap[K, V] = - build(i.SortedMap.newBuilder[K, V], source) - } - - implicit class ImmutableTreeMapExtensions(private val fact: i.TreeMap.type) extends AnyVal { - def from[K: Ordering, V](source: TraversableOnce[(K, V)]): i.TreeMap[K, V] = - build(i.TreeMap.newBuilder[K, V], source) - } - - implicit class ImmutableIntMapExtensions(private val fact: i.IntMap.type) extends AnyVal { - def from[V](source: TraversableOnce[(Int, V)]): i.IntMap[V] = - build(i.IntMap.canBuildFrom[Int, V](), source) - } - - implicit class ImmutableLongMapExtensions(private val fact: i.LongMap.type) extends AnyVal { - def from[V](source: TraversableOnce[(Long, V)]): i.LongMap[V] = - build(i.LongMap.canBuildFrom[Long, V](), source) - } - - implicit class MutableSortedMapExtensions(private val fact: m.SortedMap.type) extends AnyVal { - def from[K: Ordering, V](source: TraversableOnce[(K, V)]): m.SortedMap[K, V] = - build(m.SortedMap.newBuilder[K, V], source) - } - - implicit class MutableTreeMapExtensions(private val fact: m.TreeMap.type) extends AnyVal { - def from[K: Ordering, V](source: TraversableOnce[(K, V)]): m.TreeMap[K, V] = - build(m.TreeMap.newBuilder[K, V], source) - } - - implicit class MutableLongMapExtensions(private val fact: m.LongMap.type) extends AnyVal { - def from[V](source: TraversableOnce[(Long, V)]): m.LongMap[V] = - build(m.LongMap.canBuildFrom[Long, V](), source) - } - - implicit class StreamExtensionMethods[A](private val stream: Stream[A]) extends AnyVal { - def lazyAppendedAll(as: => TraversableOnce[A]): Stream[A] = stream.append(as) - } - - implicit class SortedExtensionMethods[K, T <: Sorted[K, T]](private val fact: Sorted[K, T]) { - def rangeFrom(from: K): T = fact.from(from) - def rangeTo(to: K): T = fact.to(to) - def rangeUntil(until: K): T = fact.until(until) - } - - implicit class IteratorExtensionMethods[A](private val self: Iterator[A]) extends AnyVal { - def sameElements[B >: A](that: IterableOnce[B]): Boolean = { - self.sameElements(that.iterator) - } - def concat[B >: A](that: IterableOnce[B]): IterableOnce[B] = self ++ that - } - - implicit class TraversableOnceExtensionMethods[A](private val self: TraversableOnce[A]) extends AnyVal { - def iterator: Iterator[A] = self.toIterator - } - - // This really belongs into scala.collection but there's already a package object in scala-library so we can't add to it - type IterableOnce[+X] = TraversableOnce[X] - val IterableOnce = TraversableOnce -} diff --git a/compat/src/main/scala-2.12/scala/collection/compat/package.scala b/compat/src/main/scala-2.12/scala/collection/compat/package.scala new file mode 100644 index 00000000..17ab2e06 --- /dev/null +++ b/compat/src/main/scala-2.12/scala/collection/compat/package.scala @@ -0,0 +1,17 @@ +package scala.collection + +import scala.collection.{mutable => m} + +package object compat extends compat.PackageShared { + implicit class MutableTreeMapExtensions2(private val fact: m.TreeMap.type) extends AnyVal { + def from[K: Ordering, V](source: TraversableOnce[(K, V)]): m.TreeMap[K, V] = + build(m.TreeMap.newBuilder[K, V], source) + } + + implicit class MutableSortedMapExtensions(private val fact: m.SortedMap.type) extends AnyVal { + def from[K: Ordering, V](source: TraversableOnce[(K, V)]): m.SortedMap[K, V] = + build(m.SortedMap.newBuilder[K, V], source) + } +} + + From 68d8300228f5bef6587bb3665c68cb1b3cd7c422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Mon, 23 Jul 2018 14:35:17 +0200 Subject: [PATCH 3/3] Fix jdk test logic --- .../test/scala/collection/JdkVersionTest.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala b/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala index e61f4a9c..acf3a890 100644 --- a/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala +++ b/compat/src/test/scala/test/scala/collection/JdkVersionTest.scala @@ -10,17 +10,19 @@ class JdkVersionTest { val isOnCi = sys.env.get("CI").isDefined if (isOnCi) { val travisJdkVersion = sys.env("TRAVIS_JDK_VERSION") - val jdkVersion = sys.props("java.specification.version") + val obtained = sys.props("java.specification.version") println(s"travisJdkVersion: $travisJdkVersion") - println(s"jdkVersion: $jdkVersion") + println(s"jdkVersion: $obtained") - if (travisJdkVersion == "openjdk6") { - assertEquals(jdkVersion, "1.8") - } else if (travisJdkVersion == "oraclejdk8") { - assertEquals(jdkVersion, "1.6") - } else { - throw new Exception(s"Unknown CI jdk version: $travisJdkVersion") + val expectedJdkVersion = Map( + "openjdk6" -> "1.6", + "oraclejdk8" -> "1.8" + ) + + expectedJdkVersion.get(travisJdkVersion) match { + case Some(expected) => assertEquals(obtained, expected) + case None => throw new Exception(s"Unknown CI jdk version: $travisJdkVersion") } } }