Skip to content

Commit

Permalink
refactor: Migrate Metals server to Scala 3
Browse files Browse the repository at this point in the history
This mostly involved:
- changing imports
- moving things between MtagsEnrichements variants
- adding ()
- fixing bugs reported now as warning or errors (things previously not reported at all)
  • Loading branch information
tgodzik committed May 31, 2024
1 parent b9b8c5b commit ffe658e
Show file tree
Hide file tree
Showing 202 changed files with 1,004 additions and 985 deletions.
12 changes: 4 additions & 8 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
rules = [
OrganizeImports,
ExplicitResultTypes,
RemoveUnused
OrganizeImports
]

ExplicitResultTypes.rewriteStructuralTypesToNamedSubclass = false

RemoveUnused.imports = false

OrganizeImports.groupedImports = Explode
OrganizeImports.expandRelative = true
OrganizeImports.removeUnused = true
OrganizeImports.removeUnused = false
OrganizeImports.groups = [
"re:javax?\\."
"scala."
"scala.meta."
"*"
]

OrganizeImports.targetDialect = StandardLayout
19 changes: 19 additions & 0 deletions .scalafix2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
rules = [
OrganizeImports,
ExplicitResultTypes,
RemoveUnused
]

ExplicitResultTypes.rewriteStructuralTypesToNamedSubclass = false

RemoveUnused.imports = false

OrganizeImports.groupedImports = Explode
OrganizeImports.expandRelative = true
OrganizeImports.removeUnused = true
OrganizeImports.groups = [
"re:javax?\\."
"scala."
"scala.meta."
"*"
]
14 changes: 0 additions & 14 deletions .scalafix3.conf

This file was deleted.

3 changes: 2 additions & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version = "3.8.1"
runner.dialect = scala213source3
runner.dialect = scala3
project.git = true
align.preset = none
align.stripMargin = true
Expand Down Expand Up @@ -37,6 +37,7 @@ fileOverride {
},
"glob:**/mtags*/**" {
trailingCommas = never
runner.dialect = scala213
}
"glob:**/tests/cross/src/**" {
trailingCommas = never
Expand Down
104 changes: 66 additions & 38 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ def crossSetting[A](
logo := Welcome.logo
usefulTasks := Welcome.tasks

ThisBuild / scalafixScalaBinaryVersion := scalaBinaryVersion.value
ThisBuild / scalafixScalaBinaryVersion := "2.13"

inThisBuild(
List(
version ~= { dynVer =>
if (isCI) dynVer
else localSnapshotVersion // only for local publishing
},
scalaVersion := V.scala213,
crossScalaVersions := List(V.scala213),
scalaVersion := V.scala3,
crossScalaVersions := List(V.scala3),
organization := "org.scalameta",
licenses := Seq(
"Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")
Expand Down Expand Up @@ -128,7 +128,7 @@ commands ++= Seq(
runMtagsPublishLocal(st, v, localSnapshotVersion)
}
"interfaces/publishLocal" ::
s"++${V.scala213} metals/publishLocal" ::
s"++${V.scala3} metals/publishLocal" ::
"mtags-java/publishLocal" ::
publishMtags
},
Expand Down Expand Up @@ -218,6 +218,27 @@ val sharedSettings = sharedJavacOptions ++ sharedScalacOptions ++ List(
)
),
),
excludeDependencies ++= crossSetting(
scalaVersion.value,
if3 = {
// Exclude cross published version dependencies leading to conflicts in Scala 3 vs 2.13
// When using Scala 3 exclude Scala 2.13 standard native libraries,
// when using Scala 2.13 exclude Scala 3 standard native libraries
// Use full name, Maven style published artifacts cannot use artifact/cross version for exclusion rules
List(
ExclusionRule()
.withOrganization("org.scala-lang.modules")
.withName(
"scala-collection-compat_2.13"
),
ExclusionRule()
.withOrganization("org.scala-lang.modules")
.withName(
"scala-xml_2.13"
),
)
},
),
scalacOptions ++= lintingOptions(scalaVersion.value),
)

Expand Down Expand Up @@ -284,21 +305,19 @@ 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
def scalametaDependency = ("org.scalameta" %% "scalameta" % V.scalameta)
.cross(CrossVersion.for3Use2_13)
.exclude("org.scala-lang", "scala-reflect")
.exclude("org.scala-lang", "scala-compiler")
.exclude("org.scala-lang.modules", "scala-collection-compat")
.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",
)

