Skip to content

Commit

Permalink
improvement: Add basic BazelBsp test
Browse files Browse the repository at this point in the history
  • Loading branch information
jkciesluk committed Jul 18, 2023
1 parent bb878d8 commit 9d9e769
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import java.nio.file.Files
import scala.concurrent.ExecutionContext
import scala.concurrent.Future

import scala.meta.internal.builds.BazelBuildTool
import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.builds.BazelBuildTool
import scala.meta.internal.builds.BuildServerProvider
import scala.meta.internal.builds.BuildTools
import scala.meta.internal.builds.SbtBuildTool
Expand Down Expand Up @@ -118,7 +118,8 @@ class BspConnector(
bspServers
.findAvailableServers()
.collectFirst {
case details if details.getName == BazelBuildTool.bspName =>
case details
if details.getName == BazelBuildTool.bspName =>
tables.buildServers.chooseServer(BazelBuildTool.bspName)
bspServers.newServer(workspace, details).map(Some(_))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package scala.meta.internal.builds

import java.util.concurrent.TimeUnit

import scala.concurrent.ExecutionContext
import scala.concurrent.Future

import scala.meta.internal.metals.Messages
import scala.meta.internal.metals.Messages.ImportBuild
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.Tables
import scala.meta.internal.metals.UserConfiguration
import scala.meta.internal.process.ExitCodes
import scala.meta.io.AbsolutePath

import coursierapi.Dependency
import scala.meta.internal.metals.Messages.ImportBuild
import scala.meta.internal.metals.Messages
import scala.meta.internal.metals.Tables
import scala.meta.internal.process.ExitCodes
import java.util.concurrent.TimeUnit
import org.eclipse.lsp4j.services.LanguageClient

case class BazelBuildTool(userConfig: () => UserConfiguration)
Expand All @@ -36,7 +38,7 @@ case class BazelBuildTool(userConfig: () => UserConfiguration)

override def recommendedVersion: String = version

override def version: String = "2.7.1"
override def version: String = BazelBuildTool.version

override def toString: String = "Bazel"

Expand All @@ -51,26 +53,30 @@ case class BazelBuildTool(userConfig: () => UserConfiguration)
object BazelBuildTool {
val name: String = "bazel"
val bspName: String = "bazelbsp"
val version: String = "2.7.1"

val mainClass = "org.jetbrains.bsp.bazel.install.Install"

private val coursierArgs = List(
"cs", "launch", "org.jetbrains.bsp:bazel-bsp:2.7.1", "-M",
"org.jetbrains.bsp.bazel.install.Install",
"cs",
"launch",
s"org.jetbrains.bsp:bazel-bsp:$version",
"-M",
mainClass,
)

private val dependency = Dependency.of(
"org.jetbrains.bsp",
"bazel-bsp",
"2.7.1",
version,
)

private val mainClass = "org.jetbrains.bsp.bazel.install.Install"

def writeBazelConfig(
shellRunner: ShellRunner,
projectDirectory: AbsolutePath,
)(implicit
ec: ExecutionContext
) = {
): Future[WorkspaceLoadedStatus] = {
def run() =
shellRunner.runJava(dependency, mainClass, projectDirectory, Nil, false)
run()
Expand All @@ -96,13 +102,13 @@ object BazelBuildTool {
forceImport: Boolean = false,
)(implicit
ec: ExecutionContext
) = {
): Future[WorkspaceLoadedStatus] = {
val notification = tables.dismissedNotifications.ImportChanges
if (forceImport) {
writeBazelConfig(shellRunner, projectDirectory)
} else if (!notification.isDismissed) {
languageClient
.showMessageRequest(ImportBuild.params(name))
.showMessageRequest(ImportBuild.params("Bazel"))
.asScala
.flatMap {
case item if item == Messages.dontShowAgain =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ final class BuildTools(
MavenBuildTool(userConfig),
MillBuildTool(userConfig),
ScalaCliBuildTool(workspace),
BazelBuildTool(userConfig),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ object Digest {
def digestBazel(
file: AbsolutePath,
digest: MessageDigest,
) = {
): Boolean = {
try {
Files
.readAllLines(file.toNIO)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1913,15 +1913,15 @@ class MetalsLspService(
)
case Some(_)
if buildTool.executableName == BazelBuildTool.name && !buildTools.isBazelBsp =>
BazelBuildTool.maybeWriteBazelConfig(
shellRunner,
folder,
languageClient,
tables,
forceImport
).flatMap(
_ => quickConnectToBuildServer()
)
BazelBuildTool
.maybeWriteBazelConfig(
shellRunner,
folder,
languageClient,
tables,
forceImport,
)
.flatMap(_ => quickConnectToBuildServer())
case Some(_)
if buildTool.executableName == ScalaCliBuildTool.name && chosenBuildServer.isEmpty =>
tables.buildServers.chooseServer(ScalaCliBuildTool.name)
Expand Down Expand Up @@ -2120,7 +2120,9 @@ class MetalsLspService(
possibleBuildTool <- supportedBuildTool()
_ <- importBuild(session)
_ <- indexer.profiledIndexWorkspace(runDoctorCheck)
_ = possibleBuildTool.map(workspaceReload.persistChecksumStatus(Digest.Status.Installed, _))
_ = possibleBuildTool.map(
workspaceReload.persistChecksumStatus(Digest.Status.Installed, _)
)
_ = if (session.main.isBloop) checkRunningBloopVersion(session.version)
} yield {
BuildChange.Reconnected
Expand Down
113 changes: 113 additions & 0 deletions tests/slow/src/test/scala/tests/bazel/BazelLspSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package tests.bazel

import scala.meta.internal.builds.BazelBuildTool

import scala.meta.internal.metals.Messages._
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.io.AbsolutePath

import tests.BaseImportSuite
import scala.meta.internal.builds.BazelDigest
import tests.BazelServerInitializer
import tests.BazelBuildLayout

class BazelLspSuite
extends BaseImportSuite("bazel-import", BazelServerInitializer) {
val scalaVersion = "2.13.6"
val buildTool: BazelBuildTool = BazelBuildTool(() => userConfig)

val bazelVersion = "6.2.1"

val libPath = "src/main/scala/lib"
val cmdPath = "src/main/scala/cmd"

override def currentDigest(
workspace: AbsolutePath
): Option[String] = BazelDigest.current(workspace)

test("basic") {
cleanWorkspace()
for {
_ <- initialize(BazelBuildLayout(workspaceLayout, scalaVersion, bazelVersion))
_ = assertNoDiff(
client.workspaceMessageRequests,
List(
importBuildMessage,
// create .bazelbsp progress message
BazelBuildTool.mainClass,
allProjectsMisconfigured,
).mkString("\n"),
)
_ = assert(workspace.resolve(".bsp/bazelbsp.json").exists)
_ = client.messageRequests.clear() // restart
_ = assertStatus(_.isInstalled)
_ <- server.didChange("WORKSPACE")(_ + "\n# comment")
_ <- server.didSave("WORKSPACE")(identity)
// Comment changes do not trigger "re-import project" request
_ = assertNoDiff(client.workspaceMessageRequests, "")
_ <- server.didChange(s"$cmdPath/BUILD") { text =>
text.replace("runner", "runner1")
}
_ = assertNoDiff(client.workspaceMessageRequests, "")
_ = client.importBuildChanges = ImportBuildChanges.yes
_ <- server.didSave(s"$cmdPath/BUILD")(identity)
} yield {
assertNoDiff(
client.workspaceMessageRequests,
List(
importBuildChangesMessage
).mkString("\n"),
)
server.assertBuildServerConnection()
}
}

private val greetingFile =
"""|package lib
|
|object Greeting {
| def greet: String = "Hi"
|
| def sayHi = println(s"$greet!")
|}
|""".stripMargin

private val runnerFile =
"""|package cmd
|
|import lib.Greeting
|
|object Runner {
| def main(args: Array[String]): Unit = {
| Greeting.sayHi
| }
|}
|""".stripMargin

private val workspaceLayout =
s"""|/$libPath/BUILD
|load("@io_bazel_rules_scala//scala:scala.bzl", "scala_library")
|
|scala_library(
| name = "greeting",
| srcs = ["Greeting.scala"],
| visibility = ["//src/main/scala/cmd:__pkg__"],
|)
|
|/$libPath/Greeting.scala
|$greetingFile
|
|/$cmdPath/BUILD
|load("@io_bazel_rules_scala//scala:scala.bzl", "scala_binary")
|
|scala_binary(
| name = "runner",
| main_class = "cmd.Runner",
| srcs = ["Runner.scala"],
| deps = ["//src/main/scala/lib:greeting"],
|)
|
|/$cmdPath/Runner.scala
|$runnerFile
|""".stripMargin
}
3 changes: 3 additions & 0 deletions tests/unit/src/main/scala/tests/BaseImportSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ abstract class BaseImportSuite(
def progressMessage: String =
bloopInstallProgress(buildTool.executableName).message

def allProjectsMisconfigured: String =
CheckDoctor.allProjectsMisconfigured

def currentDigest(workspace: AbsolutePath): Option[String]

def currentChecksum(): String =
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/src/main/scala/tests/BuildServerInitializer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,26 @@ object MillServerInitializer extends BuildServerInitializer {
}
}
}

object BazelServerInitializer extends BuildServerInitializer {
this: BaseLspSuite =>
override def initialize(
workspace: AbsolutePath,
server: TestingServer,
client: TestingClient,
expectError: Boolean,
workspaceFolders: List[String] = Nil,
)(implicit ec: ExecutionContext): Future[InitializeResult] = {
for {
initializeResult <- server.initialize()
// Import build using Bazel
_ = client.importBuild = ImportBuild.yes
_ <- server.initialized()
} yield {
if (!expectError) {
server.assertBuildServerConnection()
}
initializeResult
}
}
}
58 changes: 58 additions & 0 deletions tests/unit/src/main/scala/tests/BuildServerLayout.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,61 @@ object MillBuildLayout extends BuildToolLayout {
|${apply(sourceLayout, scalaVersion)}
|""".stripMargin
}

object BazelBuildLayout extends BuildToolLayout {

override def apply(sourceLayout: String, scalaVersion: String): String =
s"""|/WORKSPACE
|${workspaceFileLayout(scalaVersion)}
|$sourceLayout
|""".stripMargin

def apply(
sourceLayout: String,
scalaVersion: String,
bazelVersion: String,
): String =
s"""|/.bazelversion
|$bazelVersion
|${apply(sourceLayout, scalaVersion)}
|""".stripMargin

def workspaceFileLayout(scalaVersion: String): String =
s"""|load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
|skylib_version = "1.0.3"
|
|http_archive(
| name = "bazel_skylib",
| sha256 = "1c531376ac7e5a180e0237938a2536de0c54d93f5c278634818e0efc952dd56c",
| type = "tar.gz",
| url = "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/{}/bazel-skylib-{}.tar.gz".format(skylib_version, skylib_version),
|)
|
|http_archive(
| name = "io_bazel_rules_scala",
| sha256 = "77a3b9308a8780fff3f10cdbbe36d55164b85a48123033f5e970fdae262e8eb2",
| strip_prefix = "rules_scala-20220201",
| type = "zip",
| url = "https://github.com/bazelbuild/rules_scala/releases/download/20220201/rules_scala-20220201.zip",
|)
|
|load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config")
|
|scala_config(scala_version = "$scalaVersion")
|
|load("@io_bazel_rules_scala//scala:scala.bzl", "scala_repositories")
|
|scala_repositories()
|
|load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
|
|rules_proto_dependencies()
|
|rules_proto_toolchains()
|
|load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains")
|
|scala_register_toolchains()
|""".stripMargin
}

0 comments on commit 9d9e769

Please sign in to comment.