From e366d286d68140372af10c1b928ebc086ca83c52 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Sun, 17 Mar 2024 15:12:59 +0100 Subject: [PATCH 1/3] Handle new `JvmCompileClasspath` request If the client report to support the `JvmCompileClasspathReceiver` capability, we also return an empty classpath from the `ScalacOptions` request. Update bsp4j from 2.2.0-M1 to 2.2.0-M2 --- .../src/mill/bsp/worker/MillBuildServer.scala | 7 +++ .../mill/bsp/worker/MillJvmBuildServer.scala | 33 ++++++++++++-- .../bsp/worker/MillScalaBuildServer.scala | 45 +++++++++++-------- build.sc | 2 +- 4 files changed, 64 insertions(+), 23 deletions(-) diff --git a/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala b/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala index 1e890f59bda..8ae3c5a279c 100644 --- a/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala +++ b/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala @@ -100,6 +100,9 @@ private class MillBuildServer( protected var clientWantsSemanticDb = false protected var clientIsIntelliJ = false + /** `true` when client and server support the `JvmCompileClasspathProvider`` request. */ + protected var enableJvmCompileClasspathProvider = false + private[this] var statePromise: Promise[State] = Promise[State]() def updateEvaluator(evaluatorsOpt: Option[Seq[Evaluator]]): Unit = { @@ -120,6 +123,9 @@ private class MillBuildServer( : CompletableFuture[InitializeBuildResult] = completableNoState(s"buildInitialize ${request}", checkInitialized = false) { + val clientCapabilities = request.getCapabilities() + enableJvmCompileClasspathProvider = clientCapabilities.getJvmCompileClasspathReceiver + // TODO: scan BspModules and infer their capabilities val supportedLangs = Seq("java", "scala").asJava @@ -138,6 +144,7 @@ private class MillBuildServer( capabilities.setResourcesProvider(true) capabilities.setRunProvider(new RunProvider(supportedLangs)) capabilities.setTestProvider(new TestProvider(supportedLangs)) + capabilities.setJvmCompileClasspathProvider(enableJvmCompileClasspathProvider) // IJ is currently not able to handle files as source paths, only dirs // TODO: Rumor has it, that newer version may handle it, so we need to better detect that diff --git a/bsp/worker/src/mill/bsp/worker/MillJvmBuildServer.scala b/bsp/worker/src/mill/bsp/worker/MillJvmBuildServer.scala index 79c574ea020..b358ddcc28e 100644 --- a/bsp/worker/src/mill/bsp/worker/MillJvmBuildServer.scala +++ b/bsp/worker/src/mill/bsp/worker/MillJvmBuildServer.scala @@ -3,6 +3,9 @@ package mill.bsp.worker import ch.epfl.scala.bsp4j.{ BuildTargetIdentifier, JvmBuildServer, + JvmCompileClasspathItem, + JvmCompileClasspathParams, + JvmCompileClasspathResult, JvmEnvironmentItem, JvmMainClass, JvmRunEnvironmentParams, @@ -22,7 +25,7 @@ private trait MillJvmBuildServer extends JvmBuildServer { this: MillBuildServer override def buildTargetJvmRunEnvironment(params: JvmRunEnvironmentParams) : CompletableFuture[JvmRunEnvironmentResult] = { jvmRunTestEnvironment( - s"jvmRunEnvironment ${params}", + s"buildTarget/jvmRunEnvironment ${params}", params.getTargets.asScala.toSeq, new JvmRunEnvironmentResult(_) ) @@ -31,7 +34,7 @@ private trait MillJvmBuildServer extends JvmBuildServer { this: MillBuildServer override def buildTargetJvmTestEnvironment(params: JvmTestEnvironmentParams) : CompletableFuture[JvmTestEnvironmentResult] = { jvmRunTestEnvironment( - s"jvmTestEnvironment ${params}", + s"buildTarget/jvmTestEnvironment ${params}", params.getTargets.asScala.toSeq, new JvmTestEnvironmentResult(_) ) @@ -41,7 +44,7 @@ private trait MillJvmBuildServer extends JvmBuildServer { this: MillBuildServer name: String, targetIds: Seq[BuildTargetIdentifier], agg: java.util.List[JvmEnvironmentItem] => V - ) = { + ): CompletableFuture[V] = { completableTasks( name, targetIds = _ => targetIds, @@ -65,7 +68,7 @@ private trait MillJvmBuildServer extends JvmBuildServer { this: MillBuildServer ev, state, id, - m: JavaModule, + _: JavaModule, (runClasspath, forkArgs, forkWorkingDir, forkEnv, mainClass, zincWorker, compile) ) => val classpath = runClasspath.map(_.path).map(sanitizeUri) @@ -84,4 +87,26 @@ private trait MillJvmBuildServer extends JvmBuildServer { this: MillBuildServer agg } } + + override def buildTargetJvmCompileClasspath(params: JvmCompileClasspathParams) + : CompletableFuture[JvmCompileClasspathResult] = + completableTasks( + hint = "buildTarget/jvmCompileClasspath", + targetIds = _ => params.getTargets.asScala.toSeq, + tasks = { + case m: JavaModule => m.bspCompileClasspath + } + ) { + case (ev, _, id, _: JavaModule, compileClasspath) => + val pathResolver = ev.pathsResolver + + new JvmCompileClasspathItem( + id, + compileClasspath.iterator + .map(_.resolve(pathResolver)) + .map(sanitizeUri).toSeq.asJava + ) + } { + new JvmCompileClasspathResult(_) + } } diff --git a/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala b/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala index 454ad9927b8..38798090829 100644 --- a/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala +++ b/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala @@ -16,7 +16,7 @@ import ch.epfl.scala.bsp4j.{ import mill.{Agg, T} import mill.bsp.worker.Utils.sanitizeUri import mill.util.Jvm -import mill.scalalib.{JavaModule, ScalaModule, SemanticDbJavaModule, TestModule} +import mill.scalalib.{JavaModule, ScalaModule, TestModule, UnresolvedPath} import mill.testrunner.{Framework, TestRunnerUtils} import sbt.testing.Fingerprint @@ -29,25 +29,34 @@ private trait MillScalaBuildServer extends ScalaBuildServer { this: MillBuildSer override def buildTargetScalacOptions(p: ScalacOptionsParams) : CompletableFuture[ScalacOptionsResult] = completableTasks( - hint = s"buildTargetScalacOptions ${p}", + hint = s"buildTarget/scalacOptions ${p}", targetIds = _ => p.getTargets.asScala.toSeq, tasks = { - case m: ScalaModule => - val classesPathTask = m match { - case sem: SemanticDbJavaModule if clientWantsSemanticDb => - sem.bspCompiledClassesAndSemanticDbFiles - case _ => m.bspCompileClassesPath + case m: JavaModule => + + val scalacOptionsTask = m match { + case m: ScalaModule => m.allScalacOptions + case _ => T.task { Seq.empty[String] } } - T.task((m.allScalacOptions(), m.bspCompileClasspath(), classesPathTask())) + val compileClasspathTask = + if (enableJvmCompileClasspathProvider) { + // We have a dedicated request for it + T.task { Agg.empty[UnresolvedPath] } + } else { + m.bspCompileClasspath + } + + val classesPathTask = + if (clientWantsSemanticDb) { + m.bspCompiledClassesAndSemanticDbFiles + } else { + m.bspCompileClassesPath + } - case m: JavaModule => - val classesPathTask = m match { - case sem: SemanticDbJavaModule if clientWantsSemanticDb => - sem.bspCompiledClassesAndSemanticDbFiles - case _ => m.bspCompileClassesPath + T.task { + (scalacOptionsTask(), compileClasspathTask(), classesPathTask()) } - T.task { (Nil, Nil, classesPathTask()) } } ) { // We ignore all non-JavaModule @@ -56,13 +65,13 @@ private trait MillScalaBuildServer extends ScalaBuildServer { this: MillBuildSer state, id, m: JavaModule, - (allScalacOptions, bspCompileClsaspath, classesPathTask) + (allScalacOptions, compileClasspath, classesPathTask) ) => val pathResolver = ev.pathsResolver new ScalacOptionsItem( id, allScalacOptions.asJava, - bspCompileClsaspath.iterator + compileClasspath.iterator .map(_.resolve(pathResolver)) .map(sanitizeUri).toSeq.asJava, sanitizeUri(classesPathTask.resolve(pathResolver)) @@ -74,7 +83,7 @@ private trait MillScalaBuildServer extends ScalaBuildServer { this: MillBuildSer override def buildTargetScalaMainClasses(p: ScalaMainClassesParams) : CompletableFuture[ScalaMainClassesResult] = completableTasks( - hint = "buildTargetScalaMainClasses", + hint = "buildTarget/scalaMainClasses", targetIds = _ => p.getTargets.asScala.toSeq, tasks = { case m: JavaModule => T.task((m.zincWorker().worker(), m.compile(), m.forkArgs(), m.forkEnv())) @@ -100,7 +109,7 @@ private trait MillScalaBuildServer extends ScalaBuildServer { this: MillBuildSer override def buildTargetScalaTestClasses(p: ScalaTestClassesParams) : CompletableFuture[ScalaTestClassesResult] = completableTasks( - s"buildTargetScalaTestClasses ${p}", + s"buildTarget/scalaTestClasses ${p}", targetIds = _ => p.getTargets.asScala.toSeq, tasks = { case m: TestModule => diff --git a/build.sc b/build.sc index 89c5579f13e..1aee81222ac 100644 --- a/build.sc +++ b/build.sc @@ -184,7 +184,7 @@ object Deps { val windowsAnsi = ivy"io.github.alexarchambault.windows-ansi:windows-ansi:0.0.5" val zinc = ivy"org.scala-sbt::zinc:1.9.6" // keep in sync with doc/antora/antory.yml - val bsp4j = ivy"ch.epfl.scala:bsp4j:2.2.0-M1" + val bsp4j = ivy"ch.epfl.scala:bsp4j:2.2.0-M2" val fansi = ivy"com.lihaoyi::fansi:0.4.0" val jarjarabrams = ivy"com.eed3si9n.jarjarabrams::jarjar-abrams-core:1.14.0" val requests = ivy"com.lihaoyi::requests:0.8.0" From cbeaf30d2ee2c27ffd3fc89937991aab3cdc523a Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Sun, 17 Mar 2024 15:15:38 +0100 Subject: [PATCH 2/3] . --- bsp/worker/src/mill/bsp/worker/MillBuildServer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala b/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala index 8ae3c5a279c..3a21d7b1e46 100644 --- a/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala +++ b/bsp/worker/src/mill/bsp/worker/MillBuildServer.scala @@ -138,13 +138,13 @@ private class MillBuildServer( capabilities.setDependencyModulesProvider(true) capabilities.setDependencySourcesProvider(true) capabilities.setInverseSourcesProvider(true) + capabilities.setJvmCompileClasspathProvider(enableJvmCompileClasspathProvider) capabilities.setJvmRunEnvironmentProvider(true) capabilities.setJvmTestEnvironmentProvider(true) capabilities.setOutputPathsProvider(true) capabilities.setResourcesProvider(true) capabilities.setRunProvider(new RunProvider(supportedLangs)) capabilities.setTestProvider(new TestProvider(supportedLangs)) - capabilities.setJvmCompileClasspathProvider(enableJvmCompileClasspathProvider) // IJ is currently not able to handle files as source paths, only dirs // TODO: Rumor has it, that newer version may handle it, so we need to better detect that From d76ae3022b3d6ed6600d49ce1d78abd87cf91834 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Sun, 17 Mar 2024 21:14:41 +0100 Subject: [PATCH 3/3] scalafmt --- bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala b/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala index 38798090829..2f9610dbe68 100644 --- a/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala +++ b/bsp/worker/src/mill/bsp/worker/MillScalaBuildServer.scala @@ -33,7 +33,6 @@ private trait MillScalaBuildServer extends ScalaBuildServer { this: MillBuildSer targetIds = _ => p.getTargets.asScala.toSeq, tasks = { case m: JavaModule => - val scalacOptionsTask = m match { case m: ScalaModule => m.allScalacOptions case _ => T.task { Seq.empty[String] }