diff --git a/project/Jdk9.scala b/project/Jdk9.scala index 12275d13bc..776ed1052b 100644 --- a/project/Jdk9.scala +++ b/project/Jdk9.scala @@ -53,16 +53,21 @@ object Jdk9 extends AutoPlugin { yield (task / sourceDirectory).value / sourceDirectoryName } + private def releaseOption(scalaVer: String): Seq[String] = { + if (JdkOptions.isScala3_8Plus(scalaVer)) Seq("-java-output-version", majorVersion.toString) + else Seq("-release", majorVersion.toString) + } + lazy val compileJdk9Settings = Seq( // following the scala-2.12, scala-sbt-1.0, ... convention unmanagedSourceDirectories := additionalSourceDirectories.value, - scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ Seq("-release", majorVersion.toString), + scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ releaseOption(scalaVersion.value), javacOptions := PekkoBuild.DefaultJavacOptions ++ Seq("--release", majorVersion.toString)) lazy val testJdk9Settings = Seq( // following the scala-2.12, scala-sbt-1.0, ... convention unmanagedSourceDirectories := additionalTestSourceDirectories.value, - scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ Seq("-release", majorVersion.toString), + scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ releaseOption(scalaVersion.value), javacOptions := PekkoBuild.DefaultJavacOptions ++ Seq("--release", majorVersion.toString), compile := compile.dependsOn(CompileJdk9 / compile).value, classpathConfiguration := TestJdk9, diff --git a/project/JdkOptions.scala b/project/JdkOptions.scala index 99291c99e1..1d16dd4667 100644 --- a/project/JdkOptions.scala +++ b/project/JdkOptions.scala @@ -35,10 +35,23 @@ object JdkOptions extends AutoPlugin { // for LevelDB "--add-opens=java.base/java.nio=ALL-UNNAMED" :: Nil - def targetJdkScalacOptions(scalaVersion: String): Seq[String] = - Seq("-release", JdkOptions.targetJavaVersion) ++ { - if (scalaVersion.startsWith("3.")) Seq(s"-Xtarget:${targetJavaVersion}") else Seq.empty + def isScala3_8Plus(scalaVersion: String): Boolean = + scalaVersion.startsWith("3.") && { + val parts = scalaVersion.split('.') + def safeToInt(s: String): Int = try { s.split('-').head.toInt } + catch { case _: NumberFormatException => 0 } + parts.length >= 2 && (safeToInt(parts(1)) >= 8 || safeToInt(parts(0)) > 3) } + def targetJdkScalacOptions(scalaVersion: String): Seq[String] = { + if (isScala3_8Plus(scalaVersion)) { + Seq("-java-output-version", JdkOptions.targetJavaVersion) + } else { + Seq("-release", JdkOptions.targetJavaVersion) ++ { + if (scalaVersion.startsWith("3.")) Seq(s"-Xtarget:${targetJavaVersion}") else Seq.empty + } + } + } + val targetJdkJavacOptions = Seq("--release", targetJavaVersion) } diff --git a/project/PekkoDisciplinePlugin.scala b/project/PekkoDisciplinePlugin.scala index 48212954c2..aa9990bcee 100644 --- a/project/PekkoDisciplinePlugin.scala +++ b/project/PekkoDisciplinePlugin.scala @@ -74,21 +74,31 @@ object PekkoDisciplinePlugin extends AutoPlugin { "pekko-stream-tests-tck", "pekko-testkit") + private val scala3Suppressions = Seq( + "-Wconf:msg=Implicit parameters should be provided with a .using. clause:s", + "-Wconf:msg=is no longer supported for vararg splices:s", + "-Wconf:msg=with as a type operator has been deprecated:s", + "-Wconf:msg=SerialVersionUID does nothing on a trait:s", + "-Wconf:msg=has been deprecated.*use .= uninitialized. instead:s", + "-Wconf:msg=trailing.*_.*for eta-expansion is unnecessary:s", + "-Wconf:msg=is not declared infix:s", + "-Wconf:msg=._. is deprecated for wildcard arguments of types:s", + "-Wconf:msg=Ignoring ..this.. qualifier:s", + "-Wconf:msg=Unreachable case except for null:s", + "-Wconf:msg=Classic remoting is deprecated:s", + "-Wconf:msg=Use EventSourcedBehavior:s", + "-Wconf:msg=migration-to-pekko-grpc:s") + lazy val defaultScalaOptions = Def.setting(CrossVersion.partialVersion(scalaVersion.value).get match { - case (3, _) => "-Wconf:cat=unused-nowarn:s,cat=other-shadowing:s,any:e" - case (2, 13) => "-Wconf:any:e,cat=unused-nowarn:s,cat=other-shadowing:s" - case (2, 12) => "-Wconf:cat=unused-nowarn:s,any:e" + case (3, _) => Seq("-Wconf:any:e", "-Wconf:cat=unused-nowarn:s", "-Wconf:cat=other-shadowing:s") ++ + scala3Suppressions + case (2, 13) => Seq("-Wconf:any:e", "-Wconf:cat=unused-nowarn:s", "-Wconf:cat=other-shadowing:s") + case (2, 12) => Seq("-Wconf:cat=unused-nowarn:s", "-Wconf:any:e") }) lazy val nowarnSettings = Seq( - Compile / scalacOptions ++= ( - if (scalaVersion.value.startsWith("3.")) Nil - else Seq(defaultScalaOptions.value) - ), - Test / scalacOptions ++= ( - if (scalaVersion.value.startsWith("3.")) Nil - else Seq(defaultScalaOptions.value) - ), + Compile / scalacOptions ++= defaultScalaOptions.value, + Test / scalacOptions ++= defaultScalaOptions.value, Compile / doc / scalacOptions := Seq()) // ignore Scala compile warnings for Java 20+ @@ -96,25 +106,46 @@ object PekkoDisciplinePlugin extends AutoPlugin { System.getProperty("java.version").startsWith("2") } + private val scala3DocSuppressions = Seq( + "-Wconf:cat=unused:s", + "-Wconf:cat=deprecation:s", + "-Wconf:cat=unchecked:s") ++ scala3Suppressions + + // cat=unused:s does not match subcategories (unused-imports, unused-locals, etc.) + // in Scala 2.13's -Wconf category matching (exact string match, not hierarchical). + // Add explicit rules for each subcategory plus message-based patterns as fallback. + private val docsScala2Suppressions = Seq( + "-Wconf:cat=unused:s", + "-Wconf:cat=unused-imports:s", + "-Wconf:cat=unused-locals:s", + "-Wconf:cat=unused-pat-vars:s", + "-Wconf:cat=unused-params:s", + "-Wconf:cat=unused-privates:s", + "-Wconf:cat=unused-explicits:s", + "-Wconf:msg=Unused import:s", + "-Wconf:msg=is never used:s", + "-Wconf:cat=deprecation:s", + "-Wconf:cat=unchecked:s") + /** * We are a little less strict in docs */ lazy val docs = Seq( - Compile / scalacOptions -= defaultScalaOptions.value, + Compile / scalacOptions --= defaultScalaOptions.value, Compile / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value).get match { - case (3, _) => Nil - case (2, 13) => Seq("-Wconf:any:e,cat=unused:s,cat=deprecation:s,cat=unchecked:s") - case (2, 12) => Seq("-Wconf:cat=unused:s,cat=deprecation:s,cat=unchecked:s,any:e") + case (3, _) => scala3DocSuppressions + case (2, 13) => docsScala2Suppressions + case (2, 12) => docsScala2Suppressions :+ "-Wconf:any:e" }), Test / scalacOptions --= Seq("-Xlint", "-unchecked", "-deprecation"), - Test / scalacOptions -= defaultScalaOptions.value, + Test / scalacOptions --= defaultScalaOptions.value, Test / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value).get match { - case (3, _) => Nil - case (2, 13) => Seq("-Wconf:any:e,cat=unused:s,cat=deprecation:s,cat=unchecked:s") - case (2, 12) => Seq("-Wconf:cat=unused:s,cat=deprecation:s,cat=unchecked:s,any:e") + case (3, _) => scala3DocSuppressions + case (2, 13) => "-Wconf:any:e" +: docsScala2Suppressions + case (2, 12) => docsScala2Suppressions :+ "-Wconf:any:e" }), Compile / doc / scalacOptions := Seq()) diff --git a/project/SbtMultiJvmPlugin.scala b/project/SbtMultiJvmPlugin.scala index 01c484f986..c49f915c0d 100644 --- a/project/SbtMultiJvmPlugin.scala +++ b/project/SbtMultiJvmPlugin.scala @@ -84,14 +84,14 @@ object MultiJvmPlugin extends AutoPlugin { override lazy val projectSettings = multiJvmSettings - private[this] def noTestsMessage(scoped: ScopedKey[?])(implicit display: Show[ScopedKey[?]]): String = + private def noTestsMessage(scoped: ScopedKey[?])(implicit display: Show[ScopedKey[?]]): String = "No tests to run for " + display.show(scoped) lazy val multiJvmSettings: Seq[Def.Setting[?]] = inConfig(MultiJvm)(Defaults.configSettings ++ internalMultiJvmSettings) // https://github.com/sbt/sbt/blob/v0.13.15/main/actions/src/main/scala/sbt/Tests.scala#L296-L298 - private[this] def showResults(log: Logger, results: Tests.Output, noTestsMessage: => String): Unit = + private def showResults(log: Logger, results: Tests.Output, noTestsMessage: => String): Unit = TestResultLogger.Default.copy(printNoTests = TestResultLogger.const(_.info(noTestsMessage))).run(log, results, "") private def internalMultiJvmSettings =