Skip to content

Commit

Permalink
For 1-15, potentially drop Scala 2.11 support and add Scala 3 (#41)
Browse files Browse the repository at this point in the history
* for 1-15, drop _2.11 and add _3
* bump scoverage plugin
* bump scoverage plugin M3
* Drop ScalaCheck 1.12, drop Scala 2.11
* mima and initial _3
* put 2.11 back, use project matrix
  • Loading branch information
russellremple authored Dec 23, 2021
1 parent d0a848b commit 8d53310
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 146 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ before_script:
- curl -L -o $HOME/.sbt/launchers/1.5.3/sbt-launch.jar https://repo1.maven.org/maven2/org/scala-sbt/sbt-launch/1.5.3/sbt-launch-1.5.3.jar

script:
- sbt clean coverage +test coverageAggregate
- sbt clean coverage test coverageAggregate
# Upload coverage reports to codecov.io before checking binary compatibility
- bash <(curl -s https://codecov.io/bash)
- sbt +mimaReportBinaryIssues
- sbt mimaReportBinaryIssues

# Avoid unnecessary cache updates
before_cache:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ no version suffix would pull in ScalaCheck version 1.12.6.

| Artifact Name | Version Limit | ScalaCheck | Supported JDK | Supported Scala |
| :-----------------: | :------------: | :--------: | :-----------: | :--------------: |
| scalacheck-ops_1-15 | x >= 2.5.2 | 1.15.2 | 8 | 2.11, 2.12, 2.13 |
| scalacheck-ops_1-15 | x >= 2.5.2 | 1.15.4 | 8 | 2.12, 2.13, 3 |
| scalacheck-ops_1-14 | x >= 2.0 | 1.14.3 | 8 | 2.11, 2.12, 2.13 |
| scalacheck-ops_1-13 | x >= 2.0 | 1.13.5 | 8 | 2.11, 2.12 |
| scalacheck-ops_1-13 | 1.5 <= x < 2.0 | 1.13.4 | 6 - 8 | 2.10 - 2.11 |
Expand Down
239 changes: 143 additions & 96 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,24 @@ mimaFailOnNoPrevious := false
// don't publish the aggregate root project
publish / skip := true

def commonProject(id: String, artifact: String, path: String): Project = {
Project(id, file(path)).settings(
def commonSettings(artifact: String): Seq[Setting[_]] =
Seq(
name := artifact,

mimaPreviousArtifacts := Set(organization.value %% artifact % "2.6.0"),
mimaPreviousArtifacts := (
if (scalaBinaryVersion.value == "3") Set.empty // remove once _3 is published
else Set(organization.value %% artifact % "2.6.0")
),

scalacOptions := Seq(
scalacOptions ++= Seq(
// "-Xfatal-warnings", // some methods in Scala 2.13 are deprecated, but I don't want to maintain to copies of source
"-deprecation:false",
"-feature",
"-encoding", "UTF-8"
) ++ (if (scalaBinaryVersion.value == "3") Seq.empty else Seq(
"-Xlint",
"-Ywarn-dead-code",
"-encoding", "UTF-8"
),
)),

// show full stack traces in test failures
Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-oF"),
Expand All @@ -49,98 +53,141 @@ def commonProject(id: String, artifact: String, path: String): Project = {
Compile / packageDoc / publishArtifact := false,

// Don't publish the test artifacts, nobody should depend on these
Test / publishArtifact := false,
Test / publishArtifact := false
)
}

def scSuffix(scalaCheckVersion: String): String = scalaCheckVersion match {
case ScalaCheck_1_12 => "_1-12"
case ScalaCheck_1_13 => "_1-13"
case ScalaCheck_1_14 => "_1-14"
case ScalaCheck_1_15 => "_1-15"
}

def scalaVersions(scalaCheckVersion: String): Seq[String] = scalaCheckVersion match {
case ScalaCheck_1_12 => Seq(Scala_2_11)
case ScalaCheck_1_13 => Seq(Scala_2_11, Scala_2_12)
case ScalaCheck_1_14 => Seq(Scala_2_11, Scala_2_12, Scala_2_13)
case ScalaCheck_1_15 => Seq(Scala_2_11, Scala_2_12, Scala_2_13)
}

def coreProject(srcPath: File, testPath: File, scalaCheckVersion: String): Project = {
val suffix = scSuffix(scalaCheckVersion)
val targetPath = s"core$suffix"
commonProject(targetPath, s"scalacheck-ops$suffix", targetPath).settings(
scalaVersion := crossScalaVersions.value.head,
crossScalaVersions := scalaVersions(scalaCheckVersion),
Compile / sourceDirectory := (srcPath / "src" / "main").getAbsoluteFile,
Test / sourceDirectory := (testPath / "src" / "test").getAbsoluteFile,
scalacOptions ++= {
scalaVersion.value match {
case Scala_2_13 => Seq("-Ymacro-annotations")
case _ => Seq()
}
},
libraryDependencies ++= {
Seq(
izumiReflect,
scalaCheck(scalaCheckVersion),
tagging,
) ++ {
scalaVersion.value match {
case Scala_2_11 | Scala_2_12 => Seq(
compilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)
)
case _ => Seq()
}
}
} ++ {
// Test-only dependencies
Seq(
scalaTest(scalaCheckVersion),
newtype,
) ++ {
scalaCheckVersion match {
case ScalaCheck_1_12 | ScalaCheck_1_13 => Seq()
case ScalaCheck_1_14 | ScalaCheck_1_15 => Seq(
scalaTestPlusScalaCheck(scalaCheckVersion),
)
}

}
}.map(_ % Test)
)
}

lazy val `core_1-12` = coreProject(file("core_1-12"), file("core_1-12"), ScalaCheck_1_12)
lazy val `core_1-13` = coreProject(file("core"), file("core-1-13-test"), ScalaCheck_1_13)
lazy val `core_1-14` = coreProject(file("core"), file("core"), ScalaCheck_1_14)
lazy val `core_1-15` = coreProject(file("core"), file("core"), ScalaCheck_1_15)


def jodaProject(scalaCheckVersion: String): Project = {
val projectPath = "joda"
val suffix = scSuffix(scalaCheckVersion)
commonProject(s"joda$suffix", s"scalacheck-ops-joda$suffix", s"$projectPath$suffix").settings(
scalaVersion := crossScalaVersions.value.head,
crossScalaVersions := scalaVersions(scalaCheckVersion),
Compile / sourceDirectory := file(s"$projectPath/src/main").getAbsoluteFile,
Test / sourceDirectory := file(s"$projectPath/src/test").getAbsoluteFile,
// don't include dependencies that come from scalacheck-ops core project

lazy val `core` = projectMatrix
.settings(
// default locations, overridden in custom rows where needed
Compile / sourceDirectory := (file("core") / "src" / "main").getAbsoluteFile,
Test / sourceDirectory := (file("core") / "src" / "test").getAbsoluteFile,

scalacOptions ++= (scalaVersion.value match {
case Scala_2_13 => Seq("-Ymacro-annotations")
case _ => Seq()
}),

libraryDependencies ++= Seq(
jodaTime,
izumiReflect,
tagging,
newtype // Test-only
) ++ (scalaVersion.value match {
case Scala_2_11 | Scala_2_12 => Seq(
compilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)
)
case _ => Seq()
})
)
.customRow(
scalaVersions = Seq(Scala_2_11),
axisValues = Seq(ScalaCheckAxis.v1_12, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_12.artifact) ++ Seq(
coverageEnabled := false, // Scala 2.11
Compile / sourceDirectory := (file("core_1-12") / "src" / "main").getAbsoluteFile,
Test / sourceDirectory := (file("core_1-12") / "src" / "test").getAbsoluteFile,
libraryDependencies ++= Seq(
ScalaCheckAxis.v1_12.scalaCheck,
ScalaCheckAxis.v1_12.scalaTest
)
)
)
.customRow(
scalaVersions = Seq(Scala_2_11),
axisValues = Seq(ScalaCheckAxis.v1_13, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_13.artifact) ++ Seq(
coverageEnabled := false, // Scala 2.11
Test / sourceDirectory := (file("core-1-13-test") / "src" / "test").getAbsoluteFile,
libraryDependencies ++= Seq(
ScalaCheckAxis.v1_13.scalaCheck,
ScalaCheckAxis.v1_13.scalaTest
)
)
)
.customRow(
scalaVersions = Seq(Scala_2_12),
axisValues = Seq(ScalaCheckAxis.v1_13, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_13.artifact) ++ Seq(
Test / sourceDirectory := (file("core-1-13-test") / "src" / "test").getAbsoluteFile,
libraryDependencies ++= Seq(
ScalaCheckAxis.v1_13.scalaCheck,
ScalaCheckAxis.v1_13.scalaTest
)
)
)
.customRow(
scalaVersions = Seq(Scala_2_11),
axisValues = Seq(ScalaCheckAxis.v1_14, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_14.artifact) ++ Seq(
coverageEnabled := false, // Scala 2.11
libraryDependencies ++= Seq(
ScalaCheckAxis.v1_14.scalaCheck,
ScalaCheckAxis.v1_14.scalaTest,
ScalaCheckAxis.v1_14.scalaTestPlusScalaCheck(scalaVersion.value)
)
)
)
.customRow(
scalaVersions = Seq(Scala_2_12, Scala_2_13),
axisValues = Seq(ScalaCheckAxis.v1_14, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_14.artifact) ++ Seq(
libraryDependencies ++= Seq(
ScalaCheckAxis.v1_14.scalaCheck,
ScalaCheckAxis.v1_14.scalaTest,
ScalaCheckAxis.v1_14.scalaTestPlusScalaCheck(scalaVersion.value)
)
)
)
.customRow(
scalaVersions = Seq(Scala_2_12, Scala_2_13, Scala_3),
axisValues = Seq(ScalaCheckAxis.v1_15, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_15.artifact) ++ Seq(
libraryDependencies ++= Seq(
ScalaCheckAxis.v1_15.scalaCheck,
ScalaCheckAxis.v1_15.scalaTest,
ScalaCheckAxis.v1_15.scalaTestPlusScalaCheck(scalaVersion.value)
)
)
).dependsOn(
(scalaCheckVersion match {
case ScalaCheck_1_12 => `core_1-12`
case ScalaCheck_1_13 => `core_1-13`
case ScalaCheck_1_14 => `core_1-14`
case ScalaCheck_1_15 => `core_1-15`
}) % "compile;test->test"
)
}

lazy val `joda_1-12` = jodaProject(ScalaCheck_1_12)
lazy val `joda_1-13` = jodaProject(ScalaCheck_1_13)
lazy val `joda_1-14` = jodaProject(ScalaCheck_1_14)
lazy val `joda_1-15` = jodaProject(ScalaCheck_1_15)
lazy val `joda` = projectMatrix
.dependsOn(`core` % "compile;test->test")
.settings(
Compile / sourceDirectory := file(s"joda/src/main").getAbsoluteFile,
Test / sourceDirectory := file(s"joda/src/test").getAbsoluteFile,

// don't include dependencies that come from scalacheck-ops core project
libraryDependencies += jodaTime
)
.customRow(
scalaVersions = Seq(Scala_2_11),
axisValues = Seq(ScalaCheckAxis.v1_12, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_12.subArtifact("joda")) :+
(coverageEnabled := false) // Scala 2.11
)
.customRow(
scalaVersions = Seq(Scala_2_11),
axisValues = Seq(ScalaCheckAxis.v1_13, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_13.subArtifact("joda")) :+
(coverageEnabled := false) // Scala 2.11
)
.customRow(
scalaVersions = Seq(Scala_2_12),
axisValues = Seq(ScalaCheckAxis.v1_13, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_13.subArtifact("joda"))
)
.customRow(
scalaVersions = Seq(Scala_2_11),
axisValues = Seq(ScalaCheckAxis.v1_14, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_14.subArtifact("joda")) :+
(coverageEnabled := false) // Scala 2.11
)
.customRow(
scalaVersions = Seq(Scala_2_12, Scala_2_13),
axisValues = Seq(ScalaCheckAxis.v1_14, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_14.subArtifact("joda"))
)
.customRow(
scalaVersions = Seq(Scala_2_12, Scala_2_13, Scala_3),
axisValues = Seq(ScalaCheckAxis.v1_15, VirtualAxis.jvm),
settings = commonSettings(ScalaCheckAxis.v1_15.subArtifact("joda"))
)
4 changes: 2 additions & 2 deletions core/src/main/scala/org/scalacheck/ops/GenOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ object GenOps {
} map pf
}

def enumValue[E <: Enumeration](enum: E): Gen[enum.Value] =
Gen.oneOf[enum.Value](enum.values.toSeq)
def enumValue[E <: Enumeration](enumuration: E): Gen[enumuration.Value] =
Gen.oneOf[enumuration.Value](enumuration.values.toSeq)

def boolean: Gen[Boolean] = Gen.oneOf(true, false)

Expand Down
23 changes: 23 additions & 0 deletions core/src/test/scala-3/org/scalacheck/ops/ArbitraryAsGenSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.scalacheck.ops

import org.scalacheck.{Arbitrary, Gen}
import org.scalatest.freespec.AnyFreeSpec

class ArbitraryAsGenSpec extends AnyFreeSpec {

private val it = classOf[ArbitraryAsGen].getSimpleName

s"$it should implicitly convert a Gen to Arbitrary" in {
def f(arb: Arbitrary[Char]): Unit = ()
f(Gen.numChar)
}

private def implicitGen(implicit gen: Gen[Char]): Unit = ()

s"$it should convert an implicit Arbitrary to an implicit Gen" in {
/*
* Note this compiles in Scala 3, not Scala 2
*/
assertCompiles("implicitGen")
}
}
20 changes: 20 additions & 0 deletions core/src/test/scala-3/org/scalacheck/ops/NewtypeTypeNameSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.scalacheck.ops

import org.scalatest.freespec.AnyFreeSpec

class NewtypeTypeNameSpec extends AnyFreeSpec {
/*
* Note differences in type name emitted by Scala 3 vs. Scala 2
*/
"Find a TypeName of a newtype" in {
assertResult("org.scalacheck.ops.NewtypeExample$IdType") {
implicitly[TypeName[NewtypeExample.IdType]].typeName
}
}

"Find a TypeName of a newsubtype" in {
assertResult("org.scalacheck.ops.NewtypeExample$IdSubtype") {
implicitly[TypeName[NewtypeExample.IdSubtype]].typeName
}
}
}
4 changes: 2 additions & 2 deletions core/src/test/scala/org/scalacheck/ops/GenOpsSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ class GenOpsSpec extends AnyFlatSpec {
behavior of "Gen.enumValue"

it should "create a generator from an Enumeration" in {
forAll(Gen.enumValue(TestValues)) { enum =>
forAll(Gen.enumValue(TestValues)) { (enumeration: TestValues.Value) =>
// Should be of the expected type
assert(enum == TestValues.withName(enum.toString))
assert(enumeration == TestValues.withName(enumeration.toString))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class SeedExtractorSpec extends AnyFreeSpec {

"verify this test catches collisions" in {
implicit val collisionProneSeedExtractor: SeedExtractor[Int] = SeedExtractor.fromLong(_ % 2)
forAll(Gen.listOfN(1000, arbitrary[Int]), collisionCheckParams: _*) { ints: Seq[Int] =>
forAll(Gen.listOfN(1000, arbitrary[Int]), collisionCheckParams: _*) { (ints: Seq[Int]) =>
whenever(ints.nonEmpty) {
val collisions = groupCollisions(ints)
assert(collisions.nonEmpty)
Expand All @@ -45,13 +45,13 @@ class SeedExtractorSpec extends AnyFreeSpec {
val typeName = classTag[A].runtimeClass.getSimpleName

s"$it[$typeName]$suffix should extract a consistent seed" in {
forAll { a: A =>
forAll { (a: A) =>
assert(extractor.seed(a) == extractor.seed(a))
}
}

s"$it[$typeName]$suffix should avoid collisions" in {
forAll(Gen.listOfN(1000, arbitrary[A]), collisionCheckParams: _*) { as: Seq[A] =>
forAll(Gen.listOfN(1000, arbitrary[A]), collisionCheckParams: _*) { (as: Seq[A]) =>
val collisions = groupCollisions(as)
collisions should have size 0
}
Expand Down
Loading

0 comments on commit 8d53310

Please sign in to comment.