Skip to content

Commit e5b50a5

Browse files
committed
refactor: Migrate Metals server to Scala 3
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)
1 parent e6534a0 commit e5b50a5

File tree

202 files changed

+1004
-985
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

202 files changed

+1004
-985
lines changed

.scalafix.conf

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
rules = [
2-
OrganizeImports,
3-
ExplicitResultTypes,
4-
RemoveUnused
2+
OrganizeImports
53
]
64

7-
ExplicitResultTypes.rewriteStructuralTypesToNamedSubclass = false
8-
9-
RemoveUnused.imports = false
10-
115
OrganizeImports.groupedImports = Explode
126
OrganizeImports.expandRelative = true
13-
OrganizeImports.removeUnused = true
7+
OrganizeImports.removeUnused = false
148
OrganizeImports.groups = [
159
"re:javax?\\."
1610
"scala."
1711
"scala.meta."
1812
"*"
1913
]
14+
15+
OrganizeImports.targetDialect = StandardLayout

.scalafix2.conf

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
rules = [
2+
OrganizeImports,
3+
ExplicitResultTypes,
4+
RemoveUnused
5+
]
6+
7+
ExplicitResultTypes.rewriteStructuralTypesToNamedSubclass = false
8+
9+
RemoveUnused.imports = false
10+
11+
OrganizeImports.groupedImports = Explode
12+
OrganizeImports.expandRelative = true
13+
OrganizeImports.removeUnused = true
14+
OrganizeImports.groups = [
15+
"re:javax?\\."
16+
"scala."
17+
"scala.meta."
18+
"*"
19+
]

.scalafix3.conf

-14
This file was deleted.

.scalafmt.conf

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
version = "3.8.1"
2-
runner.dialect = scala213source3
2+
runner.dialect = scala3
33
project.git = true
44
align.preset = none
55
align.stripMargin = true
@@ -37,6 +37,7 @@ fileOverride {
3737
},
3838
"glob:**/mtags*/**" {
3939
trailingCommas = never
40+
runner.dialect = scala213
4041
}
4142
"glob:**/tests/cross/src/**" {
4243
trailingCommas = never

build.sbt

+66-38
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ def crossSetting[A](
3636
logo := Welcome.logo
3737
usefulTasks := Welcome.tasks
3838

39-
ThisBuild / scalafixScalaBinaryVersion := scalaBinaryVersion.value
39+
ThisBuild / scalafixScalaBinaryVersion := "2.13"
4040

4141
inThisBuild(
4242
List(
4343
version ~= { dynVer =>
4444
if (isCI) dynVer
4545
else localSnapshotVersion // only for local publishing
4646
},
47-
scalaVersion := V.scala213,
48-
crossScalaVersions := List(V.scala213),
47+
scalaVersion := V.scala3,
48+
crossScalaVersions := List(V.scala3),
4949
organization := "org.scalameta",
5050
licenses := Seq(
5151
"Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")
@@ -128,7 +128,7 @@ commands ++= Seq(
128128
runMtagsPublishLocal(st, v, localSnapshotVersion)
129129
}
130130
"interfaces/publishLocal" ::
131-
s"++${V.scala213} metals/publishLocal" ::
131+
s"++${V.scala3} metals/publishLocal" ::
132132
"mtags-java/publishLocal" ::
133133
publishMtags
134134
},
@@ -218,6 +218,27 @@ val sharedSettings = sharedJavacOptions ++ sharedScalacOptions ++ List(
218218
)
219219
),
220220
),
221+
excludeDependencies ++= crossSetting(
222+
scalaVersion.value,
223+
if3 = {
224+
// Exclude cross published version dependencies leading to conflicts in Scala 3 vs 2.13
225+
// When using Scala 3 exclude Scala 2.13 standard native libraries,
226+
// when using Scala 2.13 exclude Scala 3 standard native libraries
227+
// Use full name, Maven style published artifacts cannot use artifact/cross version for exclusion rules
228+
List(
229+
ExclusionRule()
230+
.withOrganization("org.scala-lang.modules")
231+
.withName(
232+
"scala-collection-compat_2.13"
233+
),
234+
ExclusionRule()
235+
.withOrganization("org.scala-lang.modules")
236+
.withName(
237+
"scala-xml_2.13"
238+
),
239+
)
240+
},
241+
),
221242
scalacOptions ++= lintingOptions(scalaVersion.value),
222243
)
223244