val mtagsSettings = List(
crossScalaVersions := V.supportedScalaVersions,
Expand Down Expand Up @@ -331,7 +350,7 @@ val mtagsSettings = List(
),
if3 = List(
"org.scala-lang" %% "scala3-compiler" % scalaVersion.value,
scala3ScalametaDependency,
scalametaDependency,
),
),
},
Expand Down Expand Up @@ -360,22 +379,22 @@ val mtagsSettings = List(
},
)

lazy val mtags3 = project
lazy val mtags2 = project
.in(file(".mtags"))
.settings(
Compile / unmanagedSourceDirectories := Seq(),
sharedSettings,
mtagsSettings,
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags" / "src" / "main" / "scala",
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags-shared" / "src" / "main" / "scala",
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags-shared" / "src" / "main" / "scala-3",
moduleName := "mtags3",
scalaVersion := V.scala3,
target := (ThisBuild / baseDirectory).value / "mtags" / "target" / "target3",
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags-shared" / "src" / "main" / "scala-2.13",
moduleName := "mtags2",
scalaVersion := V.scala213,
target := (ThisBuild / baseDirectory).value / "mtags" / "target" / "target2",
publish / skip := true,
libraryDependencies += V.guava,
scalafixConfig := Some(
(ThisBuild / baseDirectory).value / ".scalafix3.conf"
(ThisBuild / baseDirectory).value / ".scalafix2.conf"
),
)
.dependsOn(interfaces)
Expand Down Expand Up @@ -421,7 +440,8 @@ lazy val metals = project
// for BSP
"org.scala-sbt.ipcsocket" % "ipcsocket" % "1.6.2",
"ch.epfl.scala" % "bsp4j" % V.bsp,
"ch.epfl.scala" %% "bloop-launcher-core" % V.bloop,
("ch.epfl.scala" %% "bloop-launcher-core" % V.bloop)
.cross(CrossVersion.for3Use2_13),
// for LSP
V.lsp4j,
// for DAP
Expand Down Expand Up @@ -451,14 +471,20 @@ lazy val metals = project
// Scala dependencies
// ==================
"org.scalameta" % "mdoc-interfaces" % V.mdoc,
"org.scalameta" %% "scalafmt-dynamic" % V.scalafmt,
("org.scalameta" %% "scalafmt-dynamic" % V.scalafmt)
.cross(CrossVersion.for3Use2_13),
"com.googlecode.java-diff-utils" % "diffutils" % "1.3.0",
"ch.epfl.scala" % "scalafix-interfaces" % V.scalafix,
// For reading classpaths.
// for fetching ch.epfl.scala:bloop-frontend and other library dependencies
"io.get-coursier" % "interface" % V.coursierInterfaces,
// for comparing versions && fetching from sbt maven repository
"io.get-coursier" %% "coursier" % V.coursier,
"io.get-coursier" %% "coursier-sbt-maven-repository" % V.coursier,
("io.get-coursier" %% "versions" % "0.3.2")
.cross(CrossVersion.for3Use2_13),
("io.get-coursier" %% "coursier-sbt-maven-repository" % V.coursier)
.cross(CrossVersion.for3Use2_13),
("io.get-coursier" %% "coursier" % V.coursier)
.cross(CrossVersion.for3Use2_13),
// for logging
"com.outr" %% "scribe" % V.scribe,
"com.outr" %% "scribe-file" % V.scribe,
Expand All @@ -467,13 +493,11 @@ lazy val metals = project
"com.lihaoyi" %% "ujson" % "3.3.1",
// For fetching projects' templates
"com.lihaoyi" %% "requests" % "0.8.2",
// for producing SemanticDB from Scala source files, to be sure we want the same version of scalameta
"org.scalameta" %% "scalameta" % V.semanticdb(scalaVersion.value),
"org.scalameta" % "semanticdb-scalac-core" % V.semanticdb(
scalaVersion.value
) cross CrossVersion.full,
// for producing SemanticDB from Scala source files
scalametaDependency,
// For starting Ammonite
"io.github.alexarchambault.ammonite" %% "ammonite-runner" % "0.4.0",
("io.github.alexarchambault.ammonite" %% "ammonite-runner" % "0.4.0")
.cross(CrossVersion.for3Use2_13),
"org.scala-lang.modules" %% "scala-xml" % "2.3.0",
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4",
("org.virtuslab.scala-cli" % "scala-cli-bsp" % V.scalaCli)
Expand Down Expand Up @@ -543,6 +567,7 @@ lazy val input = project
.in(file("tests/input"))
.settings(
sharedSettings,
scalaVersion := V.scala213,
scalacOptions -= "-Xsource:3",
publish / skip := true,
libraryDependencies ++= List(
Expand Down Expand Up @@ -719,6 +744,7 @@ lazy val metalsDependencies = project
.in(file("target/.dependencies"))
.settings(
publish / skip := true,
scalaVersion := V.scala213,
// silent the intransitive dependency warning
publishMavenStyle := false,
libraryDependencies ++= List(
Expand Down Expand Up @@ -749,8 +775,10 @@ lazy val unit = project
sharedSettings,
Test / javaOptions += "-Xmx2G",
libraryDependencies ++= List(
"io.get-coursier" %% "coursier" % V.coursier, // for jars
"ch.epfl.scala" %% "bloop-config" % V.bloopConfig,
("io.get-coursier" %% "coursier" % V.coursier)
.cross(CrossVersion.for3Use2_13), // for jars
("ch.epfl.scala" %% "bloop-config" % V.bloopConfig)
.cross(CrossVersion.for3Use2_13),
"org.scalameta" %% "munit" % V.munit,
),
buildInfoPackage := "tests",
Expand Down
43 changes: 0 additions & 43 deletions metals-bench/src/main/scala/bench/MetalsBench.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package bench

import scala.reflect.internal.util.BatchSourceFile
import scala.reflect.io.VirtualFile
import scala.tools.nsc.interactive.Global

import scala.meta.dialects
import scala.meta.interactive.InteractiveSemanticdb
import scala.meta.internal.metals.EmptyReportContext
import scala.meta.internal.metals.IdentifierIndex
import scala.meta.internal.metals.JdkSources
Expand All @@ -22,7 +17,6 @@ import scala.meta.internal.mtags.SemanticdbClasspath
import scala.meta.internal.parsing.Trees
import scala.meta.internal.semanticdb.TextDocument
import scala.meta.internal.tokenizers.LegacyScanner
import scala.meta.internal.tokenizers.LegacyToken
import scala.meta.io.AbsolutePath
import scala.meta.io.Classpath

Expand Down Expand Up @@ -128,22 +122,6 @@ class MetalsBench {
}
}

@Benchmark
@BenchmarkMode(Array(Mode.SingleShotTime))
def scalacTokenize(): Unit = {
val g = global
scalaDependencySources.foreach { input =>
val unit = new g.CompilationUnit(
new BatchSourceFile(new VirtualFile(input.path), input.chars)
)
val scanner = g.newUnitScanner(unit)
scanner.init()
while (scanner.token != LegacyToken.EOF) {
scanner.nextToken()
}
}
}

@Benchmark
@BenchmarkMode(Array(Mode.SingleShotTime))
def scalametaParse(): Unit = {
Expand All @@ -153,27 +131,6 @@ class MetalsBench {
}
}

lazy val global: Global = InteractiveSemanticdb.newCompiler()

@Benchmark
@BenchmarkMode(Array(Mode.SingleShotTime))
def scalacParse(): Unit = {
val g = global
scalaDependencySources.foreach { input =>
val unit = new g.CompilationUnit(
new BatchSourceFile(new VirtualFile(input.path), input.chars)
)
val tree = g.newUnitParser(unit).parse()
var i = 0
new g.Traverser {
override def apply[T <: g.Tree](tree: T): T = {
i += 1
super.apply(tree)
}
}.traverse(tree)
}
}

@Benchmark
@BenchmarkMode(Array(Mode.SingleShotTime))
def mtagsJavaParse(): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import scala.meta.internal.builds.BuildServerProvider
import scala.meta.internal.builds.ShellRunner
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.Messages.BspProvider
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.StatusBar
import scala.meta.internal.metals.UserConfiguration
import scala.meta.internal.metals.StatusBar
import scala.meta.internal.metals.MetalsEnrichments.given
import scala.meta.internal.metals.clients.language.MetalsLanguageClient
import scala.meta.io.AbsolutePath

Expand Down Expand Up @@ -75,7 +75,7 @@ final class BspConfigGenerator(
buildTools: List[BuildServerProvider]
): Future[(BuildServerProvider, BspConfigGenerationStatus)] = {
for {
Some(buildTool) <- chooseBuildServerProvider(buildTools)
case Some(buildTool) <- chooseBuildServerProvider(buildTools)
status <- buildTool.generateBspConfig(
workspace,
args => runUnconditionally(buildTool, args),
Expand Down
Loading

0 comments on commit ffe658e

Please sign in to comment.