Skip to content

Commit

Permalink
Only use scala-collection-compat for Scala 2.12
Browse files Browse the repository at this point in the history
  • Loading branch information
mdedetrich committed Jun 15, 2023
1 parent 058a66c commit b8b7f14
Show file tree
Hide file tree
Showing 26 changed files with 245 additions and 26 deletions.
14 changes: 12 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,17 @@ def slickGeneralSettings =
"-diagrams", // requires graphviz
"-groups"
),
logBuffered := false
logBuffered := false,
// Adds a `src/main/scala-2.13+` source directory for code shared
// between Scala 2.13 and Scala 3
Compile / unmanagedSourceDirectories ++= {
val sourceDir = (Compile / sourceDirectory).value
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, n)) => Seq(sourceDir / "scala-2.13+")
case Some((2, n)) if n >= 13 => Seq(sourceDir / "scala-2.13+")
case _ => Nil
}
}
)

// set the scala-compiler dependency unless a local scala is in use
Expand Down Expand Up @@ -136,7 +146,7 @@ lazy val slick =
extTarget("slick"),
name := "Slick",
description := "Scala Language-Integrated Connection Kit",
libraryDependencies ++= Dependencies.mainDependencies,
libraryDependencies ++= Dependencies.mainDependencies.value,
scaladocSourceUrl("slick"),
Compile / doc / scalacOptions ++= Seq(
"-doc-root-content", "scaladoc-root.txt"
Expand Down
16 changes: 16 additions & 0 deletions doc/paradox/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,22 @@ Latest changes

See @ref:[the generated tables of incompatible changes](compat-report.md)

Upgrade from 3.4.x to 3.5.0
-----------------------

### Dependency upgrades

Slick 3.5.x drops [scala-collection-compat](https://github.com/scala/scala-collection-compat) for Scala versions
2.13 and higher. This shouldn't affect end users unless you happen to be transitively relying on
`scala-collection-compat` on a version of Scala 2.13 or higher. If this is the case then it's recommended to migrate
your codebase away from `scala-collection-compat`, otherwise if this is not possible then you can just add the

```sbt
"org.scala-lang.modules" %% "scala-collection-compat" % "2.10.0"
```

dependency manually.

Upgrade from 3.3.x to 3.4.0
-----------------------

Expand Down
15 changes: 13 additions & 2 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sbt.*
import sbt.Keys.scalaVersion

/** Dependencies for reuse in different parts of the build */
object Dependencies {
Expand All @@ -9,9 +10,19 @@ object Dependencies {
val reactiveStreamsVersion = "1.0.4"
val reactiveStreams = "org.reactivestreams" % "reactive-streams" % reactiveStreamsVersion
val reactiveStreamsTCK = "org.reactivestreams" % "reactive-streams-tck" % reactiveStreamsVersion
val scalaCollectionCompat = "org.scala-lang.modules" %% "scala-collection-compat" % "2.10.0"

def mainDependencies = Seq(slf4j, typesafeConfig, reactiveStreams, scalaCollectionCompat)
val scalaCollectionCompat = Def.setting {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) if n == 12 =>
Seq("org.scala-lang.modules" %% "scala-collection-compat" % "2.10.0")
case _ =>
Seq.empty
}
}

def mainDependencies = Def.setting {
Seq(slf4j, typesafeConfig, reactiveStreams) ++ scalaCollectionCompat.value
}

val junit = Seq(
"junit" % "junit-dep" % "4.11",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package slick.codegen

import scala.collection.compat.*

import slick.{SlickException, model as m}
import slick.ast.ColumnOption
import slick.model.ForeignKeyAction
import slick.relational.RelationalProfile
import slick.sql.SqlProfile
import slick.util.ccompat.*

/** Base implementation for a Source code String generator */
abstract class AbstractSourceCodeGenerator(model: m.Model)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import java.lang.reflect.Method
import java.util.concurrent.{ExecutionException, LinkedBlockingQueue, ThreadPoolExecutor, TimeUnit}
import java.util.concurrent.atomic.AtomicInteger

import scala.collection.compat.*
import scala.concurrent.*
import scala.concurrent.duration.Duration
import scala.reflect.ClassTag
Expand All @@ -19,6 +18,7 @@ import slick.lifted.Rep
import slick.relational.RelationalCapabilities
import slick.sql.SqlCapabilities
import slick.util.DumpInfo
import slick.util.ccompat.*

import org.junit.runner.Description
import org.junit.runner.notification.RunNotifier
Expand Down
22 changes: 22 additions & 0 deletions slick/src/main/scala-2.12/slick/util/ccompat/CompatImpl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2018-2022 Lightbend Inc. <https://www.lightbend.com>
*/

package slick.util.ccompat

import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder

/**
* INTERNAL API
*
* Based on https://github.com/scala/scala-collection-compat/blob/master/compat/src/main/scala-2.11_2.12/scala/collection/compat/CompatImpl.scala
* but reproduced here so we don't need to add a dependency on this library. It contains much more than we need right now, and is
* not promising binary compatibility yet at the time of writing.
*/
private[ccompat] object CompatImpl {
def simpleCBF[A, C](f: => Builder[A, C]): CanBuildFrom[Any, A, C] = new CanBuildFrom[Any, A, C] {
def apply(from: Any): Builder[A, C] = apply()
def apply(): Builder[A, C] = f
}
}
144 changes: 144 additions & 0 deletions slick/src/main/scala-2.12/slick/util/ccompat/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright (C) 2018-2022 Lightbend Inc. <https://www.lightbend.com>
*/

package slick.util

import scala.{ collection => c }
import scala.collection.{ immutable => i, mutable => m, GenTraversable, IterableView }
import scala.collection.generic.{ CanBuildFrom, GenericCompanion, Sorted, SortedSetFactory }
import scala.language.higherKinds
import scala.language.implicitConversions

/**
* INTERNAL API
*
* Based on https://github.com/scala/scala-collection-compat/blob/master/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala
* but reproduced here so we don't need to add a dependency on this library. It contains much more than we need right now, and is
* not promising binary compatibility yet at the time of writing.
*/
package object ccompat {
import CompatImpl.*

/**
* A factory that builds a collection of type `C` with elements of type `A`.
*
* @tparam A Type of elements (e.g. `Int`, `Boolean`, etc.)
* @tparam C Type of collection (e.g. `List[Int]`, `TreeMap[Int, String]`, etc.)
*/
private[slick] type Factory[-A, +C] = CanBuildFrom[Nothing, A, C]

private[slick] type LazyList[+T] = scala.collection.immutable.Stream[T]
private[slick] val LazyList = scala.collection.immutable.Stream

private[slick] implicit final class FactoryOps[-A, +C](private val factory: Factory[A, C]) {

/**
* @return A collection of type `C` containing the same elements
* as the source collection `it`.
* @param it Source collection
*/
def fromSpecific(it: TraversableOnce[A]): C = (factory() ++= it).result()

/**
* Get a Builder for the collection. For non-strict collection types this will use an intermediate buffer.
* Building collections with `fromSpecific` is preferred because it can be lazy for lazy collections.
*/
def newBuilder: m.Builder[A, C] = factory()
}

private[slick] implicit def genericCompanionToCBF[A, CC[X] <: GenTraversable[X]]
(fact: GenericCompanion[CC]): CanBuildFrom[Any, A, CC[A]] =
simpleCBF(fact.newBuilder[A])

private[slick] 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])

private[ccompat] def build[T, CC](builder: m.Builder[T, CC], source: TraversableOnce[T]): CC = {
builder ++= source
builder.result()
}

private[slick] implicit final 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)
}

