diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c2469cddcb..4733497509d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,6 +106,10 @@ jobs: command: sbt javapc/test name: Scala javapc tests os: ubuntu-latest + - type: cross-test-nightly + command: sbt cross-test-latest-nightly + name: Scala3 latest NIGHTLY cross test + os: ubuntu-latest - type: scalafix command: sbt scalafixCheck docs/docusaurusCreateSite name: Scalafix and docs diff --git a/build.sbt b/build.sbt index e3f90d5fdcb..eba71a3d245 100644 --- a/build.sbt +++ b/build.sbt @@ -17,18 +17,26 @@ def isScala212(v: Option[(Long, Long)]): Boolean = v.contains((2, 12)) def isScala213(v: Option[(Long, Long)]): Boolean = v.contains((2, 13)) def isScala2(v: Option[(Long, Long)]): Boolean = v.exists(_._1 == 2) def isScala3(v: Option[(Long, Long)]): Boolean = v.exists(_._1 == 3) +def isScala3WithPresentationCompiler(v: String): Boolean = + (DottyVersion.parse(v), DottyVersion.parse(V.firstScala3PCVersion)) match { + case (Some(v), Some(firstScala3PCVersion)) => v >= firstScala3PCVersion + case _ => false + } def crossSetting[A]( scalaVersion: String, if211: List[A] = Nil, if213: List[A] = Nil, if3: List[A] = Nil, + if3WithPresentationCompiler: List[A] = Nil, if2: List[A] = Nil, ): List[A] = CrossVersion.partialVersion(scalaVersion) match { case partialVersion if isScala211(partialVersion) => if211 ::: if2 case partialVersion if isScala212(partialVersion) => if2 case partialVersion if isScala213(partialVersion) => if2 ::: if213 + case _ if isScala3WithPresentationCompiler(scalaVersion) => + if3WithPresentationCompiler case partialVersion if isScala3(partialVersion) => if3 case _ => Nil } @@ -97,11 +105,12 @@ def configureMtagsScalaVersionDynamically( ): State = { val scalaVersionSettings = List( - mtest / scalaVersion := scalaV, mtagsShared / scalaVersion := scalaV, + mtest / scalaVersion := scalaV, mtags / scalaVersion := scalaV, cross / scalaVersion := scalaV, ) + val extracted = Project.extract(state) extracted .appendWithSession( @@ -242,9 +251,10 @@ lazy val mtagsShared = project .settings( moduleName := "mtags-shared", crossTarget := target.value / s"scala-${scalaVersion.value}", - crossScalaVersions := { - V.supportedScalaVersions ++ V.nightlyScala3Versions - }, + // Dotty depends on Scala 2.13 for compatibility guarantees for from-source compilation. + crossScalaVersions := + (V.supportedScalaVersions ++ V.nightlyScala3Versions) + .filterNot(isScala3WithPresentationCompiler), crossVersion := CrossVersion.full, Compile / packageSrc / publishArtifact := true, libraryDependencies ++= List( @@ -272,10 +282,24 @@ def multiScalaDirectories(root: File, scalaVersion: String) = { result.toList } +def scala3ScalametaDependency = + ("org.scalameta" %% "scalameta" % V.scalameta) + .cross(CrossVersion.for3Use2_13) + .exclude("org.scala-lang", "scala-reflect") + .exclude("org.scala-lang", "scala-compiler") + // the correct one should be brought in by the scala 3 compiler + .exclude("org.scala-lang", "scala-library") + .exclude( + "com.lihaoyi", + "geny_2.13", + ) // avoid 2.13 and 3 on the classpath since we rely on it directly + .exclude( + "com.lihaoyi", + "sourcecode_2.13", + ) // avoid 2.13 and 3 on the classpath since it comes in via pprint + val mtagsSettings = List( - crossScalaVersions := { - V.supportedScalaVersions ++ V.nightlyScala3Versions - }, + crossScalaVersions := V.supportedScalaVersions ++ V.nightlyScala3Versions, crossTarget := target.value / s"scala-${scalaVersion.value}", crossVersion := CrossVersion.full, Compile / unmanagedSourceDirectories ++= multiScalaDirectories( @@ -291,40 +315,30 @@ val mtagsSettings = List( "org.jsoup" % "jsoup" % V.jsoup, // for extracting HTML from javadocs // for ivy completions "io.get-coursier" % "interface" % V.coursierInterfaces, + "org.lz4" % "lz4-java" % "1.8.0", ), - libraryDependencies ++= crossSetting( - scalaVersion.value, - if2 = List( - // for token edit-distance used by goto definition - "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0", - "org.scalameta" % "semanticdb-scalac-core" % V.scalameta cross CrossVersion.full, - ), - if3 = List( - "org.scala-lang" %% "scala3-compiler" % scalaVersion.value, - ("org.scalameta" %% "scalameta" % V.scalameta) - .cross(CrossVersion.for3Use2_13) - .exclude("org.scala-lang", "scala-reflect") - .exclude("org.scala-lang", "scala-compiler") - // the correct one should be brought in by the scala 3 compiler - .exclude("org.scala-lang", "scala-library") - .exclude( - "com.lihaoyi", - "geny_2.13", - ) // avoid 2.13 and 3 on the classpath since we rely on it directly - .exclude( - "com.lihaoyi", - "sourcecode_2.13", - ), // avoid 2.13 and 3 on the classpath since it comes in via pprint + libraryDependencies ++= { + crossSetting( + scalaVersion.value, + if2 = List( + // for token edit-distance used by goto definition + "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0", + "org.scalameta" % "semanticdb-scalac-core" % V.scalameta cross CrossVersion.full, + ), + if3 = List( + "org.scala-lang" %% "scala3-compiler" % scalaVersion.value, + scala3ScalametaDependency, + ), + if3WithPresentationCompiler = List( + "org.scala-lang" %% "scala3-presentation-compiler" % scalaVersion.value + ), ), - ), - libraryDependencies ++= List("org.lz4" % "lz4-java" % "1.8.0"), + }, libraryDependencies ++= { if (isCI) Nil // NOTE(olafur) pprint is indispensable for me while developing, I can't // use println anymore for debugging because pprint.log is 100 times better. - else { - List("com.lihaoyi" %% "pprint" % V.pprint) - } + else List("com.lihaoyi" %% "pprint" % V.pprint) }, buildInfoPackage := "scala.meta.internal.mtags", buildInfoKeys := Seq[BuildInfoKey]( @@ -339,6 +353,8 @@ val mtagsSettings = List( val scalaVersionsWithSpecialCompat = Set("2.13.9", "2.13.10", "2.13.11") if (scalaVersionsWithSpecialCompat(scalaVersion.value)) current.filter(f => f.getName() != "scala-2.13") + else if (isScala3WithPresentationCompiler(scalaVersion.value)) + List(base / s"scala-3-wrapper") else current }, @@ -364,11 +380,35 @@ lazy val mtags3 = project .dependsOn(interfaces) .enablePlugins(BuildInfoPlugin) +lazy val mtags3WithPresentationCompiler = project + .in(file(".mtags")) + .settings( + Compile / unmanagedSourceDirectories := Seq(), + sharedSettings, + mtagsSettings, + Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags" / "src" / "main" / "scala-3-wrapper", + moduleName := "mtags3WithPresentationCompiler", + scalaVersion := V.firstScala3PCVersion, + target := (ThisBuild / baseDirectory).value / "mtags" / "target" / "target3-wrapper", + publish / skip := true, + scalafixConfig := Some( + (ThisBuild / baseDirectory).value / ".scalafix3.conf" + ), + ) + .dependsOn(interfaces) + .enablePlugins(BuildInfoPlugin) + lazy val mtags = project .settings( sharedSettings, mtagsSettings, moduleName := "mtags", + projectDependencies := { + // mtags-shared are included in scala3-presentation-compiler module as sources + if (isScala3WithPresentationCompiler(scalaVersion.value)) { + projectDependencies.value.filterNot(_.name == "mtags-shared") + } else projectDependencies.value + }, ) .dependsOn(mtagsShared) .enablePlugins(BuildInfoPlugin) @@ -575,8 +615,8 @@ def runMtagsPublishLocal( .extract(state) .appendWithSession( List( - mtags / scalaVersion := scalaV, mtagsShared / scalaVersion := scalaV, + mtags / scalaVersion := scalaV, ThisBuild / version := projectV, ThisBuild / useSuperShell := false, ), @@ -635,6 +675,7 @@ lazy val mtest = project "scala212" -> V.scala212, "scala213" -> V.scala213, "scala3" -> V.scala3, + "firstScala3PCVersion" -> V.firstScala3PCVersion, "scala2Versions" -> V.scala2Versions, "scala3Versions" -> (V.scala3Versions ++ V.nightlyScala3Versions), "scala2Versions" -> V.scala2Versions, @@ -647,6 +688,19 @@ lazy val mtest = project (ThisBuild / baseDirectory).value / "tests" / "mtest", scalaVersion.value, ), + libraryDependencies ++= { + if (isScala3WithPresentationCompiler(scalaVersion.value)) + List(scala3ScalametaDependency) + else Nil + }, + Compile / unmanagedSourceDirectories ++= { + val base = (mtags / Compile / sourceDirectory).value + if (isScala3WithPresentationCompiler(scalaVersion.value)) { + List(base / "scala") + } else { + Nil + } + }, ) .dependsOn(mtags) .enablePlugins(BuildInfoPlugin) diff --git a/mtags/src/main/scala-3-wrapper/ScalaPresentationCompiler.scala b/mtags/src/main/scala-3-wrapper/ScalaPresentationCompiler.scala new file mode 100644 index 00000000000..d75870743f0 --- /dev/null +++ b/mtags/src/main/scala-3-wrapper/ScalaPresentationCompiler.scala @@ -0,0 +1,186 @@ +package scala.meta.internal.pc + +import java.net.URI +import java.nio.file.Path +import java.util.concurrent.CompletableFuture +import java.util.concurrent.ExecutorService +import java.util.concurrent.ScheduledExecutorService +import java.{util as ju} + +import scala.meta.pc.AutoImportsResult +import scala.meta.pc.DefinitionResult +import scala.meta.pc.HoverSignature +import scala.meta.pc.OffsetParams +import scala.meta.pc.PresentationCompiler +import scala.meta.pc.PresentationCompilerConfig +import scala.meta.pc.RangeParams +import scala.meta.pc.SymbolSearch +import scala.meta.pc.VirtualFileParams + +import dotty.tools.pc.{ScalaPresentationCompiler as DottyPresentationCompiler} +import org.eclipse.lsp4j.CompletionItem +import org.eclipse.lsp4j.CompletionList +import org.eclipse.lsp4j.Diagnostic +import org.eclipse.lsp4j.DocumentHighlight +import org.eclipse.lsp4j.SelectionRange +import org.eclipse.lsp4j.SignatureHelp +import org.eclipse.lsp4j.TextEdit + +/** + * This is a wrapper around the DottyPresentationCompiler + * The main purpose is to allow metals developers to iterate + * faster on new features. + * + * All bugfixes should happen directly in dotty repository. + * https://github.com/lampepfl/dotty/tree/main/presentation-compiler + * + * New features can be developed here, and then later moved to dotty. + */ +class ScalaPresentationCompiler( + underlying: DottyPresentationCompiler = new DottyPresentationCompiler() +) extends PresentationCompiler: + + override def didClose(uri: URI): Unit = + underlying.didClose(uri) + + override def isLoaded(): Boolean = + underlying.isLoaded() + + override def autoImports( + name: String, + params: OffsetParams, + isExtension: java.lang.Boolean, + ): CompletableFuture[ju.List[AutoImportsResult]] = + underlying.autoImports(name, params, isExtension) + + override def newInstance( + buildTargetIdentifier: String, + classpath: ju.List[Path], + options: ju.List[String], + ): PresentationCompiler = + underlying.newInstance(buildTargetIdentifier, classpath, options) + + override def withScheduledExecutorService( + scheduledExecutorService: ScheduledExecutorService + ): PresentationCompiler = + underlying.withScheduledExecutorService(scheduledExecutorService) + + override def hover( + params: OffsetParams + ): CompletableFuture[ju.Optional[HoverSignature]] = + underlying.hover(params) + + override def convertToNamedArguments( + params: OffsetParams, + argIndices: ju.List[Integer], + ): CompletableFuture[ju.List[TextEdit]] = + underlying.convertToNamedArguments(params, argIndices) + + override def shutdown(): Unit = + underlying.shutdown() + + override def withWorkspace(workspace: Path): PresentationCompiler = + underlying.withWorkspace(workspace) + + override def complete( + params: OffsetParams + ): CompletableFuture[CompletionList] = + underlying.complete(params) + + override def withConfiguration( + config: PresentationCompilerConfig + ): PresentationCompiler = + underlying.withConfiguration(config) + + override def insertInferredType( + params: OffsetParams + ): CompletableFuture[ju.List[TextEdit]] = + underlying.insertInferredType(params) + + override def typeDefinition( + params: OffsetParams + ): CompletableFuture[DefinitionResult] = + underlying.typeDefinition(params) + + override def completionItemResolve( + item: CompletionItem, + symbol: String, + ): CompletableFuture[CompletionItem] = + underlying.completionItemResolve(item, symbol) + + override def prepareRename( + params: OffsetParams + ): CompletableFuture[ju.Optional[org.eclipse.lsp4j.Range]] = + underlying.prepareRename(params) + + override def diagnosticsForDebuggingPurposes(): ju.List[String] = + underlying.diagnosticsForDebuggingPurposes() + + override def withSearch(search: SymbolSearch): PresentationCompiler = + underlying.withSearch(search) + + override def scalaVersion(): String = + underlying.scalaVersion() + + override def definition( + params: OffsetParams + ): CompletableFuture[DefinitionResult] = + underlying.definition(params) + + override def documentHighlight( + params: OffsetParams + ): CompletableFuture[ju.List[DocumentHighlight]] = + underlying.documentHighlight(params) + + override def rename( + params: OffsetParams, + name: String, + ): CompletableFuture[ju.List[TextEdit]] = + underlying.rename(params, name) + + override def implementAbstractMembers( + params: OffsetParams + ): CompletableFuture[ju.List[TextEdit]] = + underlying.implementAbstractMembers(params) + + override def didChange( + params: VirtualFileParams + ): CompletableFuture[ju.List[Diagnostic]] = + underlying.didChange(params) + + override def semanticdbTextDocument( + filename: URI, + code: String, + ): CompletableFuture[Array[Byte]] = + underlying.semanticdbTextDocument(filename, code) + + override def signatureHelp( + params: OffsetParams + ): CompletableFuture[SignatureHelp] = + underlying.signatureHelp(params) + + override def selectionRange( + params: ju.List[OffsetParams] + ): CompletableFuture[ju.List[SelectionRange]] = + underlying.selectionRange(params) + + override def extractMethod( + range: RangeParams, + extractionPos: OffsetParams, + ): CompletableFuture[ju.List[TextEdit]] = + underlying.extractMethod(range, extractionPos) + + override def getTasty( + targetUri: URI, + isHttpEnabled: Boolean, + ): CompletableFuture[String] = + underlying.getTasty(targetUri, isHttpEnabled) + + override def restart(): Unit = + underlying.restart() + + override def withExecutorService( + executorService: ExecutorService + ): PresentationCompiler = + underlying.withExecutorService(executorService) +end ScalaPresentationCompiler diff --git a/mtags/src/main/scala/scala/meta/internal/metals/JdkSources.scala b/mtags/src/main/scala/scala/meta/internal/metals/JdkSources.scala index 56b598ff007..4d4841b2079 100644 --- a/mtags/src/main/scala/scala/meta/internal/metals/JdkSources.scala +++ b/mtags/src/main/scala/scala/meta/internal/metals/JdkSources.scala @@ -7,7 +7,7 @@ import scala.util.Failure import scala.util.Success import scala.util.Try -import scala.meta.internal.mtags.MtagsEnrichments._ +import scala.meta.internal.mtags.ScalametaCommonEnrichments._ import scala.meta.io.AbsolutePath import scala.meta.io.RelativePath diff --git a/project/DottyVersion.scala b/project/DottyVersion.scala new file mode 100644 index 00000000000..fbeda541419 --- /dev/null +++ b/project/DottyVersion.scala @@ -0,0 +1,64 @@ +import scala.util.Try + +final case class DottyVersion( + major: Int, + minor: Int, + patch: Int, + rc: Option[Int], + nigthlyDate: Option[Int], + original: String, +) { + + def >(o: DottyVersion): Boolean = { + val diff = toList + .zip(o.toList) + .collectFirst { + case (a, b) if a - b != 0 => a - b + } + .getOrElse(0) + diff > 0 + } + + def >=(o: DottyVersion): Boolean = this == o || this > o + + override def toString(): String = original + + private def toList: List[Int] = + List( + major, + minor, + patch, + rc.getOrElse(Int.MaxValue), + nigthlyDate.getOrElse(Int.MaxValue), + ) +} + +object DottyVersion { + def parse(v: String): Option[DottyVersion] = { + Try { + val parts = v.split("\\.|-RC|-") + if (parts.size < 3) None + else { + val Array(major, minor, patch) = parts.take(3).map(_.toInt) + val rc = parts.lift(3).map(_.toInt) + // format is "$major.$minor.$patch-RC$rc-bin-$date-hash-NIGHTLY" + // or when locally published "$major.$minor.$patch-RC$rc-bin-SNAPSHOT" + if (parts.lift(5) == Some("SNAPSHOT")) { + Some(DottyVersion(major, minor, patch, rc, None, v)) + } else { + val date = parts.lift(5).map(_.toInt) + Some(DottyVersion(major, minor, patch, rc, date, v)) + } + } + + }.toOption.flatten + } + + implicit val ordering: Ordering[DottyVersion] = + new Ordering[DottyVersion] { + override def compare(x: DottyVersion, y: DottyVersion): Int = + if (x == y) 0 + else if (x > y) 1 + else -1 + } +} diff --git a/project/Scala3NightlyVersions.scala b/project/Scala3NightlyVersions.scala index 0f211826469..e9dd97e4ff0 100644 --- a/project/Scala3NightlyVersions.scala +++ b/project/Scala3NightlyVersions.scala @@ -1,5 +1,4 @@ import scala.jdk.CollectionConverters._ -import scala.util.Try object Scala3NightlyVersions { @@ -72,60 +71,4 @@ object Scala3NightlyVersions { .sorted .lastOption } - - case class DottyVersion( - major: Int, - minor: Int, - patch: Int, - rc: Option[Int], - nigthlyDate: Option[Int], - original: String, - ) { - - def >(o: DottyVersion): Boolean = { - val diff = toList - .zip(o.toList) - .collectFirst { - case (a, b) if a - b != 0 => a - b - } - .getOrElse(0) - diff > 0 - } - - override def toString(): String = original - - private def toList: List[Int] = - List( - major, - minor, - patch, - rc.getOrElse(Int.MaxValue), - nigthlyDate.getOrElse(Int.MaxValue), - ) - } - - object DottyVersion { - def parse(v: String): Option[DottyVersion] = { - Try { - val parts = v.split("\\.|-RC|-") - if (parts.size < 3) None - else { - val Array(major, minor, patch) = parts.take(3).map(_.toInt) - val rc = parts.lift(3).map(_.toInt) - // format is "$major.$minor.$patch-RC$rc-bin-$date-hash-NIGHTLY" - val date = parts.lift(5).map(_.toInt) - Some(DottyVersion(major, minor, patch, rc, date, v)) - } - - }.toOption.flatten - } - - implicit val ordering: Ordering[DottyVersion] = - new Ordering[DottyVersion] { - override def compare(x: DottyVersion, y: DottyVersion): Int = - if (x == y) 0 - else if (x > y) 1 - else -1 - } - } } diff --git a/project/V.scala b/project/V.scala index 96a9aeb8412..5cb6a40821d 100644 --- a/project/V.scala +++ b/project/V.scala @@ -6,6 +6,7 @@ object V { val scala212 = "2.12.18" val scala213 = "2.13.11" val scala3 = "3.3.0" + val firstScala3PCVersion = "3.3.2-RC1-bin-20230721-492f777-NIGHTLY" // When you can add to removedScalaVersions in MtagsResolver.scala with the last released version val scala3RC: Option[String] = Some("3.3.1-RC4") val sbtScala = "2.12.17" @@ -19,7 +20,9 @@ object V { val bloopConfig = "1.5.5" val bsp = "2.1.0-M5" val coursier = "2.1.5" - val coursierInterfaces = "1.0.18" + val coursierInterfaces = + "1.0.18" // changing coursier interfaces version may be not binary compatible. + // After each update of coursier interfaces, remember to bump the version in dotty repository. val debugAdapter = "3.1.4" val genyVersion = "1.0.0" val gradleBloop = "1.6.1" @@ -47,9 +50,8 @@ object V { val lsp4j = "org.eclipse.lsp4j" % "org.eclipse.lsp4j" % lsp4jV val dap4j = "org.eclipse.lsp4j" % "org.eclipse.lsp4j.debug" % lsp4jV - // https://github.com/scalameta/metals/issues/5427 - def isNightliesEnabled: Boolean = false - // sys.env.get("CI").isDefined || sys.env.get("NIGHTLIES").isDefined + def isNightliesEnabled: Boolean = + sys.env.get("CI").isDefined || sys.env.get("NIGHTLIES").isDefined // List of supported Scala versions in SemanticDB. Needs to be manually updated // for every SemanticDB upgrade. @@ -103,22 +105,26 @@ object V { // Scala 3 def nonDeprecatedScala3Versions = Seq(scala3, "3.2.2", "3.1.3") ++ scala3RC.toSeq + // ++ Seq("3.4.0-RC1-bin-SNAPSHOT") // local testing of scala3-presentation-compiler + // whenever version is removed please add it to MtagsResolver under last supported Metals version def deprecatedScala3Versions = Seq("3.2.1", "3.2.0", "3.1.2", "3.1.1", "3.1.0") + // NOTE if you had a new Scala Version make sure it's contained in quickPublishScalaVersions def scala3Versions = nonDeprecatedScala3Versions ++ deprecatedScala3Versions lazy val nightlyScala3DottyVersions = { if (isNightliesEnabled) - Scala3NightlyVersions.nightlyReleasesAfter(scala3) + Scala3NightlyVersions.nightlyReleasesAfter(firstScala3PCVersion) else Nil } def nightlyScala3Versions = nightlyScala3DottyVersions.map(_.toString) - def supportedScalaVersions = scala2Versions ++ scala3Versions + def supportedScalaVersions = + scala2Versions ++ scala3Versions def nonDeprecatedScalaVersions = nonDeprecatedScala2Versions ++ nonDeprecatedScala3Versions def deprecatedScalaVersions = diff --git a/tests/cross/src/main/scala/tests/BaseCompletionSuite.scala b/tests/cross/src/main/scala/tests/BaseCompletionSuite.scala index fed880c6ed4..e5a57ca640e 100644 --- a/tests/cross/src/main/scala/tests/BaseCompletionSuite.scala +++ b/tests/cross/src/main/scala/tests/BaseCompletionSuite.scala @@ -7,7 +7,7 @@ import scala.meta.internal.jdk.CollectionConverters._ import scala.meta.internal.metals.CompilerOffsetParams import scala.meta.internal.metals.EmptyCancelToken import scala.meta.internal.metals.TextEdits -import scala.meta.internal.mtags.MtagsEnrichments._ +import scala.meta.internal.mtags.CommonMtagsEnrichments.XtensionCompletionItemData import scala.meta.pc.CancelToken import munit.Location diff --git a/tests/cross/src/main/scala/tests/pc/BaseHoverSuite.scala b/tests/cross/src/main/scala/tests/pc/BaseHoverSuite.scala index e07df248633..916d308d35d 100644 --- a/tests/cross/src/main/scala/tests/pc/BaseHoverSuite.scala +++ b/tests/cross/src/main/scala/tests/pc/BaseHoverSuite.scala @@ -5,7 +5,7 @@ import java.nio.file.Paths import scala.meta.XtensionSyntax import scala.meta.internal.metals.CompilerOffsetParams import scala.meta.internal.metals.CompilerRangeParams -import scala.meta.internal.mtags.MtagsEnrichments._ +import scala.meta.internal.mtags.CommonMtagsEnrichments.XtensionOptionalJava import munit.Location import munit.TestOptions diff --git a/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala index 352e2fa90f2..c068814eeee 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala @@ -29,10 +29,14 @@ class CompletionDocSuite extends BaseCompletionSuite { |join(delimiter: CharSequence, elements: Iterable[_ <: CharSequence]): String |""".stripMargin, compat = Map( + scala3PresentationCompilerVersion -> + """|join(delimiter: CharSequence, elements: CharSequence*): String + |join(delimiter: CharSequence, elements: java.lang.Iterable[? <: CharSequence]): String + |""".stripMargin, "3" -> """|join(delimiter: CharSequence, elements: CharSequence*): String |join(delimiter: CharSequence, elements: Iterable[? <: CharSequence]): String - |""".stripMargin + |""".stripMargin, ), ) @@ -568,6 +572,15 @@ class CompletionDocSuite extends BaseCompletionSuite { | section on `StringBuilders` for more information. |StringBuilder scala.collection.mutable |""".stripMargin, + scala3PresentationCompilerVersion -> + List( + "StringBuilder scala.collection.mutable", + "StringBuilder(): StringBuilder", + "StringBuilder(str: String): StringBuilder", + "StringBuilder(underlying: java.lang.StringBuilder): StringBuilder", + "StringBuilder(capacity: Int): StringBuilder", + "StringBuilder(initCapacity: Int, initValue: String): StringBuilder", + ).map(s => scala213Docs + "\n" + s).mkString("\n"), "3" -> List( "StringBuilder scala.collection.mutable", diff --git a/tests/cross/src/test/scala/tests/pc/CompletionOverrideSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionOverrideSuite.scala index 11dc8e9d10b..ea2838afeb2 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionOverrideSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionOverrideSuite.scala @@ -283,6 +283,18 @@ class CompletionOverrideSuite extends BaseCompletionSuite { |} |""".stripMargin, compat = Map( + scala3PresentationCompilerVersion -> + """|package a.b + |abstract class Conflict { + | def self: Conflict + |} + |object Main { + | class Conflict + | new a.b.Conflict { + | def self: a.b.Conflict = ${0:???} + | } + |} + |""".stripMargin, "3" -> """|package a.b | @@ -296,7 +308,7 @@ class CompletionOverrideSuite extends BaseCompletionSuite { | def self: a.b.Conflict = ${0:???} | } |} - |""".stripMargin + |""".stripMargin, ), ) @@ -370,8 +382,10 @@ class CompletionOverrideSuite extends BaseCompletionSuite { " def foo@@", """ def foo: scala.collection.mutable.Set[Int] = ${0:???}""", compat = Map( + scala3PresentationCompilerVersion -> + """ def foo: scala.collection.mutable.Set[Int] = ${0:???}""", "3" -> - """ def foo: collection.mutable.Set[Int] = ${0:???}""" + """ def foo: collection.mutable.Set[Int] = ${0:???}""", ), ) @@ -452,6 +466,16 @@ class CompletionOverrideSuite extends BaseCompletionSuite { | def foo: lang.StringBuilder = ${0:???} |} |""".stripMargin, + compat = Map( + scala3PresentationCompilerVersion -> + """|abstract class Mutable { + | def foo: java.lang.StringBuilder + |} + |class Main extends Mutable { + | def foo: java.lang.StringBuilder = ${0:???} + |} + |""".stripMargin + ), ) checkEditLine( diff --git a/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala index 55b6732cf6a..71c56eeaa03 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala @@ -778,7 +778,8 @@ class CompletionSuite extends BaseCompletionSuite { """|incrementThisType(): A.this.type (with underlying type singleton.A) |""".stripMargin, compat = Map( - "3" -> "incrementThisType(): (A.this : singleton.A)" + scala3PresentationCompilerVersion -> "incrementThisType(): A.this.type", + "3" -> "incrementThisType(): (A.this : singleton.A)", ), ) @@ -1258,14 +1259,6 @@ class CompletionSuite extends BaseCompletionSuite { |""".stripMargin, ) - val pre331: String = - """|dynamics scala.languageFeature - |existentials scala.languageFeature - |experimental scala.languageFeature - |higherKinds scala.languageFeature - |implicitConversions scala.languageFeature - |""".stripMargin - check( "ordering-1", s"""|object Main { @@ -1280,7 +1273,7 @@ class CompletionSuite extends BaseCompletionSuite { |""".stripMargin, topLines = Some(5), compat = Map( - // higherKinds was deprecated + // higherKinds was deprecated in 2.13.11 but current dotty still depends on 2.13.10 "2.13.11" -> """|dynamics scala.languageFeature |existentials scala.languageFeature @@ -1288,16 +1281,12 @@ class CompletionSuite extends BaseCompletionSuite { |implicitConversions scala.languageFeature |postfixOps scala.languageFeature |""".stripMargin, - "3.2" -> pre331, - "3.1" -> pre331, - "3.3.0" -> pre331, - "3.3.1" -> pre331, - "3" -> - """|dynamics languageFeature - |existentials languageFeature - |experimental languageFeature - |higherKinds languageFeature - |implicitConversions languageFeature + scala3PresentationCompilerVersion -> + """|dynamics scala.languageFeature + |existentials scala.languageFeature + |experimental scala.languageFeature + |higherKinds scala.languageFeature + |implicitConversions scala.languageFeature |""".stripMargin, ), ) @@ -1405,7 +1394,7 @@ class CompletionSuite extends BaseCompletionSuite { | def hello = { | val name = Option("Bob") | name.@@ - | println(msg) + | println(msg) | } |} |""".stripMargin, diff --git a/tests/cross/src/test/scala/tests/pc/InsertInferredTypeSuite.scala b/tests/cross/src/test/scala/tests/pc/InsertInferredTypeSuite.scala index 9c01ef36dc5..83dd6dd00c6 100644 --- a/tests/cross/src/test/scala/tests/pc/InsertInferredTypeSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/InsertInferredTypeSuite.scala @@ -636,27 +636,31 @@ class InsertInferredTypeSuite extends BaseCodeActionSuite { |""".stripMargin, ) - checkEdit( - "refined-types", + val defaultRefinedTypes: String = """|object O{ | trait Foo { | type T | type G | } | - | val <> = new Foo { type T = Int; type G = Long} + | val c: Foo{type T = Int; type G = Long} = new Foo { type T = Int; type G = Long} |} - |""".stripMargin, + |""".stripMargin + + checkEdit( + "refined-types", """|object O{ | trait Foo { | type T | type G | } | - | val c: Foo{type T = Int; type G = Long} = new Foo { type T = Int; type G = Long} + | val <> = new Foo { type T = Int; type G = Long} |} |""".stripMargin, + defaultRefinedTypes, compat = Map( + scala3PresentationCompilerVersion -> defaultRefinedTypes, "3" -> """|object O{ | trait Foo { @@ -666,29 +670,33 @@ class InsertInferredTypeSuite extends BaseCodeActionSuite { | | val c: Foo{type T >: Int <: Int; type G >: Long <: Long} = new Foo { type T = Int; type G = Long} |} - |""".stripMargin + |""".stripMargin, ), ) - checkEdit( - "refined-types2", + val defaultRefinedTypes2: String = """|object O{ | trait Foo { | type T | } | val c = new Foo { type T = Int } - | val <> = c + | val d: Foo{type T = Int} = c |} - |""".stripMargin, + |""".stripMargin + + checkEdit( + "refined-types2", """|object O{ | trait Foo { | type T | } | val c = new Foo { type T = Int } - | val d: Foo{type T = Int} = c + | val <> = c |} |""".stripMargin, + defaultRefinedTypes2, compat = Map( + scala3PresentationCompilerVersion -> defaultRefinedTypes2, "3" -> """|object O{ | trait Foo { @@ -697,29 +705,33 @@ class InsertInferredTypeSuite extends BaseCodeActionSuite { | val c = new Foo { type T = Int } | val d: Foo{type T >: Int <: Int} = c |} - |""".stripMargin + |""".stripMargin, ), ) - checkEdit( - "refined-types3", + val defaultRefinedTypes3: String = """|object O{ | trait Foo { | type T | } | - | val <> = new Foo { type T = Int } + | val c: Foo{type T = Int} = new Foo { type T = Int } |} - |""".stripMargin, + |""".stripMargin + + checkEdit( + "refined-types3", """|object O{ | trait Foo { | type T | } | - | val c: Foo{type T = Int} = new Foo { type T = Int } + | val <> = new Foo { type T = Int } |} |""".stripMargin, + defaultRefinedTypes3, compat = Map( + scala3PresentationCompilerVersion -> defaultRefinedTypes3, "3" -> """|object O{ | trait Foo { @@ -728,34 +740,52 @@ class InsertInferredTypeSuite extends BaseCodeActionSuite { | | val c: Foo{type T >: Int <: Int} = new Foo { type T = Int } |} - |""".stripMargin + |""".stripMargin, ), ) - checkEdit( - "refined-types4".tag(IgnoreScala2), + val defaultRefinedTypes4: String = """|trait Foo extends Selectable { | type T |} | - |val <> = new Foo { + |val c: Foo{type T = Int; val x: Int; def y: Int; val z: Int; def z_=(x$1: Int): Unit} = new Foo { | type T = Int | val x = 0 | def y = 0 | var z = 0 |} - |""".stripMargin, + |""".stripMargin + + checkEdit( + "refined-types4".tag(IgnoreScala2), """|trait Foo extends Selectable { | type T |} | - |val c: Foo{type T >: Int <: Int; val x: Int; def y: Int; val z: Int; def z_=(x$1: Int): Unit} = new Foo { + |val <> = new Foo { | type T = Int | val x = 0 | def y = 0 | var z = 0 |} |""".stripMargin, + defaultRefinedTypes4, + compat = Map( + scala3PresentationCompilerVersion -> defaultRefinedTypes4, + "3" -> + """|trait Foo extends Selectable { + | type T + |} + | + |val c: Foo{type T >: Int <: Int; val x: Int; def y: Int; val z: Int; def z_=(x$1: Int): Unit} = new Foo { + | type T = Int + | val x = 0 + | def y = 0 + | var z = 0 + |} + |""".stripMargin, + ), ) checkEdit( diff --git a/tests/mtest/src/main/scala/tests/BaseSuite.scala b/tests/mtest/src/main/scala/tests/BaseSuite.scala index 5af76c6edf5..6e49a7025b7 100644 --- a/tests/mtest/src/main/scala/tests/BaseSuite.scala +++ b/tests/mtest/src/main/scala/tests/BaseSuite.scala @@ -19,6 +19,9 @@ abstract class BaseSuite extends munit.FunSuite with Assertions { */ val FlakyWindows = new Tag("FlakyWindows") + val scala3PresentationCompilerVersion: String = + s">=${BuildInfoVersions.firstScala3PCVersion}" + Testing.enable() def isJava8: Boolean =