From c0cf7bdb3b5148b170af8c3babd49a06763ec72f Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 10:31:54 +0100 Subject: [PATCH 01/52] chore: Update scalaz-core to 7.3.8 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index 39d3f97d42..4f8776e970 100644 --- a/build.sc +++ b/build.sc @@ -72,7 +72,7 @@ object Dependencies { def scalaJsSbtTestAdapter1 = ivy"org.scala-js::scalajs-sbt-test-adapter:$scalaJs1Version" def scalaJsLogging1 = ivy"org.scala-js::scalajs-logging:1.1.1" def scalaNativeTools04 = ivy"org.scala-native::tools:0.4.16" - def scalazCore = ivy"org.scalaz::scalaz-core:7.3.7" + def scalazCore = ivy"org.scalaz::scalaz-core:7.3.8" def snailgun = ivy"io.github.alexarchambault.scala-cli.snailgun::snailgun-core:0.4.1-sc2" def sourcecode = ivy"com.lihaoyi::sourcecode:0.3.1" def svm = ivy"org.graalvm.nativeimage:svm:$graalvmVersion" From c7e56637a914bfb73c4e500bdb429e6dcd67acf7 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Thu, 16 Nov 2023 19:30:10 +0100 Subject: [PATCH 02/52] bugfix: Make sure proper runtime classpath is used when debugging Previously, we would use the default config, which would not always be correct. Now, we use runtime config with a fallback to normal platform config. --- .../main/scala/bloop/dap/BloopDebuggee.scala | 10 +-- .../scala/bloop/dap/DebugServerSpec.scala | 81 ++++++++++++++++++- .../test/scala/bloop/util/TestProject.scala | 5 +- 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala b/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala index b7614c72de..81ee81a6fc 100644 --- a/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala +++ b/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala @@ -155,7 +155,7 @@ object BloopDebuggeeRunner { modules, libraries, unmanagedEntries, - jvm.config, + jvm.runtimeConfig.getOrElse(jvm.config), state, ioScheduler, project.scalaInstance.map(_.version) @@ -184,8 +184,8 @@ object BloopDebuggeeRunner { val modules = getModules(dag, state.client) val libraries = getLibraries(dag) val unmanagedEntries = getUnmanagedEntries(project, dag, state.client, modules ++ libraries) - val Platform.Jvm(config, _, _, _, _, _) = project.platform - val javaRuntime = JavaRuntime(config.javaHome.underlying) + val Platform.Jvm(config, _, _, runtimeConfig, _, _) = project.platform + val javaRuntime = JavaRuntime(runtimeConfig.getOrElse(config).javaHome.underlying) Right( new TestSuiteDebugAdapter( projects, @@ -229,8 +229,8 @@ object BloopDebuggeeRunner { val libraries = getLibraries(dag) val modules = getModules(dag, state.client) val unmanagedEntries = getUnmanagedEntries(project, dag, state.client, modules ++ libraries) - val Platform.Jvm(config, _, _, _, _, _) = project.platform - val javaRuntime = JavaRuntime(config.javaHome.underlying) + val Platform.Jvm(config, _, _, runtimeConfig, _, _) = project.platform + val javaRuntime = JavaRuntime(runtimeConfig.getOrElse(config).javaHome.underlying) new AttachRemoteDebugAdapter( modules, libraries, diff --git a/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala b/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala index e27b1527e6..e1fd750667 100644 --- a/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala +++ b/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala @@ -7,6 +7,7 @@ import java.util.NoSuchElementException import java.util.concurrent.TimeUnit.MILLISECONDS import java.util.concurrent.TimeUnit.SECONDS +import scala.collection.JavaConverters._ import scala.collection.mutable import scala.concurrent.Future import scala.concurrent.Promise @@ -14,17 +15,18 @@ import scala.concurrent.TimeoutException import scala.concurrent.duration.Duration import scala.concurrent.duration.FiniteDuration +import ch.epfl.scala.bsp import ch.epfl.scala.bsp.ScalaMainClass import ch.epfl.scala.debugadapter._ import bloop.ScalaInstance -import ch.epfl.scala.bsp import bloop.cli.ExitStatus import bloop.data.Platform import bloop.data.Project import bloop.engine.State import bloop.engine.tasks.RunMode import bloop.engine.tasks.Tasks +import bloop.internal.build import bloop.internal.build.BuildTestInfo import bloop.io.AbsolutePath import bloop.io.Environment.lineSeparator @@ -42,6 +44,8 @@ import bloop.util.TestUtil import com.microsoft.java.debug.core.protocol.Requests.SetBreakpointArguments import com.microsoft.java.debug.core.protocol.Types import com.microsoft.java.debug.core.protocol.Types.SourceBreakpoint +import coursierapi.Dependency +import coursierapi.Fetch import monix.execution.Ack import monix.reactive.Observer @@ -207,6 +211,81 @@ object DebugServerSpec extends DebugBspBaseSuite { } } + testTask( + "runs-correct-runtime", + FiniteDuration(60, SECONDS) + ) { + TestUtil.withinWorkspace { workspace => + val runtimeClasspath = Fetch + .create() + .addDependencies( + Dependency.of( + "ch.qos.logback", + "logback-classic", + "1.2.7" + ), + Dependency.of( + "org.scala-lang", + "scala-library", + build.BuildInfo.scalaVersion + ) + ) + .fetch() + .asScala + .map(_.toPath()) + .toList + + val main = + """|/main/scala/Main.scala + |object Main { + | def main(args: Array[String]): Unit = { + | println(s">>> hello world! <<<") + | val cn = Class.forName("ch.qos.logback.classic.Logger") + | println(s"$cn") + | } + |} + | + |""".stripMargin + + val logger = new RecordingLogger(ansiCodesSupported = false) + val project = + TestProject(workspace, "r", List(main), runtimeClasspath = Some(runtimeClasspath)) + + loadBspStateWithTask(workspace, List(project), logger) { state => + val runner = mainRunner( + project, + state, + arguments = Nil, + jvmOptions = Nil, + environmentVariables = Nil + ) + + startDebugServer(runner) { server => + for { + client <- server.startConnection + _ <- client.initialize() + _ <- client.launch(noDebug = true) + _ <- client.configurationDone() + _ <- client.exited + _ <- client.terminated + _ <- Task.fromFuture(client.closedPromise.future) + output <- client.takeCurrentOutput + } yield { + assert(client.socket.isClosed) + assertNoDiff( + output.linesIterator + .filterNot(_.contains("ERROR: JDWP Unable to get JNI 1.2 environment")) + .filterNot(_.contains("JDWP exit error AGENT_ERROR_NO_JNI_ENV")) + .mkString(lineSeparator), + """|>>> hello world! <<< + |class ch.qos.logback.classic.Logger""".stripMargin + ) + } + } + } + } + } + testTask("supports scala and java breakpoints", FiniteDuration(60, SECONDS)) { TestUtil.withinWorkspace { workspace => object Sources { diff --git a/frontend/src/test/scala/bloop/util/TestProject.scala b/frontend/src/test/scala/bloop/util/TestProject.scala index 81811d907c..b55ba3a387 100644 --- a/frontend/src/test/scala/bloop/util/TestProject.scala +++ b/frontend/src/test/scala/bloop/util/TestProject.scala @@ -107,6 +107,7 @@ abstract class BaseTestProject { scalaVersion: Option[String] = None, resources: List[String] = Nil, runtimeResources: Option[List[String]] = None, + runtimeClasspath: Option[List[Path]] = None, jvmConfig: Option[Config.JvmConfig] = None, runtimeJvmConfig: Option[Config.JvmConfig] = None, order: Config.CompileOrder = Config.Mixed, @@ -136,7 +137,7 @@ abstract class BaseTestProject { mkScalaInstance(finalScalaOrg, finalScalaCompiler, scalaVersion, jars.toList, NoopLogger) val allJars = instance.allJars.map(AbsolutePath.apply) - val (compileClasspath, runtimeClasspath) = { + val (compileClasspath, runtimeClasspathForStrict) = { val transitiveClasspath = (directDependencies.flatMap(classpathDeps) ++ allJars ++ jars).map(_.underlying) val directClasspath = @@ -170,7 +171,7 @@ abstract class BaseTestProject { javaConfig, None, runtimeJvmConfig, - Some(runtimeClasspath), + runtimeClasspath.orElse(Some(runtimeClasspathForStrict)), runtimeResourcesList ) From 67ea1ded96fad25bef6ac4cd7061896b37442402 Mon Sep 17 00:00:00 2001 From: Arthur McGibbon Date: Sun, 19 Nov 2023 15:30:58 +0000 Subject: [PATCH 03/52] Implement buildTargetDependencyModules --- .../scala/bloop/bsp/BloopBspServices.scala | 55 ++++++++++++++++- .../test/scala/bloop/bsp/BspBaseSuite.scala | 16 +++++ .../scala/bloop/bsp/BspProtocolSpec.scala | 60 +++++++++++++++++++ .../test/scala/bloop/bsp/TestConstants.scala | 1 + 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala b/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala index 634d8b0e9b..cad8371618 100644 --- a/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala +++ b/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala @@ -139,6 +139,7 @@ final class BloopBspServices( .requestAsync(endpoints.BuildTarget.scalaMainClasses)(p => schedule(scalaMainClasses(p))) .requestAsync(endpoints.BuildTarget.scalaTestClasses)(p => schedule(scalaTestClasses(p))) .requestAsync(endpoints.BuildTarget.dependencySources)(p => schedule(dependencySources(p))) + .requestAsync(endpoints.BuildTarget.dependencyModules)(p => schedule(dependencyModules(p))) .requestAsync(endpoints.DebugSession.start)(p => schedule(startDebugSession(p))) .requestAsync(endpoints.BuildTarget.jvmTestEnvironment)(p => schedule(jvmTestEnvironment(p))) .requestAsync(endpoints.BuildTarget.jvmRunEnvironment)(p => schedule(jvmRunEnvironment(p))) @@ -308,7 +309,7 @@ final class BloopBspServices( debugProvider = Some(BloopBspServices.DefaultDebugProvider), inverseSourcesProvider = Some(true), dependencySourcesProvider = Some(true), - dependencyModulesProvider = None, + dependencyModulesProvider = Some(true), resourcesProvider = Some(true), outputPathsProvider = None, buildTargetChangedProvider = Some(false), @@ -1205,6 +1206,58 @@ final class BloopBspServices( } } + def dependencyModules( + request: bsp.DependencyModulesParams + ): BspEndpointResponse[bsp.DependencyModulesResult] = { + def modules( + projects: Seq[ProjectMapping], + state: State + ): BspResult[bsp.DependencyModulesResult] = { + val response = bsp.DependencyModulesResult( + projects.iterator.map { + case (target, project) => + val modules = project.resolution.toList.flatMap { res => + res.modules.map { module => + val mavenDependencyModule = bsp.MavenDependencyModule( + module.organization, + module.name, + module.version, + module.artifacts.map(artifact => + bsp.MavenDependencyModuleArtifact( + bsp.Uri(AbsolutePath(artifact.path).toBspUri), + artifact.classifier + ) + ), + None + ) + + val encoded = writeToArray(mavenDependencyModule) + bsp.DependencyModule( + module.name, + module.version, + Some(bsp.DependencyModuleDataKind.Maven), + Some(RawJson(encoded)) + ) + } + }.distinct + bsp.DependencyModulesItem(target, modules) + }.toList + ) + + Task.now((state, Right(response))) + } + + ifInitialized(None) { (state: State, logger: BspServerLogger) => + mapToProjects(request.targets, state) match { + case Left(error) => + // Log the mapping error to the user via a log event + an error status code + logger.error(error) + Task.now((state, Right(bsp.DependencyModulesResult(Nil)))) + case Right(mappings) => modules(mappings, state) + } + } + } + def dependencySources( request: bsp.DependencySourcesParams ): BspEndpointResponse[bsp.DependencySourcesResult] = { diff --git a/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala b/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala index 6cc6ce0f57..544f662e50 100644 --- a/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala +++ b/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala @@ -349,6 +349,22 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { TestUtil.await(FiniteDuration(5, "s"))(resourcesTask) } + def requestDependencyModules(project: TestProject): bsp.DependencyModulesResult = { + val dependencyModulesTask = { + client0 + .request( + endpoints.BuildTarget.dependencyModules, + bsp.DependencyModulesParams(List(project.bspId)) + ) + .map { + case RpcFailure(_, error) => fail(s"Received error ${error}") + case RpcSuccess(modules, _) => modules + } + } + + TestUtil.await(FiniteDuration(5, "s"))(dependencyModulesTask) + } + def requestDependencySources(project: TestProject): bsp.DependencySourcesResult = { val dependencySourcesTask = { client0 diff --git a/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala b/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala index be51b1de20..51ec49ae91 100644 --- a/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala +++ b/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala @@ -516,6 +516,66 @@ class BspProtocolSpec( } } + test("dependency modules request works") { + TestUtil.withinWorkspace { workspace => + val logger = new RecordingLogger(ansiCodesSupported = false) + loadBspBuildFromResources("cross-test-build-scalajs-0.6", workspace, logger) { build => + val mainProject = build.projectFor("test-project") + val testProject = build.projectFor("test-project-test") + val mainJsProject = build.projectFor("test-projectJS") + val testJsProject = build.projectFor("test-projectJS-test") + val rootMain = build.projectFor("cross-test-build-scalajs-0-6") + val rootTest = build.projectFor("cross-test-build-scalajs-0-6-test") + + def checkDependencyModules(project: TestProject): Unit = { + val dependencyModulesResult = build.state.requestDependencyModules(project) + assert(dependencyModulesResult.items.size == 1) + val dependencyModules = dependencyModulesResult.items.flatMap(item => + item.modules + .map(dependencyModule => { + val json = dependencyModule.data.get + val mavenModule = readFromArray[bsp.MavenDependencyModule](json.value) + val artifacts: List[Config.Artifact] = mavenModule.artifacts + .map(artifact => + Config.Artifact( + dependencyModule.name, + artifact.classifier, + None, + artifact.uri.toPath + ) + ) + .distinct; + new Config.Module( + mavenModule.organization, + mavenModule.name, + mavenModule.version, + None, + artifacts + ) + }) + .distinct + ) + + val expectedModules = project.config.resolution.toList.flatMap { res => + res.modules.map { m => + val artifacts = m.artifacts.map(artifact => artifact.copy(checksum = None)) + m.copy(configurations = None, artifacts = artifacts) + } + }.distinct + + assertEquals(dependencyModules, expectedModules) + } + + checkDependencyModules(mainProject) + checkDependencyModules(testProject) + checkDependencyModules(mainJsProject) + checkDependencyModules(testJsProject) + checkDependencyModules(rootMain) + checkDependencyModules(rootTest) + } + } + } + test("dependency sources request works") { TestUtil.withinWorkspace { workspace => val logger = new RecordingLogger(ansiCodesSupported = false) diff --git a/frontend/src/test/scala/bloop/bsp/TestConstants.scala b/frontend/src/test/scala/bloop/bsp/TestConstants.scala index db3b4359b2..f3699b62e6 100644 --- a/frontend/src/test/scala/bloop/bsp/TestConstants.scala +++ b/frontend/src/test/scala/bloop/bsp/TestConstants.scala @@ -16,6 +16,7 @@ object TestConstants { "debugProvider": { "languageIds": ["scala", "java"] }, "inverseSourcesProvider": true, "dependencySourcesProvider": true, + "dependencyModulesProvider": true, "resourcesProvider": true, "buildTargetChangedProvider": false, "jvmRunEnvironmentProvider": true, From 1efba78cc84103a47b2a932ffa8631bfe36a294b Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:07:53 +0100 Subject: [PATCH 04/52] Update scala debug adapter to 3.1.5 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index 4f8776e970..6292417faf 100644 --- a/build.sc +++ b/build.sc @@ -64,7 +64,7 @@ object Dependencies { def pprint = ivy"com.lihaoyi::pprint:0.8.1" def sbtTestAgent = ivy"org.scala-sbt:test-agent:1.9.7" def sbtTestInterface = ivy"org.scala-sbt:test-interface:1.0" - def scalaDebugAdapter = ivy"ch.epfl.scala::scala-debug-adapter:3.1.4" + def scalaDebugAdapter = ivy"ch.epfl.scala::scala-debug-adapter:3.1.5" def scalaJsLinker1 = ivy"org.scala-js::scalajs-linker:$scalaJs1Version" def scalaJsEnvs1 = ivy"org.scala-js::scalajs-js-envs:$scalaJsEnvsVersion" def scalaJsEnvNode1 = ivy"org.scala-js::scalajs-env-nodejs:$scalaJsEnvsVersion" From abf36a52c4036b515d99a7e50f44fac8167f0c80 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:08:43 +0100 Subject: [PATCH 05/52] Update scala log4j to 2.22.0 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index 6292417faf..eaa2720d7d 100644 --- a/build.sc +++ b/build.sc @@ -54,7 +54,7 @@ object Dependencies { def junit = ivy"com.github.sbt:junit-interface:0.13.3" def libdaemonjvm = ivy"io.github.alexarchambault.libdaemon::libdaemon:0.0.11" def libraryManagement = ivy"org.scala-sbt::librarymanagement-ivy:1.9.3" - def log4j = ivy"org.apache.logging.log4j:log4j-core:2.21.1" + def log4j = ivy"org.apache.logging.log4j:log4j-core:2.22.0" def logback = ivy"ch.qos.logback:logback-classic:1.4.6" def macroParadise = ivy"org.scalamacros:::paradise:2.1.1" def monix = ivy"io.monix::monix:3.2.0" From 82ad3a237ab64b13ffd63979f5926e3504a897a0 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:09:46 +0100 Subject: [PATCH 06/52] Update scalafmt to 3.7.17 --- .scalafmt.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index 09ae845903..e92cb45745 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = "3.7.15" +version = "3.7.17" align.preset = more maxColumn = 100 From 57e567c553a0895aadc235cfa322871dd699bb56 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:10:41 +0100 Subject: [PATCH 07/52] Update zupkin-sender-urlconnection to 2.16.5 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index eaa2720d7d..d04a4633e2 100644 --- a/build.sc +++ b/build.sc @@ -79,7 +79,7 @@ object Dependencies { def utest = ivy"com.lihaoyi::utest:0.8.2" def xxHashLibrary = ivy"net.jpountz.lz4:lz4:1.3.0" def zinc = ivy"org.scala-sbt::zinc:1.9.5" - def zipkinSender = ivy"io.zipkin.reporter2:zipkin-sender-urlconnection:2.16.4" + def zipkinSender = ivy"io.zipkin.reporter2:zipkin-sender-urlconnection:2.16.5" def zt = ivy"org.zeroturnaround:zt-zip:1.16" def graalVmId = s"graalvm-java17:$graalvmVersion" From 875b0268e6247157722bee803521a8180fb127e0 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Tue, 12 Dec 2023 19:26:02 +0100 Subject: [PATCH 08/52] improvement: Change information about test framework to warn Previously, this would be set to error, which would mean Metals would show it to the users more prominently. Now, we change it to warn, which means it's still present, but since this might be actually be related to non compiled code, it's prominence is reduced, --- bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala b/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala index 86877f94d5..c2893a9766 100644 --- a/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala +++ b/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala @@ -169,7 +169,7 @@ object JsBridge { val result = adapter.loadFrameworks(frameworkNames).flatMap(_.toList) (result, () => adapter.close()) } else { - logger.error( + logger.warn( s"Cannot discover test frameworks, missing node_modules in test project, expected them at $nodeModules" ) (Nil, () => ()) From da9f796b182345573d47c7120a61ee8b94d0efc4 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:11:07 +0100 Subject: [PATCH 09/52] Update zupkin-sender-urlconnection to 2.17.0 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index d04a4633e2..5f51b51e26 100644 --- a/build.sc +++ b/build.sc @@ -79,7 +79,7 @@ object Dependencies { def utest = ivy"com.lihaoyi::utest:0.8.2" def xxHashLibrary = ivy"net.jpountz.lz4:lz4:1.3.0" def zinc = ivy"org.scala-sbt::zinc:1.9.5" - def zipkinSender = ivy"io.zipkin.reporter2:zipkin-sender-urlconnection:2.16.5" + def zipkinSender = ivy"io.zipkin.reporter2:zipkin-sender-urlconnection:2.17.0" def zt = ivy"org.zeroturnaround:zt-zip:1.16" def graalVmId = s"graalvm-java17:$graalvmVersion" From a301dd522927f2baba60827a3fba4bbe569bcae3 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:11:38 +0100 Subject: [PATCH 10/52] Update sbt test agent to 1.9.8 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index 5f51b51e26..a2a36cbbc7 100644 --- a/build.sc +++ b/build.sc @@ -62,7 +62,7 @@ object Dependencies { def nailgun = ivy"io.github.alexarchambault.bleep:nailgun-server:1.0.7" def osLib = ivy"com.lihaoyi::os-lib:0.9.0" def pprint = ivy"com.lihaoyi::pprint:0.8.1" - def sbtTestAgent = ivy"org.scala-sbt:test-agent:1.9.7" + def sbtTestAgent = ivy"org.scala-sbt:test-agent:1.9.8" def sbtTestInterface = ivy"org.scala-sbt:test-interface:1.0" def scalaDebugAdapter = ivy"ch.epfl.scala::scala-debug-adapter:3.1.5" def scalaJsLinker1 = ivy"org.scala-js::scalajs-linker:$scalaJs1Version" From 17758c269f2ba0a472f7dfceeddd4de6162c6668 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Fri, 15 Dec 2023 19:58:45 +0100 Subject: [PATCH 11/52] Don't show warning when using the correct version of JDK --- backend/src/main/scala/bloop/Compiler.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/main/scala/bloop/Compiler.scala b/backend/src/main/scala/bloop/Compiler.scala index 70f0d76f16..ac56c5b587 100644 --- a/backend/src/main/scala/bloop/Compiler.scala +++ b/backend/src/main/scala/bloop/Compiler.scala @@ -637,12 +637,14 @@ object Compiler { val bloopNumVer = JavaRuntime.version.takeWhile(_.isDigit).toInt if (bloopNumVer > numVer) { scalacOptions ++ List("-release", numVer.toString()) - } else { + } else if (bloopNumVer < numVer) { logger.warn( s"Bloop is runing with ${JavaRuntime.version} but your code requires $version to compile, " + "this might cause some compilation issues when using JDK API unsupported by the Bloop's current JVM version" ) scalacOptions + } else { + scalacOptions } } catch { case NonFatal(_) => From bfe0b3b5f75202f8eac286761c57080ee1cc9e44 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:12:20 +0100 Subject: [PATCH 12/52] Update brave to 5.17.0 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index a2a36cbbc7..6c75e898fc 100644 --- a/build.sc +++ b/build.sc @@ -33,7 +33,7 @@ object Dependencies { def asm = ivy"org.ow2.asm:asm:$asmVersion" def asmUtil = ivy"org.ow2.asm:asm-util:$asmVersion" def bloopConfig = ivy"ch.epfl.scala::bloop-config:1.5.5" - def brave = ivy"io.zipkin.brave:brave:5.16.0" + def brave = ivy"io.zipkin.brave:brave:5.17.0" def bsp4j = ivy"ch.epfl.scala:bsp4j:2.1.0-M7" def bsp4s = ivy"ch.epfl.scala::bsp4s:2.1.0-M7" def caseApp = ivy"com.github.alexarchambault::case-app:2.0.6" From 659251add798ae609a5e54e83310d810bbfbdcbd Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:12:49 +0100 Subject: [PATCH 13/52] Update zupkin-sender-urlconnection to 2.17.1 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index 6c75e898fc..0a87a99c93 100644 --- a/build.sc +++ b/build.sc @@ -79,7 +79,7 @@ object Dependencies { def utest = ivy"com.lihaoyi::utest:0.8.2" def xxHashLibrary = ivy"net.jpountz.lz4:lz4:1.3.0" def zinc = ivy"org.scala-sbt::zinc:1.9.5" - def zipkinSender = ivy"io.zipkin.reporter2:zipkin-sender-urlconnection:2.17.0" + def zipkinSender = ivy"io.zipkin.reporter2:zipkin-sender-urlconnection:2.17.1" def zt = ivy"org.zeroturnaround:zt-zip:1.16" def graalVmId = s"graalvm-java17:$graalvmVersion" From e386dc79da20f1d9f4a1956d4799f94e2ac6b926 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Mar 2024 14:13:15 +0100 Subject: [PATCH 14/52] Update scala log4j to 2.22.1 --- build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sc b/build.sc index 0a87a99c93..6429028a92 100644 --- a/build.sc +++ b/build.sc @@ -54,7 +54,7 @@ object Dependencies { def junit = ivy"com.github.sbt:junit-interface:0.13.3" def libdaemonjvm = ivy"io.github.alexarchambault.libdaemon::libdaemon:0.0.11" def libraryManagement = ivy"org.scala-sbt::librarymanagement-ivy:1.9.3" - def log4j = ivy"org.apache.logging.log4j:log4j-core:2.22.0" + def log4j = ivy"org.apache.logging.log4j:log4j-core:2.22.1" def logback = ivy"ch.qos.logback:logback-classic:1.4.6" def macroParadise = ivy"org.scalamacros:::paradise:2.1.1" def monix = ivy"io.monix::monix:3.2.0" From d4943b9031a4897a325abad3fc08d023af058ffc Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Dec 2023 20:13:14 +0100 Subject: [PATCH 15/52] refactor: Remove forked parts of scala js envs As far as I can see this should work properly and it hits us even more to have duplicated part of code that is not maintained. --- .../main/scala/bloop/scalajs/JsBridge.scala | 40 +-- .../bloop/scalajs/jsenv/JsDomNodeJsEnv.scala | 198 ----------- .../scala/bloop/scalajs/jsenv/NodeJsEnv.scala | 308 ---------------- .../scalajs/jsenv/nodejs/BloopComRun.scala | 330 ------------------ .../scala/bloop/bsp/BloopBspServices.scala | 7 +- .../main/scala/bloop/engine/Interpreter.scala | 16 +- .../scala/bloop/engine/tasks/LinkTask.scala | 15 +- .../tasks/toolchains/ScalaJsToolchain.scala | 4 +- .../main/scala/bloop/io/AbsolutePath.scala | 3 + 9 files changed, 47 insertions(+), 874 deletions(-) delete mode 100644 bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/JsDomNodeJsEnv.scala delete mode 100644 bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/NodeJsEnv.scala delete mode 100644 bridges/scalajs-1/src/main/scala/org/scalajs/jsenv/nodejs/BloopComRun.scala diff --git a/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala b/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala index c2893a9766..b189f22055 100644 --- a/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala +++ b/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala @@ -14,12 +14,12 @@ import bloop.config.Config.ModuleKindJS import bloop.data.Project import bloop.logging.DebugFilter import bloop.logging.{Logger => BloopLogger} -import bloop.scalajs.jsenv.JsDomNodeJsEnv -import bloop.scalajs.jsenv.NodeJSConfig -import bloop.scalajs.jsenv.NodeJSEnv import org.scalajs.jsenv.Input +import org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv +import org.scalajs.jsenv.nodejs.NodeJSEnv import org.scalajs.linker.PathIRContainer +import org.scalajs.linker.PathOutputDirectory import org.scalajs.linker.PathOutputFile import org.scalajs.linker.StandardImpl import org.scalajs.linker.interface.{ModuleKind => ScalaJSModuleKind, _} @@ -27,20 +27,10 @@ import org.scalajs.logging.Level import org.scalajs.logging.{Logger => JsLogger} import org.scalajs.testing.adapter.TestAdapter import org.scalajs.testing.adapter.TestAdapterInitializer +import java.nio.file.Files /** * Defines operations provided by the Scala.JS 1.x toolchain. - * - * The 1.x js bridge needs to inline the implementation of `NodeJSEnv`, - * `JSDOMNodeJSEnv` and `ComRunner` because there is a bug in the latest - * Scala.js release that does not run `close` on the underlying process, - * skipping the destruction of the process running Scala.js tests. Aside - * from leaking, this is fatal in Windows because the underlying process - * is alive and keeps open references to the output JS file. - * - * We can remove all of the js environments and runners as soon as this - * issue is fixed upstream. Note that our 0.6.x version handles cancellation - * correctly. */ object JsBridge { private class Logger(logger: BloopLogger)(implicit filter: DebugFilter) extends JsLogger { @@ -94,13 +84,13 @@ object JsBridge { classpath: Array[Path], runMain: java.lang.Boolean, mainClass: Option[String], - target: Path, + targetDirectory: Path, logger: BloopLogger, executionContext: ExecutionContext ): Unit = { implicit val ec = executionContext implicit val logFilter: DebugFilter = DebugFilter.Link - val linker = ScalaJSLinker.reuseOrCreate(config, target) + val linker = ScalaJSLinker.reuseOrCreate(config, targetDirectory) val cache = StandardImpl.irFileCache().newCache val irContainersPairs = PathIRContainer.fromClasspath(classpath) @@ -126,11 +116,14 @@ object JsBridge { } } - val output = LinkerOutput(PathOutputFile(target)) - val resultFuture = for { libraryIRs <- libraryIrsFuture - _ <- linker.link(libraryIRs, moduleInitializers, output, new Logger(logger)) + _ <- linker.link( + libraryIRs, + moduleInitializers, + PathOutputDirectory(targetDirectory), + new Logger(logger) + ) } yield () Await.result(resultFuture, Duration.Inf) @@ -151,11 +144,12 @@ object JsBridge { if (nodeModules.toFile().exists()) { logger.debug("Node.js module path: " + nodeModules.toString()) val fullEnv = Map("NODE_PATH" -> nodeModules.toString()) ++ env - val config = - NodeJSConfig().withExecutable(nodePath).withCwd(Some(baseDirectory)).withEnv(fullEnv) val nodeEnv = - if (!jsConfig.jsdom.contains(true)) new NodeJSEnv(logger, config) - else new JsDomNodeJsEnv(logger, config) + if (!jsConfig.jsdom.contains(true)) + new NodeJSEnv( + NodeJSEnv.Config().withExecutable(nodePath).withEnv(fullEnv) + ) + else new JSDOMNodeJSEnv(JSDOMNodeJSEnv.Config().withExecutable(nodePath).withEnv(fullEnv)) // The order of the scripts mandates the load order in the JavaScript runtime val input = jsConfig.kind match { diff --git a/bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/JsDomNodeJsEnv.scala b/bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/JsDomNodeJsEnv.scala deleted file mode 100644 index 1fd0ef1cfe..0000000000 --- a/bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/JsDomNodeJsEnv.scala +++ /dev/null @@ -1,198 +0,0 @@ -package bloop.scalajs.jsenv - -import java.io.File -import java.io.InputStream -import java.net.URI -import java.nio.charset.StandardCharsets -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardCopyOption - -import scala.util.control.NonFatal - -import bloop.logging.Logger - -import com.google.common.jimfs.Jimfs -import org.scalajs.jsenv.ExternalJSRun -import org.scalajs.jsenv.Input -import org.scalajs.jsenv.JSComRun -import org.scalajs.jsenv.JSEnv -import org.scalajs.jsenv.JSRun -import org.scalajs.jsenv.JSUtils.escapeJS -import org.scalajs.jsenv.RunConfig -import org.scalajs.jsenv.UnsupportedInputException -import org.scalajs.jsenv.nodejs.BloopComRun - -/** - * See comments in [[bloop.scalajs.JsBridge]]. - * - * Adapted from `jsdom-nodejs-env/src/main/scala/org/scalajs/jsenv/jsdomnodejs/JSDOMNodeJSEnv.scala`. - */ -class JsDomNodeJsEnv(logger: Logger, config: NodeJSConfig) extends JSEnv { - private lazy val validator = ExternalJSRun.supports(RunConfig.Validator()) - - val name: String = "Node.js with jsdom" - - def start(input: Seq[Input], runConfig: RunConfig): JSRun = { - JsDomNodeJsEnv.validator.validate(runConfig) - val scripts = validateInput(input) - try { - internalStart(codeWithJSDOMContext(scripts), runConfig) - } catch { - case NonFatal(t) => - JSRun.failed(t) - } - } - - def startWithCom(input: Seq[Input], runConfig: RunConfig, onMessage: String => Unit): JSComRun = { - validator.validate(runConfig) - val scripts = validateInput(input) - BloopComRun.start(runConfig, onMessage) { comLoader => - internalStart(comLoader :: codeWithJSDOMContext(scripts), runConfig) - } - } - - private def validateInput(input: Seq[Input]): List[Path] = { - input.map { - case Input.Script(script) => - script - - case _ => - throw new UnsupportedInputException(input) - }.toList - } - - private def internalStart(files: List[Path], runConfig: RunConfig): JSRun = - NodeJSEnv.internalStart(logger, config, env)( - NodeJSEnv.write(files.map(Input.Script)), - runConfig - ) - - private def env: Map[String, String] = - Map("NODE_MODULE_CONTEXTS" -> "0") ++ config.env - - private def codeWithJSDOMContext(scripts: List[Path]): List[Path] = { - val scriptsURIs = scripts.map(JsDomNodeJsEnv.materialize) - val scriptsURIsAsJSStrings = - scriptsURIs.map(uri => "\"" + escapeJS(uri.toASCIIString) + "\"") - val scriptsURIsJSArray = scriptsURIsAsJSStrings.mkString("[", ", ", "]") - val jsDOMCode = { - s""" - | - |(function () { - | var jsdom = require("jsdom"); - | - | if (typeof jsdom.JSDOM === "function") { - | // jsdom >= 10.0.0 - | var virtualConsole = new jsdom.VirtualConsole() - | .sendTo(console, { omitJSDOMErrors: true }); - | virtualConsole.on("jsdomError", function (error) { - | try { - | // Display as much info about the error as possible - | if (error.detail && error.detail.stack) { - | console.error("" + error.detail); - | console.error(error.detail.stack); - | } else { - | console.error(error); - | } - | } finally { - | // Whatever happens, kill the process so that the run fails - | process.exit(1); - | } - | }); - | - | var dom = new jsdom.JSDOM("", { - | virtualConsole: virtualConsole, - | url: "http://localhost/", - | - | /* Allow unrestricted