private[slick] implicit final 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)
}

private[slick] implicit final class IterableExtensions(private val fact: Iterable.type) extends AnyVal {
def single[A](a: A): Iterable[A] = new Iterable[A] {
override def iterator = Iterator.single(a)
override def sizeHintIfCheap: Int = 1
override def hasDefiniteSize: Boolean = true
override def head = a
override def headOption = Some(a)
override def last = a
override def lastOption = Some(a)
override def view = new IterableView[A, Iterable[A]] {
override def iterator: Iterator[A] = Iterator.single(a)
override def sizeHintIfCheap: Int = 1
override def hasDefiniteSize: Boolean = true
override protected def underlying: Iterable[A] = this
}
override def take(n: Int) = if (n > 0) this else Iterable.empty
override def takeRight(n: Int) = if (n > 0) this else Iterable.empty
override def drop(n: Int) = if (n > 0) Iterable.empty else this
override def dropRight(n: Int) = if (n > 0) Iterable.empty else this
override def tail = Iterable.empty
override def init = Iterable.empty
}
}

private[slick] implicit final 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)
}

// 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

implicit def toMapViewExtensionMethods[K, V, C <: scala.collection.Map[K, V]]
(self: IterableView[(K, V), C]): MapViewExtensionMethods[K, V, C] =
new MapViewExtensionMethods[K, V, C](self)

implicit def toIterableViewExtensionMethods[A, C <: scala.collection.Iterable[A]]
(self: IterableView[A, C]): IterableViewExtensionMethods[A, C] =
new IterableViewExtensionMethods[A, C](self)

implicit final class ImmutableSortedSetOps[A](val real: i.SortedSet[A]) extends AnyVal {
def unsorted: i.Set[A] = real
}

object JavaConverters extends scala.collection.convert.DecorateAsJava with scala.collection.convert.DecorateAsScala

implicit def toTraversableOnceExtensionMethods[A](self: TraversableOnce[A]): TraversableOnceExtensionMethods[A] =
new TraversableOnceExtensionMethods[A](self)
}

final class TraversableOnceExtensionMethods[A](private val self: c.TraversableOnce[A]) extends AnyVal {
def iterator: Iterator[A] = self.toIterator
}

final class MapViewExtensionMethods[K, V, C <: scala.collection.Map[K, V]]
(private val self: IterableView[(K, V), C]) extends AnyVal {
def mapValues[W, That](f: V => W)(implicit bf: CanBuildFrom[IterableView[(K, V), C], (K, W), That]): That =
self.map[(K, W), That] { case (k, v) => (k, f(v)) }

def filterKeys(p: K => Boolean): IterableView[(K, V), C] =
self.filter { case (k, _) => p(k) }
}

