diff --git a/build.sbt b/build.sbt index acf2e78a..359c5e20 100644 --- a/build.sbt +++ b/build.sbt @@ -8,7 +8,7 @@ def scala213 = "2.13.13" def scala212 = "2.12.19" -def scala3 = "3.1.2" +def scala3 = "3.3.3" def junitVersion = "4.13.2" def gcp = "com.google.cloud" % "google-cloud-storage" % "2.32.1" inThisBuild( @@ -154,7 +154,16 @@ val sharedJVMSettings: List[Def.Setting[_]] = List( val sharedJSSettings: List[Def.Setting[_]] = List( skipIdeaSettings, - crossScalaVersions := allScalaVersions.filterNot(_.startsWith("0.")) + crossScalaVersions := allScalaVersions.filterNot(_.startsWith("0.")), + scalacOptions ++= { + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, _)) => + List( + "-P:scalajs:nowarnGlobalExecutionContext", + ) + case _ => Nil + } + } ) val sharedJSConfigure: Project => Project = _.disablePlugins(MimaPlugin) @@ -176,17 +185,40 @@ val sharedSettings = List( "-Ywarn-unused-import", "-target:jvm-1.8" ) - case Some((major, _)) if major != 2 => + case Some((2, 12)) => List( - "-language:implicitConversions" + "-feature", + "-target:jvm-1.8", + "-Ywarn-unused-import", + "-Yrangepos" + ) + case Some((2, _)) => + List( + "-deprecation", // enable deprecation first because it sets -Wconf:cat=deprecation:w + "-feature", + "--release:8", + "-unchecked", + "-Wconf:cat=deprecation&origin=scala.collection.JavaConverters:s", + "-Wconf:cat=deprecation&origin=scala.reflect.api.Trees.New:s", // no quasiquotes + "-Wconf:cat=deprecation&origin=scala.reflect.api.Position.lineContent:s", // use it anyway + "-Wconf:msg=parameter:s", // quash other messages about unused parameters + "-Wunused:params", + //"-Wconf:cat=unused-privates&msg=never used:s", + //"-Wconf:cat=unused-params&msg=never used:s", + //"-Werror", + "-Xlint:-deprecation,_", + "-Yrangepos", // default ) case _ => List( - "-target:jvm-1.8", - "-Yrangepos", - // -Xlint is unusable because of - // https://github.com/scala/bug/issues/10448 - "-Ywarn-unused:imports" + "-deprecation", + "-feature", + "-java-output-version:8", + "-Wconf:cat=deprecation&msg=Converters:s", + "-Wconf:cat=deprecation&msg=New:s", // no quasiquotes + "-Wconf:cat=deprecation&msg=Position:s", + //"-Wunused:all", + //"-language:implicitConversions" ) } } diff --git a/docs/tests.md b/docs/tests.md index eaa2651a..45cf768b 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -237,7 +237,7 @@ def check[T]( check("basic", List(1, 2), Some(1)) check("empty", List(), Some(1)) -check("null", List(null, 2), Some(null)) +check("null", List(null, "more"), Some(null)) ``` When declaring tests in a helper function, it's useful to pass around an diff --git a/munit-scalacheck/shared/src/main/scala/munit/ScalaCheckSuite.scala b/munit-scalacheck/shared/src/main/scala/munit/ScalaCheckSuite.scala index 0efa550b..a7a07dd2 100644 --- a/munit-scalacheck/shared/src/main/scala/munit/ScalaCheckSuite.scala +++ b/munit-scalacheck/shared/src/main/scala/munit/ScalaCheckSuite.scala @@ -1,9 +1,12 @@ package munit +import language.implicitConversions + import org.scalacheck.Prop import org.scalacheck.{Test => ScalaCheckTest} import org.scalacheck.util.Pretty import org.scalacheck.rng.Seed +import scala.annotation.nowarn import scala.util.Success import scala.util.Failure import scala.util.Try @@ -25,6 +28,7 @@ trait ScalaCheckSuite extends FunSuite { // Allow property bodies of type Unit // This is done to support using MUnit assertions in property bodies // instead of returning a Boolean. + @nowarn("msg=used") implicit def unitToProp(unit: Unit): Prop = Prop.passed override def munitTestTransforms: List[TestTransform] = diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala index a65fdefc..7a26d33f 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala @@ -7,6 +7,7 @@ package munit.internal.junitinterface import munit.internal.console.AnsiColors import sbt.testing._ import munit.internal.PlatformCompat +import scala.annotation.nowarn final class JUnitReporter( eventHandler: EventHandler, @@ -35,6 +36,7 @@ final class JUnitReporter( } emitEvent(method, Status.Ignored) } + @nowarn("msg=used") def reportAssumptionViolation( method: String, timeInSeconds: Double, @@ -219,6 +221,7 @@ final class JUnitReporter( .map(_.getFileName) .orNull + @nowarn("msg=used") private def stackTraceElementToString( e: StackTraceElement, testFileName: String diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala index 59cef135..94a13cff 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala @@ -6,7 +6,9 @@ package munit.internal.junitinterface import sbt.testing._ import munit.internal.PlatformCompat +import scala.annotation.nowarn +@nowarn("msg=used") final class JUnitRunner( val args: Array[String], _remoteArgs: Array[String], diff --git a/munit/js-native/src/main/scala/org/junit/experimental/categories/Category.scala b/munit/js-native/src/main/scala/org/junit/experimental/categories/Category.scala index ef674c8c..1b2b27fd 100644 --- a/munit/js-native/src/main/scala/org/junit/experimental/categories/Category.scala +++ b/munit/js-native/src/main/scala/org/junit/experimental/categories/Category.scala @@ -1,5 +1,7 @@ package org.junit.experimental.categories import scala.annotation.Annotation +import scala.annotation.nowarn +@nowarn("msg=used") class Category(classes: Array[Class[_]]) extends Annotation diff --git a/munit/js-native/src/main/scala/org/junit/runner/RunWith.scala b/munit/js-native/src/main/scala/org/junit/runner/RunWith.scala index 26c8bd84..77d908f5 100644 --- a/munit/js-native/src/main/scala/org/junit/runner/RunWith.scala +++ b/munit/js-native/src/main/scala/org/junit/runner/RunWith.scala @@ -1,5 +1,7 @@ package org.junit.runner import scala.annotation.Annotation +import scala.annotation.nowarn +@nowarn("msg=used") class RunWith(cls: Class[_]) extends Annotation diff --git a/munit/js/src/main/scala/munit/internal/PlatformCompat.scala b/munit/js/src/main/scala/munit/internal/PlatformCompat.scala index b5ed7e24..8ad9ba36 100644 --- a/munit/js/src/main/scala/munit/internal/PlatformCompat.scala +++ b/munit/js/src/main/scala/munit/internal/PlatformCompat.scala @@ -3,10 +3,11 @@ package munit.internal import scala.scalajs.reflect.Reflect import sbt.testing.TaskDef import munit.MUnitRunner -import scala.concurrent.Future import sbt.testing.Task import sbt.testing.EventHandler import sbt.testing.Logger +import scala.annotation.nowarn +import scala.concurrent.Future import scala.concurrent.Promise import scala.concurrent.duration.Duration import scala.concurrent.Await @@ -36,7 +37,7 @@ object PlatformCompat { ec: ExecutionContext ): Future[T] = { val onComplete = Promise[T]() - val timeoutHandle = timers.setTimeout(duration.toMillis) { + val timeoutHandle = timers.setTimeout(duration.toMillis.toDouble) { onComplete.tryFailure( new TimeoutException(s"test timed out after $duration") ) @@ -65,6 +66,7 @@ object PlatformCompat { def isJS: Boolean = true def isNative: Boolean = false + @nowarn("msg=used") def newRunner( taskDef: TaskDef, classLoader: ClassLoader diff --git a/munit/native/src/main/scala/munit/internal/PlatformCompat.scala b/munit/native/src/main/scala/munit/internal/PlatformCompat.scala index 9ddbd8e3..e6b1f481 100644 --- a/munit/native/src/main/scala/munit/internal/PlatformCompat.scala +++ b/munit/native/src/main/scala/munit/internal/PlatformCompat.scala @@ -7,6 +7,7 @@ import scala.scalanative.reflect.Reflect import sbt.testing.Task import sbt.testing.EventHandler import sbt.testing.Logger +import scala.annotation.nowarn import scala.concurrent.Await import scala.concurrent.Awaitable import scala.concurrent.duration.Duration @@ -26,6 +27,7 @@ object PlatformCompat { task.execute(eventHandler, loggers) Future.successful(()) } + @nowarn("msg=used") def waitAtMost[T]( startFuture: () => Future[T], duration: Duration, @@ -47,6 +49,7 @@ object PlatformCompat { def isJS: Boolean = false def isNative: Boolean = true + @nowarn("msg=used") def newRunner( taskDef: TaskDef, classLoader: ClassLoader diff --git a/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala b/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala index 791ae277..5b50b959 100644 --- a/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala +++ b/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala @@ -7,7 +7,6 @@ package munit.internal.junitinterface import munit.internal.PlatformCompat import org.junit.runner.notification.RunNotifier import sbt.testing._ -import scala.concurrent.ExecutionContext.Implicits.global /* Implementation note: In JUnitTask we use Future[Try[Unit]] instead of simply * Future[Unit]. This is to prevent Scala's Future implementation to box/wrap diff --git a/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala b/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala index e0606348..29cd3dac 100644 --- a/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala +++ b/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala @@ -1,5 +1,7 @@ package munit.internal +import language.reflectiveCalls + object Compat { type LazyList[+T] = scala.LazyList[T] val LazyList = scala.LazyList diff --git a/munit/shared/src/main/scala-2/munit/internal/MacroCompat.scala b/munit/shared/src/main/scala-2/munit/internal/MacroCompat.scala index 594abdb7..eb81e0f1 100644 --- a/munit/shared/src/main/scala-2/munit/internal/MacroCompat.scala +++ b/munit/shared/src/main/scala-2/munit/internal/MacroCompat.scala @@ -2,6 +2,7 @@ package munit.internal import munit.Clue import munit.Location +import scala.language.implicitConversions import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context diff --git a/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala b/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala index 721cf52b..8b5a4668 100644 --- a/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala +++ b/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala @@ -4,6 +4,7 @@ import munit.Clue import munit.Location import scala.quoted._ import scala.language.experimental.macros +import scala.language.implicitConversions object MacroCompat { @@ -15,7 +16,7 @@ object MacroCompat { def locationImpl()(using Quotes): Expr[Location] = { import quotes.reflect._ val pos = Position.ofMacroExpansion - val path = pos.sourceFile.jpath.toString + val path = pos.sourceFile.path val startLine = pos.startLine + 1 '{ new Location(${ Expr(path) }, ${ Expr(startLine) }) } } diff --git a/munit/shared/src/main/scala/munit/Assertions.scala b/munit/shared/src/main/scala/munit/Assertions.scala index fea92e7a..cec77f8b 100644 --- a/munit/shared/src/main/scala/munit/Assertions.scala +++ b/munit/shared/src/main/scala/munit/Assertions.scala @@ -4,9 +4,10 @@ import munit.internal.console.{Lines, Printers, StackTraces} import munit.internal.difflib.ComparisonFailExceptionHandler import munit.internal.difflib.Diffs +import scala.annotation.nowarn +import scala.collection.mutable import scala.reflect.ClassTag import scala.util.control.NonFatal -import scala.collection.mutable import munit.internal.console.AnsiColors import org.junit.AssumptionViolatedException import munit.internal.MacroCompat @@ -37,7 +38,7 @@ trait Assertions extends MacroCompat.CompileErrorMacro { def assume( cond: Boolean, clue: => Any = "assumption failed" - )(implicit loc: Location): Unit = { + )(implicit @nowarn loc: Location): Unit = { StackTraces.dropInside { if (!cond) { throw new AssumptionViolatedException(munitPrint(clue)) @@ -95,7 +96,7 @@ trait Assertions extends MacroCompat.CompileErrorMacro { StackTraces.dropInside { if (!compare.isEqual(obtained, expected)) { (obtained, expected) match { - case (a: Array[_], b: Array[_]) if a.sameElements(b) => + case (a: Array[_], b: Array[_]) if a.sameElements[Any](b) => // Special-case error message when comparing arrays. See // https://github.com/scalameta/munit/pull/393 and // https://github.com/scalameta/munit/issues/339 for a related diff --git a/munit/shared/src/main/scala/munit/MUnitRunner.scala b/munit/shared/src/main/scala/munit/MUnitRunner.scala index 348d79b3..c997b4f5 100644 --- a/munit/shared/src/main/scala/munit/MUnitRunner.scala +++ b/munit/shared/src/main/scala/munit/MUnitRunner.scala @@ -15,6 +15,7 @@ import org.junit.runner.notification.Failure import org.junit.runner.notification.RunNotifier import java.lang.reflect.Modifier +import scala.annotation.nowarn import scala.collection.mutable import scala.concurrent.ExecutionContext import scala.concurrent.Future @@ -29,7 +30,7 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) with Configurable { def this(cls: Class[_ <: Suite]) = - this(MUnitRunner.ensureEligibleConstructor(cls), () => cls.newInstance()) + this(MUnitRunner.ensureEligibleConstructor(cls), () => cls.getDeclaredConstructor().newInstance()) val suite: Suite = newInstance() @@ -92,7 +93,7 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) val desc = Description.createTestDescription( cls, testName, - test.annotations: _* + test.annotations.toIndexedSeq: _* ) desc } @@ -168,6 +169,7 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) loop(futures, mutable.ListBuffer.empty) } + @nowarn private def munitTimeout(): Option[Duration] = { suite match { case funSuite: FunSuite => Some(funSuite.munitTimeout) @@ -245,7 +247,6 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) test: Test ): Future[BeforeAllResult] = { val context = new BeforeEach(test) - val fixtures = mutable.ListBuffer.empty[AnyFixture[_]] sequenceFutures( munitFixtures.iterator.map(f => valueTransform(() => f.beforeEach(context)).map(_ => f) diff --git a/munit/shared/src/main/scala/munit/TestOptions.scala b/munit/shared/src/main/scala/munit/TestOptions.scala index 6b958133..d2243bf8 100644 --- a/munit/shared/src/main/scala/munit/TestOptions.scala +++ b/munit/shared/src/main/scala/munit/TestOptions.scala @@ -46,6 +46,8 @@ object TestOptions extends TestOptionsConversions { trait TestOptionsConversions { + import language.implicitConversions + /** * Implicitly create a TestOptions given a test name. * This allows writing `test("name") { ... }` even if `test` accepts a `TestOptions` diff --git a/munit/shared/src/main/scala/munit/ValueTransforms.scala b/munit/shared/src/main/scala/munit/ValueTransforms.scala index d6a3bea2..6e57659b 100644 --- a/munit/shared/src/main/scala/munit/ValueTransforms.scala +++ b/munit/shared/src/main/scala/munit/ValueTransforms.scala @@ -26,7 +26,7 @@ trait ValueTransforms { this: BaseFunSuite => val nested: Future[Future[Any]] = future.map { value => val transformed = munitValueTransforms.iterator .map(fn => fn(value)) - .collectFirst { case Some(future) => future } + .collectFirst { case Some(f) => f } transformed match { case Some(f) => flattenFuture(f) case None => Future.successful(value) diff --git a/munit/shared/src/main/scala/munit/internal/FutureCompat.scala b/munit/shared/src/main/scala/munit/internal/FutureCompat.scala index 1581f51e..3c4fbcd0 100644 --- a/munit/shared/src/main/scala/munit/internal/FutureCompat.scala +++ b/munit/shared/src/main/scala/munit/internal/FutureCompat.scala @@ -1,8 +1,8 @@ package munit.internal +import scala.concurrent.ExecutionContext import scala.concurrent.Future import scala.util.Try -import scala.concurrent.ExecutionContext object FutureCompat { implicit class ExtensionFuture[T](f: Future[T]) { diff --git a/munit/shared/src/main/scala/munit/internal/difflib/Diffs.scala b/munit/shared/src/main/scala/munit/internal/difflib/Diffs.scala index a8c983dd..e17e1123 100644 --- a/munit/shared/src/main/scala/munit/internal/difflib/Diffs.scala +++ b/munit/shared/src/main/scala/munit/internal/difflib/Diffs.scala @@ -7,7 +7,7 @@ object Diffs { def create(obtained: String, expected: String): Diff = new Diff(obtained, expected) - @deprecated("") + @deprecated("", since="") def assertNoDiff( obtained: String, expected: String, diff --git a/munit/shared/src/main/scala/munit/internal/difflib/Equalizer.scala b/munit/shared/src/main/scala/munit/internal/difflib/Equalizer.scala index 4c5037b5..623612af 100644 --- a/munit/shared/src/main/scala/munit/internal/difflib/Equalizer.scala +++ b/munit/shared/src/main/scala/munit/internal/difflib/Equalizer.scala @@ -6,7 +6,7 @@ trait Equalizer[T] { object Equalizer { def default[T]: Equalizer[T] = new Equalizer[T] { override def equals(original: T, revised: T): Boolean = { - original.equals(revised) + original == revised //original.equals(revised) } } } diff --git a/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala b/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala index c6eda50b..a1fedd9d 100644 --- a/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala +++ b/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala @@ -4,7 +4,7 @@ import scala.concurrent.Future import scala.concurrent.Promise class AsyncFunFixtureOrderSuite extends FunSuite { - val latch: Promise[Unit] = Promise[Unit] + val latch: Promise[Unit] = Promise[Unit]() var completedFromTest: Option[Boolean] = None var completedFromTeardown: Option[Boolean] = None diff --git a/tests/shared/src/test/scala/munit/PrintersSuite.scala b/tests/shared/src/test/scala/munit/PrintersSuite.scala index 4a692af4..7e02abd2 100644 --- a/tests/shared/src/test/scala/munit/PrintersSuite.scala +++ b/tests/shared/src/test/scala/munit/PrintersSuite.scala @@ -63,7 +63,7 @@ class PrintersSuite extends FunSuite { self => check( "list", - List(1, 2, 3, List(4, 5, List(6, 7))), + List[Any](1, 2, 3, List[Any](4, 5, List(6, 7))), """|List( | 1, | 2,