@@ -284,21 +305,19 @@ def multiScalaDirectories(root: File, scalaVersion: String) = {
284305
result.toList
285306
}
286307

287-
def scala3ScalametaDependency =
288-
("org.scalameta" %% "scalameta" % V.scalameta)
289-
.cross(CrossVersion.for3Use2_13)
290-
.exclude("org.scala-lang", "scala-reflect")
291-
.exclude("org.scala-lang", "scala-compiler")
292-
// the correct one should be brought in by the scala 3 compiler
293-
.exclude("org.scala-lang", "scala-library")
294-
.exclude(
295-
"com.lihaoyi",
296-
"geny_2.13",
297-
) // avoid 2.13 and 3 on the classpath since we rely on it directly
298-
.exclude(
299-
"com.lihaoyi",
300-
"sourcecode_2.13",
301-
) // avoid 2.13 and 3 on the classpath since it comes in via pprint
308+
def scalametaDependency = ("org.scalameta" %% "scalameta" % V.scalameta)
309+
.cross(CrossVersion.for3Use2_13)
310+
.exclude("org.scala-lang", "scala-reflect")
311+
.exclude("org.scala-lang", "scala-compiler")
312+
.exclude("org.scala-lang.modules", "scala-collection-compat")
313+
.exclude(
314+
"com.lihaoyi",
315+
"geny_2.13",
316+
) // avoid 2.13 and 3 on the classpath since we rely on it directly
317+
.exclude(
318+
"com.lihaoyi",
319+
"sourcecode_2.13",
320+
)
302321

303322
val mtagsSettings = List(
304323
crossScalaVersions := V.supportedScalaVersions,
@@ -331,7 +350,7 @@ val mtagsSettings = List(
331350
),
332351
if3 = List(
333352
"org.scala-lang" %% "scala3-compiler" % scalaVersion.value,
334-
scala3ScalametaDependency,
353+
scalametaDependency,
335354
),
336355
),
337356
},
@@ -360,22 +379,22 @@ val mtagsSettings = List(
360379
},
361380
)
362381