final class IterableViewExtensionMethods[A, C <: scala.collection.Iterable[A]]
(private val self: IterableView[A, C]) extends AnyVal {
def lazyZip[B](that: Iterable[B]): Tuple2Zipped[A, B, this.type] =
(self, that).zipped
}
18 changes: 18 additions & 0 deletions slick/src/main/scala-2.13+/slick/util/ccompat/ccompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (C) 2018-2022 Lightbend Inc. <https://www.lightbend.com>
*/

package slick.util

package object ccompat {
private[slick] type Factory[-A, +C] = scala.collection.Factory[A, C]
private[slick] val Factory = scala.collection.Factory

private[slick] type LazyList[+T] = scala.collection.immutable.LazyList[T]
private[slick] val LazyList = scala.collection.immutable.LazyList

object JavaConverters
extends scala.collection.convert.AsJavaExtensions
with scala.collection.convert.AsScalaExtensions

}
2 changes: 1 addition & 1 deletion slick/src/main/scala/slick/ast/Node.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package slick.ast

import scala.collection.compat.immutable.LazyList
import scala.collection.mutable.ListBuffer
import scala.reflect.ClassTag

import slick.SlickException
import slick.ast.TypeUtil.*
import slick.util.ccompat.LazyList
import slick.util.{ConstArray, Dumpable, DumpInfo, GlobalConfig}

/** A node in the Slick AST.
Expand Down
2 changes: 1 addition & 1 deletion slick/src/main/scala/slick/ast/Type.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package slick.ast

import scala.annotation.{implicitNotFound, tailrec}
import scala.collection.compat.*
import scala.collection.mutable
import scala.language.implicitConversions
import scala.reflect.{ClassTag, classTag as mkClassTag}

import slick.SlickException
import slick.util.{ConstArray, Dumpable, DumpInfo, TupleSupport}
import slick.util.ccompat.*

/** Super-trait for all types */
trait Type extends Dumpable {
Expand Down
2 changes: 1 addition & 1 deletion slick/src/main/scala/slick/basic/BasicBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package slick.basic
import java.io.Closeable
import java.util.concurrent.atomic.{AtomicLong, AtomicReferenceArray}

import scala.collection.compat.*
import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.util.{Failure, Success}
import scala.util.control.NonFatal

import slick.SlickException
import slick.dbio.*
import slick.util.*
import slick.util.ccompat.*
import slick.util.AsyncExecutor.{Continuation, Fresh, Priority, WithConnection}

import com.typesafe.config.Config
Expand Down
2 changes: 1 addition & 1 deletion slick/src/main/scala/slick/dbio/DBIOAction.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package slick.dbio

import scala.collection.compat.*
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.{ExecutionContext, Future}
Expand All @@ -10,6 +9,7 @@ import scala.util.control.NonFatal
import slick.SlickException
import slick.basic.BasicBackend
import slick.util.{ignoreFollowOnError, Dumpable, DumpInfo}
import slick.util.ccompat.*

import org.reactivestreams.Subscription

Expand Down
2 changes: 1 addition & 1 deletion slick/src/main/scala/slick/jdbc/Invoker.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package slick.jdbc

import scala.annotation.unchecked.uncheckedVariance
import scala.collection.compat.*

import slick.util.CloseableIterator
import slick.util.ccompat.*

/** Base trait for all statement invokers of result element type R. */
trait Invoker[+R] { self =>
Expand Down
2 changes: 1 addition & 1 deletion slick/src/main/scala/slick/jdbc/JdbcActionComponent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package slick.jdbc

import java.sql.{PreparedStatement, Statement}

import scala.collection.compat.*
import scala.collection.mutable.Builder
import scala.language.existentials
import scala.util.control.NonFatal
Expand All @@ -17,6 +16,7 @@ import slick.lifted.{CompiledStreamingExecutable, FlatShapeLevel, Query, Shape}
import slick.relational.{CompiledMapping, ResultConverter}
import slick.sql.{FixedSqlAction, FixedSqlStreamingAction, SqlActionComponent}
import slick.util.{ignoreFollowOnError, DumpInfo, SQLBuilder}
import slick.util.ccompat.*


trait JdbcActionComponent extends SqlActionComponent { self: JdbcProfile =>
Expand Down
2 changes: 1 addition & 1 deletion slick/src/main/scala/slick/jdbc/LoggingStatement.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import java.net.URL
import java.sql.{Array as _, *}
import java.util.Calendar

import scala.collection.compat.*
import scala.collection.mutable.ArrayBuffer

import slick.jdbc.JdbcBackend.{benchmarkLogger, parameterLogger, statementAndParameterLogger, statementLogger}
import slick.util.ccompat.*
import slick.util.TableDump

/** A wrapper for `java.sql.Statement` that logs statements and benchmark results
Expand Down
Loading

0 comments on commit b8b7f14

Please sign in to comment.