Skip to content

Start of using bloop rifle #678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: idea251.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions .idea/kotlinc.xml
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont understand why this file was edited at all.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bsp-builtin/bsp/src/org/jetbrains/bsp/BSPCli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import java.nio.file.Path
import java.util
import java.util.concurrent.CompletableFuture
import java.util.{Collections, UUID}
import scala.annotation.nowarn
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.io.StdIn
Expand Down Expand Up @@ -188,6 +189,7 @@ object BSPCli extends App {
}


@nowarn("cat=deprecation")
def testClasses(targets: BuildIds)(server: BspServer): CompletableFuture[ScalaTestClassesResult] = {
val params = new bsp4j.ScalaTestClassesParams(targets)
params.setOriginId(UUID.randomUUID().toString)
Expand Down
6 changes: 4 additions & 2 deletions bsp-builtin/bsp/src/org/jetbrains/bsp/project/BspTask.scala
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ class BspTask[T](project: Project,
else {
cleanRequest(targetsToClean)
.exceptionally { err =>
new CleanCacheResult(BspBundle.message("bsp.task.server.does.not.support.cleaning.build.cache", err.getMessage), false)
val res = new CleanCacheResult(false)
res.setMessage(BspBundle.message("bsp.task.server.does.not.support.cleaning.build.cache", err.getMessage))
res
}
.thenCompose { cleaned =>
if (cleaned.getCleaned) compileRequest(targetsWithCompileCap)
Expand Down Expand Up @@ -239,7 +241,7 @@ class BspTask[T](project: Project,
case WARNING =>
reporter.warning(textNoAnsi, None)
buildMessages.addWarning(textNoAnsi)
case INFORMATION =>
case INFO =>
buildMessages
case LOG =>
buildMessages
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jetbrains.bsp.project.test

import ch.epfl.scala.bsp4j.TaskDataKind._
import ch.epfl.scala.bsp4j.TaskStartDataKind._
import ch.epfl.scala.bsp4j.TaskFinishDataKind._
import ch.epfl.scala.bsp4j.TestStatus._
import ch.epfl.scala.bsp4j._
import com.google.gson.{Gson, JsonObject}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.jetbrains.plugins.scala.build.{BuildMessages, BuildReporter, BuildToo
import java.nio.file.Paths
import java.util.UUID
import java.util.concurrent.CompletableFuture
import scala.annotation.nowarn
import scala.concurrent.Promise
import scala.jdk.CollectionConverters._
import scala.util.{Failure, Success, Try}
Expand Down Expand Up @@ -81,6 +82,7 @@ class FetchScalaTestClassesTask(project: Project,
}
}

@nowarn("cat=deprecation")
private def requestTestClasses(
params: ScalaTestClassesParams
)(bsp: BspServer, serverInfo: BuildServerInfo): CompletableFuture[ScalaTestClassesResult] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,13 @@ object BspJvmEnvironment {
case ExecutionEnvironmentType.RUN =>
environment[JvmRunEnvironmentResult](
_.getJvmRunEnvironmentProvider,
targets => server.jvmRunEnvironment(new JvmRunEnvironmentParams(targets)),
targets => server.buildTargetJvmRunEnvironment(new JvmRunEnvironmentParams(targets)),
_.getItems,
"buildTarget/jvmRunEnvironment")
case ExecutionEnvironmentType.TEST =>
environment[JvmTestEnvironmentResult](
_.getJvmTestEnvironmentProvider,
targets => server.jvmTestEnvironment(new JvmTestEnvironmentParams(targets)),
targets => server.buildTargetJvmTestEnvironment(new JvmTestEnvironmentParams(targets)),
_.getItems,
"buildTarget/jvmTestEnvironment")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.jetbrains.bsp.protocol.session

import ch.epfl.scala.bsp4j.BspConnectionDetails
import com.intellij.execution.configurations.JavaParameters
import com.intellij.openapi.projectRoots.Sdk
import bloop.rifle.{BloopRifleConfig, BloopRifleLogger, BloopThreads, BloopVersion}
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.projectRoots.{JavaSdk, Sdk}
import org.apache.commons.io.input.ClosedInputStream
import org.jetbrains.bsp.buildinfo.BuildInfo
import org.jetbrains.bsp.protocol.session.BspServerConnector.BspCapabilities
import org.jetbrains.bsp.protocol.session.BspSession.Builder
Expand All @@ -12,56 +13,63 @@ import org.jetbrains.plugins.scala.DependencyManagerBase.RichStr
import org.jetbrains.plugins.scala.build.BuildReporter
import org.jetbrains.plugins.scala.extensions.PathExt

import java.nio.file.Path
import scala.jdk.CollectionConverters._
import java.io.File
import java.nio.file.{Files, Path}
import scala.concurrent.duration._
import scala.util.control.NonFatal

class BloopLauncherConnector(base: Path, compilerOutput: Path, capabilities: BspCapabilities, jdk: Sdk) extends BspServerConnector {

val bloopVersion: String = BuildInfo.bloopVersion
val bspVersion = "2.0.0"

override def connect(reporter: BuildReporter): Either[BspError, Builder] = {
def bloopClasspath(version: String): Right[Throwable, Seq[File]] = {
val dependencies = Seq(
("ch.epfl.scala" % "bloop-frontend_2.12" % version).transitive()
)

val dependencies = Seq(
("ch.epfl.scala" % "bloop-launcher_2.12" % bloopVersion).transitive()
)
val launcherClasspath = DependencyManager.resolve(dependencies: _*)
.map(_.file.toCanonicalPath.toString)
.asJava

val javaParameters: JavaParameters = new JavaParameters
javaParameters.setJdk(jdk)
javaParameters.setWorkingDirectory(base.toFile)
javaParameters.getClassPath.addAll(launcherClasspath)
javaParameters.setMainClass("bloop.launcher.Launcher")

val cmdLine = javaParameters.toCommandLine
cmdLine.addParameter(bloopVersion)
val launcherClasspath = DependencyManager.resolve(dependencies: _*).map(_.file.toFile)
Right(launcherClasspath)
}

val argv = cmdLine.getCommandLineList(null)
val bloopDataStore = PathManager.getCommonDataPath.resolve("bloop")

val details = BloopRifleConfig.default(
BloopRifleConfig.Address.DomainSocket(bloopDataStore),
bloopClasspath,
workingDir = base.toFile
).copy(javaPath = JavaSdk.getInstance().getVMExecutablePath(jdk), retainedBloopVersion = BloopRifleConfig.AtLeast(BloopVersion(bloopVersion)))
reporter.log(BspBundle.message("bsp.protocol.starting.bloop"))
//noinspection ReferencePassedToNls
reporter.log(cmdLine.getCommandLineString)
reporter.log(s"Configuring default bloop using ${details}")

Right(prepareBspSession(details, bloopDataStore))

val details = new BspConnectionDetails("Bloop", argv, bloopVersion, bspVersion, List("java","scala").asJava)
Right(prepareBspSession(details))
}

private def prepareBspSession(details: BspConnectionDetails): Builder = {
private def prepareBspSession(details: BloopRifleConfig, bloopDataDir: Path): Builder = {

val threads = BloopThreads.create()
val (connection, socket, _) = bloop.rifle.BloopServer.bsp(details, base, threads, BloopRifleLogger.nop, 10.seconds, 30.seconds)

val processBuilder = new java.lang.ProcessBuilder(details.getArgv).directory(base.toFile)
val process = processBuilder.start()
def safeClose(close: => Unit) =
try {
close
} catch {
case NonFatal(_) => ()
}

val cleanup = () => {
process.destroy()
safeClose(connection.stop())
safeClose(socket.close())
safeClose(threads.shutdown())
}
val pid = scala.util.Try(Files.readString(bloopDataDir.resolve("pid"))).toOption.flatMap(_.toIntOption).getOrElse(-1)

val rootUri = base.toCanonicalPath.toUri
val compilerOutputUri = compilerOutput.toCanonicalPath.toUri
val initializeBuildParams = BspServerConnector.createInitializeBuildParams(rootUri, compilerOutputUri, capabilities)

BspSession.builder(process.pid(), process.getInputStream, process.getErrorStream, process.getOutputStream, initializeBuildParams, cleanup)
BspSession.builder(pid, socket.getInputStream, ClosedInputStream.INSTANCE, socket.getOutputStream, initializeBuildParams, cleanup)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ class BspSession private(bspPID: Long,
.create()
val listening = launcher.startListening()
val bspServer = cancellationSafeBspServer(launcher.getRemoteProxy)
localClient.onConnectWithServer(bspServer)

val messageHandler = new BspProcessMessageHandler(bspErr)
val messageHandlerRunning = AppExecutorUtil.getAppExecutorService.submit(messageHandler)
Expand Down Expand Up @@ -359,8 +358,6 @@ class BspSession private(bspPID: Long,
}

// build-level notifications
override def onConnectWithServer(server: bsp4j.BuildServer): Unit = super.onConnectWithServer(server)

override def onBuildTargetDidChange(didChange: bsp4j.DidChangeBuildTarget): Unit = {
updateLastActivity()
val event = DidChangeBuildTarget(didChange)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ class BspResolverLogicTest {
val target = new BuildTarget(
new BuildTargetIdentifier("ePzqj://jqke:540/n/ius7/jDa/t/z78"),
List("bla").asJava, null, List.empty.asJava,
new BuildTargetCapabilities(true,true,true)
{
val cap = new BuildTargetCapabilities()
cap.setCanCompile(true)
cap.setCanTest(true)
cap.setCanRun(true)
cap
}
)

val descriptions = BspResolverLogic.calculateModuleDescriptions(List(target), Nil, Nil, Nil, Nil, Nil, Nil)
Expand All @@ -34,7 +40,13 @@ class BspResolverLogicTest {
val target = new BuildTarget(
new BuildTargetIdentifier(id),
emptyList, null, emptyList,
new BuildTargetCapabilities(true, true, true)
{
val cap = new BuildTargetCapabilities()
cap.setCanCompile(true)
cap.setCanTest(true)
cap.setCanRun(true)
cap
}
)
target.setDisplayName(displayName)
target
Expand Down
10 changes: 6 additions & 4 deletions project/dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object Versions {
// NOTE: sbt-launch / bloop-launcher won't be fetched on refresh.
// run runtimeDependencies/update manually
val sbtVersion: String = "1.10.7"
val bloopVersion = "1.5.6"
val bloopVersion = "2.0.9"
val zincVersion = "1.10.7"

// ATTENTION: check the comment in `Common.newProjectWithKotlin` when updating this version
Expand All @@ -29,7 +29,7 @@ object Versions {
val (
intellijVersion_ForManagedIntellijDependencies,
intellijRepository_ForManagedIntellijDependencies,
) = detectIntellijArtifactVersionAndRepository(intellijVersion)
) = detectIntellijArtifactVersionAndRepository(intellijVersion)

private def detectIntellijArtifactVersionAndRepository(intellijVersion: String): (String, MavenRepository) = {
val locationDescriptor = IntellijVersionUtils.detectArtifactLocation(BuildInfo(intellijVersion, IdeaCommunity), ".zip")
Expand All @@ -42,7 +42,7 @@ object Versions {
val junitVersion: String = "4.13.2"
val junitInterfaceVersion: String = "0.13.3"

val bspVersion = "2.1.0-M3"
val bspVersion = "2.1.1"
val sbtStructureVersion: String = "2025.1.5"
val sbtIdeaShellVersion: String = "2025.1.4"
val compilerIndicesVersion = "1.0.16"
Expand Down Expand Up @@ -117,7 +117,7 @@ object Dependencies {
*/
val jupiterInterface: ModuleID = "com.github.sbt.junit" % "jupiter-interface" % "0.13.3"

val jupiterParams: String => ModuleID = (version: String) =>"org.junit.jupiter" % "junit-jupiter-params" % version
val jupiterParams: String => ModuleID = (version: String) => "org.junit.jupiter" % "junit-jupiter-params" % version

val ivy2: ModuleID = "org.apache.ivy" % "ivy" % "2.5.2"

Expand Down Expand Up @@ -210,6 +210,7 @@ object Dependencies {
}

object DependencyGroups {

import Dependencies.*
import Versions.*

Expand Down Expand Up @@ -238,6 +239,7 @@ object DependencyGroups {
)

val bsp: Seq[ModuleID] = Seq(
("ch.epfl.scala" %% "bloop-rifle" % bloopVersion).excludeAll(bspExclusions *),
("ch.epfl.scala" % "bsp4j" % bspVersion).excludeAll(bspExclusions *),
("ch.epfl.scala" %% "bsp-testkit" % bspVersion).excludeAll(bspExclusions *) % Test,
scalaCheck
Expand Down