363-
lazy val mtags3 = project
382+
lazy val mtags2 = project
364383
.in(file(".mtags"))
365384
.settings(
366385
Compile / unmanagedSourceDirectories := Seq(),
367386
sharedSettings,
368387
mtagsSettings,
369388
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags" / "src" / "main" / "scala",
370389
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags-shared" / "src" / "main" / "scala",
371-
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags-shared" / "src" / "main" / "scala-3",
372-
moduleName := "mtags3",
373-
scalaVersion := V.scala3,
374-
target := (ThisBuild / baseDirectory).value / "mtags" / "target" / "target3",
390+
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "mtags-shared" / "src" / "main" / "scala-2.13",
391+
moduleName := "mtags2",
392+
scalaVersion := V.scala213,
393+
target := (ThisBuild / baseDirectory).value / "mtags" / "target" / "target2",
375394
publish / skip := true,
376395
libraryDependencies += V.guava,
377396
scalafixConfig := Some(
378-
(ThisBuild / baseDirectory).value / ".scalafix3.conf"
397+
(ThisBuild / baseDirectory).value / ".scalafix2.conf"
379398
),
380399
)
381400
.dependsOn(interfaces)
@@ -421,7 +440,8 @@ lazy val metals = project
421440
// for BSP
422441
"org.scala-sbt.ipcsocket" % "ipcsocket" % "1.6.2",
423442
"ch.epfl.scala" % "bsp4j" % V.bsp,
424-
"ch.epfl.scala" %% "bloop-launcher-core" % V.bloop,
443+
("ch.epfl.scala" %% "bloop-launcher-core" % V.bloop)
444+
.cross(CrossVersion.for3Use2_13),
425445
// for LSP
426446
V.lsp4j,
427447
// for DAP
@@ -451,14 +471,20 @@ lazy val metals = project
451471
// Scala dependencies
452472
// ==================
453473
"org.scalameta" % "mdoc-interfaces" % V.mdoc,
454-
"org.scalameta" %% "scalafmt-dynamic" % V.scalafmt,
474+
("org.scalameta" %% "scalafmt-dynamic" % V.scalafmt)
475+
.cross(CrossVersion.for3Use2_13),
476+
"com.googlecode.java-diff-utils" % "diffutils" % "1.3.0",
455477
"ch.epfl.scala" % "scalafix-interfaces" % V.scalafix,
456478
// For reading classpaths.
457479
// for fetching ch.epfl.scala:bloop-frontend and other library dependencies
458480
"io.get-coursier" % "interface" % V.coursierInterfaces,
459481
// for comparing versions && fetching from sbt maven repository
460-
"io.get-coursier" %% "coursier" % V.coursier,
461-
"io.get-coursier" %% "coursier-sbt-maven-repository" % V.coursier,
482+
("io.get-coursier" %% "versions" % "0.3.2")
483+
.cross(CrossVersion.for3Use2_13),
484+
("io.get-coursier" %% "coursier-sbt-maven-repository" % V.coursier)
485+
.cross(CrossVersion.for3Use2_13),
486+
("io.get-coursier" %% "coursier" % V.coursier)
487+
.cross(CrossVersion.for3Use2_13),
462488
// for logging
463489
"com.outr" %% "scribe" % V.scribe,
464490
"com.outr" %% "scribe-file" % V.scribe,
@@ -467,13 +493,11 @@ lazy val metals = project
467493
"com.lihaoyi" %% "ujson" % "3.3.1",
468494
// For fetching projects' templates
469495
"com.lihaoyi" %% "requests" % "0.8.3",
470-
// for producing SemanticDB from Scala source files, to be sure we want the same version of scalameta
471-
"org.scalameta" %% "scalameta" % V.semanticdb(scalaVersion.value),
472-
"org.scalameta" % "semanticdb-scalac-core" % V.semanticdb(
473-
scalaVersion.value
474-
) cross CrossVersion.full,
496+
// for producing SemanticDB from Scala source files
497+
scalametaDependency,
475498
// For starting Ammonite
476-
"io.github.alexarchambault.ammonite" %% "ammonite-runner" % "0.4.0",
499+
("io.github.alexarchambault.ammonite" %% "ammonite-runner" % "0.4.0")
500+
.cross(CrossVersion.for3Use2_13),
477501
"org.scala-lang.modules" %% "scala-xml" % "2.3.0",
478502
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4",
479503
("org.virtuslab.scala-cli" % "scala-cli-bsp" % V.scalaCli)
@@ -543,6 +567,7 @@ lazy val input = project
543567
.in(file("tests/input"))
544568
.settings(
545569
sharedSettings,
570+
scalaVersion := V.scala213,
546571
scalacOptions -= "-Xsource:3",
547572
publish / skip := true,
548573
libraryDependencies ++= List(
@@ -719,6 +744,7 @@ lazy val metalsDependencies = project
719744
.in(file("target/.dependencies"))
720745
.settings(
721746
publish / skip := true,
747+
scalaVersion := V.scala213,
722748
// silent the intransitive dependency warning
723749
publishMavenStyle := false,
724750
libraryDependencies ++= List(
@@ -749,8 +775,10 @@ lazy val unit = project
749775
sharedSettings,
750776
Test / javaOptions += "-Xmx2G",
751777
libraryDependencies ++= List(
752-
"io.get-coursier" %% "coursier" % V.coursier, // for jars
753-
"ch.epfl.scala" %% "bloop-config" % V.bloopConfig,
778+
("io.get-coursier" %% "coursier" % V.coursier)
779+
.cross(CrossVersion.for3Use2_13), // for jars
780+
("ch.epfl.scala" %% "bloop-config" % V.bloopConfig)
781+
.cross(CrossVersion.for3Use2_13),
754782
"org.scalameta" %% "munit" % V.munit,
755783
),
756784
buildInfoPackage := "tests",

metals-bench/src/main/scala/bench/MetalsBench.scala

-43
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
package bench
22

3-
import scala.reflect.internal.util.BatchSourceFile
4-
import scala.reflect.io.VirtualFile
5-
import scala.tools.nsc.interactive.Global
6-
73
import scala.meta.dialects
8-
import scala.meta.interactive.InteractiveSemanticdb
94
import scala.meta.internal.metals.EmptyReportContext
105
import scala.meta.internal.metals.IdentifierIndex
116
import scala.meta.internal.metals.JdkSources
@@ -22,7 +17,6 @@ import scala.meta.internal.mtags.SemanticdbClasspath
2217
import scala.meta.internal.parsing.Trees
2318
import scala.meta.internal.semanticdb.TextDocument
2419
import scala.meta.internal.tokenizers.LegacyScanner
25-
import scala.meta.internal.tokenizers.LegacyToken
2620
import scala.meta.io.AbsolutePath
2721
import scala.meta.io.Classpath
2822

@@ -128,22 +122,6 @@ class MetalsBench {
128122
}
129123
}
130124

131-
@Benchmark
132-
@BenchmarkMode(Array(Mode.SingleShotTime))
133-
def scalacTokenize(): Unit = {
134-
val g = global
135-
scalaDependencySources.foreach { input =>
136-
val unit = new g.CompilationUnit(
137-
new BatchSourceFile(new VirtualFile(input.path), input.chars)
138-
)
139-
val scanner = g.newUnitScanner(unit)
140-
scanner.init()
141-
while (scanner.token != LegacyToken.EOF) {
142-
scanner.nextToken()
143-
}
144-
}
145-
}
146-
147125
@Benchmark
148126
@BenchmarkMode(Array(Mode.SingleShotTime))
149127
def scalametaParse(): Unit = {
@@ -153,27 +131,6 @@ class MetalsBench {
153131
}
154132
}
155133

156-
lazy val global: Global = InteractiveSemanticdb.newCompiler()
157-
158-
@Benchmark
159-
@BenchmarkMode(Array(Mode.SingleShotTime))
160-
def scalacParse(): Unit = {
161-
val g = global
162-
scalaDependencySources.foreach { input =>
163-
val unit = new g.CompilationUnit(
164-
new BatchSourceFile(new VirtualFile(input.path), input.chars)
165-
)
166-
val tree = g.newUnitParser(unit).parse()
167-
var i = 0
168-
new g.Traverser {
169-
override def apply[T <: g.Tree](tree: T): T = {
170-
i += 1
171-
super.apply(tree)
172-
}
173-
}.traverse(tree)
174-
}
175-
}
176-
177134
@Benchmark
178135
@BenchmarkMode(Array(Mode.SingleShotTime))
179136
def mtagsJavaParse(): Unit = {

metals/src/main/scala/scala/meta/internal/bsp/BspConfigGenerator.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import scala.meta.internal.builds.BuildServerProvider
1212
import scala.meta.internal.builds.ShellRunner
1313
import scala.meta.internal.metals.Directories
1414
import scala.meta.internal.metals.Messages.BspProvider
15-
import scala.meta.internal.metals.MetalsEnrichments._
16-
import scala.meta.internal.metals.StatusBar
1715
import scala.meta.internal.metals.UserConfiguration
16+
import scala.meta.internal.metals.StatusBar
17+
import scala.meta.internal.metals.MetalsEnrichments.given
1818
import scala.meta.internal.metals.clients.language.MetalsLanguageClient
1919
import scala.meta.io.AbsolutePath
2020

@@ -75,7 +75,7 @@ final class BspConfigGenerator(
7575
buildTools: List[BuildServerProvider]
7676
): Future[(BuildServerProvider, BspConfigGenerationStatus)] = {
7777
for {
78-
Some(buildTool) <- chooseBuildServerProvider(buildTools)
78+
case Some(buildTool) <- chooseBuildServerProvider(buildTools)
7979
status <- buildTool.generateBspConfig(
8080
workspace,
8181
args => runUnconditionally(buildTool, args),

0 commit comments

Comments
 (0)