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 Aug 14, 2023
1 parent ccd5153 commit dbc3c77
Show file tree
Hide file tree
Showing 216 changed files with 1,071 additions and 1,082 deletions.
10 changes: 2 additions & 8 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
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."
Expand Down
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."
"*"
]
13 changes: 0 additions & 13 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.7.12"
runner.dialect = scala213
runner.dialect = scala3
project.git = true
align.preset = none
align.stripMargin = true
Expand Down Expand Up @@ -34,5 +34,6 @@ fileOverride {
},
"glob:**/mtags*/**" {
trailingCommas = never
runner.dialect = scala213
}
}
110 changes: 70 additions & 40 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,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 @@ -137,7 +137,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 @@ -220,6 +220,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 @@ -282,21 +303,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 ++ V.nightlyScala3Versions,
Expand Down Expand Up @@ -327,7 +346,7 @@ val mtagsSettings = List(
),
if3 = List(
"org.scala-lang" %% "scala3-compiler" % scalaVersion.value,
scala3ScalametaDependency,
scalametaDependency,
),
if3WithPresentationCompiler = List(
"org.scala-lang" %% "scala3-presentation-compiler" % scalaVersion.value
Expand Down Expand Up @@ -360,21 +379,21 @@ 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,
scalafixConfig := Some(
(ThisBuild / baseDirectory).value / ".scalafix3.conf"
(ThisBuild / baseDirectory).value / ".scalafix2.conf"
),
)
.dependsOn(interfaces)
Expand All @@ -391,9 +410,6 @@ lazy val mtags3WithPresentationCompiler = project
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)
Expand Down Expand Up @@ -443,7 +459,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 @@ -473,13 +490,16 @@ 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
"io.get-coursier" %% "versions" % "0.3.2",
("io.get-coursier" %% "versions" % "0.3.2")
.cross(CrossVersion.for3Use2_13),
// for logging
"com.outr" %% "scribe" % V.scribe,
"com.outr" %% "scribe-file" % V.scribe,
Expand All @@ -489,10 +509,11 @@ lazy val metals = project
// For remote language server
"com.lihaoyi" %% "requests" % "0.8.0",
// for producing SemanticDB from Scala source files
"org.scalameta" %% "scalameta" % V.scalameta,
"org.scalameta" % "semanticdb-scalac-core" % V.scalameta cross CrossVersion.full,
scalametaDependency,
// "org.scalameta" % "semanticdb-scalac-core" % V.scalameta cross CrossVersion.full,
// 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.2.0",
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4",
("org.virtuslab.scala-cli" % "scala-cli-bsp" % V.scalaCli)
Expand Down Expand Up @@ -558,6 +579,7 @@ lazy val `sbt-metals` = project
lazy val input = project
.in(file("tests/input"))
.settings(
scalaVersion := V.scala213,
sharedSettings,
publish / skip := true,
libraryDependencies ++= List(
Expand Down Expand Up @@ -690,7 +712,7 @@ lazy val mtest = project
),
libraryDependencies ++= {
if (isScala3WithPresentationCompiler(scalaVersion.value))
List(scala3ScalametaDependency)
List(scalametaDependency)
else Nil
},
Compile / unmanagedSourceDirectories ++= {
Expand Down Expand Up @@ -742,6 +764,7 @@ def isInTestShard(name: String, logger: Logger): Boolean = {
lazy val metalsDependencies = project
.in(file("target/.dependencies"))
.settings(
scalaVersion := V.scala213,
publish / skip := true,
// silent the intransitive dependency warning
publishMavenStyle := false,
Expand All @@ -750,13 +773,13 @@ lazy val metalsDependencies = project
// will pick them up and update them. They aren't actually used.
"com.lihaoyi" %% "ammonite-util" % V.ammonite,
"org.typelevel" % "kind-projector" % V.kindProjector cross CrossVersion.full,
"com.olegpy" %% "better-monadic-for" % V.betterMonadicFor,
("com.olegpy" %% "better-monadic-for" % V.betterMonadicFor),
"com.lihaoyi" % "mill-contrib-testng" % V.mill,
"org.virtuslab.scala-cli" % "cli_3" % V.scalaCli intransitive (),
"ch.epfl.scala" % "bloop-maven-plugin" % V.mavenBloop,
"ch.epfl.scala" %% "gradle-bloop" % V.gradleBloop,
"com.sourcegraph" % "semanticdb-java" % V.javaSemanticdb,
"ch.epfl.scala" %% "scala-debug-adapter" % V.debugAdapter intransitive (),
("ch.epfl.scala" %% "scala-debug-adapter" % V.debugAdapter) intransitive (),
),
)
.disablePlugins(ScalafixPlugin)
Expand All @@ -771,9 +794,16 @@ 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,
// The dependencies listed below are only listed so Scala Steward
// will pick them up and update them. They aren't actually used.
("com.lihaoyi" %% "ammonite-util" % V.ammonite intransitive ())
.cross(CrossVersion.for3Use2_13),
"com.lihaoyi" % "mill-contrib-testng" % V.mill intransitive (),
),
buildInfoPackage := "tests",
Compile / resourceGenerators += InputProperties
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.JdkSources
import scala.meta.internal.metals.logging.MetalsLogger
Expand All @@ -15,7 +10,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 @@ -97,22 +91,6 @@ class MetalsBench {
}
}

@Benchmark
@BenchmarkMode(Array(Mode.SingleShotTime))
def scalacTokenize(): Unit = {
val g = global
scalaDependencySources.inputs.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 @@ -122,27 +100,6 @@ class MetalsBench {
}
}

lazy val global: Global = InteractiveSemanticdb.newCompiler()

@Benchmark
@BenchmarkMode(Array(Mode.SingleShotTime))
def scalacParse(): Unit = {
val g = global
scalaDependencySources.inputs.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 @@ -7,7 +7,7 @@ import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.builds.BuildServerProvider
import scala.meta.internal.builds.ShellRunner
import scala.meta.internal.metals.Messages.BspProvider
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.MetalsEnrichments.given
import scala.meta.internal.metals.clients.language.MetalsLanguageClient
import scala.meta.io.AbsolutePath

Expand Down Expand Up @@ -42,7 +42,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 dbc3c77

Please sign in to comment.