Skip to content

Commit

Permalink
look for .bsp also in the project root
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Nov 22, 2023
1 parent ca72002 commit a6e1ac4
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 35 deletions.
22 changes: 21 additions & 1 deletion metals/src/main/scala/scala/meta/internal/bsp/BspConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import scala.meta.internal.builds.BuildServerProvider
import scala.meta.internal.builds.BuildTool
import scala.meta.internal.builds.BuildTools
import scala.meta.internal.builds.SbtBuildTool
import scala.meta.internal.builds.ScalaCliBuildTool
import scala.meta.internal.builds.ShellRunner
import scala.meta.internal.metals.BloopServers
import scala.meta.internal.metals.BuildServerConnection
Expand All @@ -19,6 +20,7 @@ import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.StatusBar
import scala.meta.internal.metals.Tables
import scala.meta.internal.metals.UserConfiguration
import scala.meta.internal.metals.scalacli.ScalaCli
import scala.meta.internal.semver.SemVer
import scala.meta.io.AbsolutePath

Expand Down Expand Up @@ -58,7 +60,10 @@ class BspConnector(
else
bspServers
.findAvailableServers()
.find(_.getName == sel)
.find(buildServer =>
(ScalaCli.names(buildServer.getName()) && ScalaCli.names(sel)) ||
buildServer.getName == sel
)
.map(ResolvedBspOne)
}
}
Expand Down Expand Up @@ -129,6 +134,7 @@ class BspConnector(
.map(Some(_))
case ResolvedBspOne(details) =>
tables.buildServers.chooseServer(details.getName())
optSetBuildTool(details.getName())
bspServers
.newServer(projectRoot, bspTraceRoot, details, bspStatusOpt)
.map(Some(_))
Expand Down Expand Up @@ -163,6 +169,7 @@ class BspConnector(
)
)
_ = tables.buildServers.chooseServer(item.getName())
_ = optSetBuildTool(item.getName())
conn <- bspServers.newServer(
projectRoot,
bspTraceRoot,
Expand Down Expand Up @@ -197,6 +204,19 @@ class BspConnector(
}
}

private def optSetBuildTool(buildServerName: String): Unit =
buildTools.loadSupported
.find {
case _: ScalaCliBuildTool if ScalaCli.names(buildServerName) => true
case buildTool: BuildServerProvider
if buildTool.buildServerName.contains(buildServerName) =>
true
case buildTool => buildTool.executableName == buildServerName
}
.foreach(buildTool =>
tables.buildTool.chooseBuildTool(buildTool.executableName)
)

private def sbtMetaWorkspaces(root: AbsolutePath): List[AbsolutePath] = {
def recursive(
p: AbsolutePath,
Expand Down
11 changes: 6 additions & 5 deletions metals/src/main/scala/scala/meta/internal/bsp/BspServers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ final class BspServers(
config: MetalsServerConfig,
userConfig: () => UserConfiguration,
)(implicit ec: ExecutionContextExecutorService) {
private def customProjectRoot =
userConfig().getCustomProjectRoot(mainWorkspace)

def resolve(): BspResolvedResult = {
findAvailableServers() match {
Expand Down Expand Up @@ -153,7 +155,7 @@ final class BspServers(
* may be a server in the current workspace
*/
def findAvailableServers(): List[BspConnectionDetails] = {
val jsonFiles = findJsonFiles(mainWorkspace)
val jsonFiles = findJsonFiles()
val gson = new Gson()
for {
candidate <- jsonFiles
Expand All @@ -172,17 +174,16 @@ final class BspServers(
}
}

private def findJsonFiles(
projectDirectory: AbsolutePath
): List[AbsolutePath] = {
private def findJsonFiles(): List[AbsolutePath] = {
val buf = List.newBuilder[AbsolutePath]
def visit(dir: AbsolutePath): Unit =
dir.list.foreach { p =>
if (p.extension == "json") {
buf += p
}
}
visit(projectDirectory.resolve(".bsp"))
visit(mainWorkspace.resolve(".bsp"))
customProjectRoot.map(_.resolve(".bsp")).foreach(visit)
bspGlobalInstallDirectories.foreach(visit)
buf.result()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import scala.meta.internal.mtags.MD5
import scala.meta.io.AbsolutePath

/**
* Build tool for custom bsp detected in `.bsp/<name>.json`
* Build tool for custom bsp detected in `.bsp/<name>.json` or `bspGlobalDirectories`
*/
case class BspOnly(
override val executableName: String,
override val projectRoot: AbsolutePath,
pathToBspConfig: AbsolutePath,
) extends BuildTool {
override def digest(workspace: AbsolutePath): Option[String] = {
val digest = MessageDigest.getInstance("MD5")
val isSuccess =
Digest.digestJson(workspace.resolve(s"$executableName.json"), digest)
Digest.digestJson(pathToBspConfig, digest)
if (isSuccess) Some(MD5.bytesToHex(digest.digest()))
else None
}
Expand Down
30 changes: 15 additions & 15 deletions metals/src/main/scala/scala/meta/internal/builds/BuildTools.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ final class BuildTools(
def isBloop: Boolean = bloopProject.isDefined
def isBsp: Boolean = {
hasJsonFile(workspace.resolve(".bsp")) ||
customProjectRoot.exists(root => hasJsonFile(root.resolve(".bsp"))) ||
bspGlobalDirectories.exists(hasJsonFile)
}
private def hasJsonFile(dir: AbsolutePath): Boolean = {
Expand Down Expand Up @@ -123,34 +124,33 @@ final class BuildTools(
def isBazel: Boolean = bazelProject.isDefined

private def customBsps: List[BspOnly] = {
val bspFolder = workspace.resolve(".bsp")
val bspFolders =
(workspace :: customProjectRoot.toList).distinct
.map(_.resolve(".bsp")) ++ bspGlobalDirectories
val root = customProjectRoot.getOrElse(workspace)
if (bspFolder.exists && bspFolder.isDirectory) {
bspFolder.toFile
for {
bspFolder <- bspFolders
if (bspFolder.exists && bspFolder.isDirectory)
buildTool <- bspFolder.toFile
.listFiles()
.collect {
case file
if file.isFile() && file.getName().endsWith(".json") &&
!knownBsps(file.getName().stripSuffix(".json")) =>
BspOnly(file.getName().stripSuffix(".json"), root)
BspOnly(
file.getName().stripSuffix(".json"),
root,
AbsolutePath(file.toPath()),
)
}
.toList
} else Nil
} yield buildTool
}

private def knownBsps =
Set(SbtBuildTool.name, MillBuildTool.name) ++ ScalaCli.names

private def customProjectRoot =
userConfig().customProjectRoot
.map(relativePath => workspace.resolve(relativePath.trim()))
.filter { projectRoot =>
val exists = projectRoot.exists
if (!exists) {
scribe.error(s"custom project root $projectRoot does not exist")
}
exists
}
private def customProjectRoot = userConfig().getCustomProjectRoot(workspace)

private def searchForBuildTool(
isProjectRoot: AbsolutePath => Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ object Configs {
new FileSystemWatcher(
Either.forLeft(s"$root/.metals/.reports/bloop/*/*")
),
new FileSystemWatcher(Either.forLeft(s"$root/.bsp/*.json")),
new FileSystemWatcher(Either.forLeft(s"$root/**/.bsp/*.json")),
).asJava
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ case class UserConfiguration(
) && this.showInferredType.nonEmpty
showImplicitArguments || showInferredType || showImplicitConversionsAndClasses
}

def getCustomProjectRoot(workspace: AbsolutePath): Option[AbsolutePath] =
customProjectRoot
.map(relativePath => workspace.resolve(relativePath.trim()))
.filter { projectRoot =>
val exists = projectRoot.toFile.exists
if (!exists) {
scribe.error(s"custom project root $projectRoot does not exist")
}
exists
}

}

object UserConfiguration {
Expand Down
2 changes: 0 additions & 2 deletions tests/unit/src/main/scala/tests/TestingClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import scala.concurrent.Promise

import scala.meta.inputs.Input
import scala.meta.internal.bsp.ConnectionBspStatus
import scala.meta.internal.builds.BuildTool
import scala.meta.internal.builds.BspErrorHandler
import scala.meta.internal.builds.BuildTools
import scala.meta.internal.decorations.PublishDecorationsParams
import scala.meta.internal.metals.Buffers
Expand Down
16 changes: 7 additions & 9 deletions tests/unit/src/test/scala/tests/BillLspSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,7 @@ class BillLspSuite extends BaseLspSuite("bill") {
testRoundtripCompilation()
}

def testSelectServerDialogue(
additionalMessages: List[String] = Nil
): Future[Unit] = {
def testSelectServerDialogue(): Future[Unit] = {
// when asked, choose the Bob build tool
client.selectBspServer = { actions =>
actions.find(_.getTitle == "Bob").get
Expand All @@ -203,11 +201,11 @@ class BillLspSuite extends BaseLspSuite("bill") {
)
_ = assertNoDiff(
client.workspaceMessageRequests,
(additionalMessages ++
List(
Messages.BspSwitch.message,
Messages.CheckDoctor.allProjectsMisconfigured,
)).mkString("\n"),
List(
Messages.ChooseBuildTool.message,
Messages.BspSwitch.message,
Messages.CheckDoctor.allProjectsMisconfigured,
).mkString("\n"),
)
} yield ()
}
Expand All @@ -216,7 +214,7 @@ class BillLspSuite extends BaseLspSuite("bill") {
cleanWorkspace()
Bill.installWorkspace(workspace.toNIO, "Bill")
Bill.installWorkspace(workspace.toNIO, "Bob")
testSelectServerDialogue(List(Messages.ChooseBuildTool.message))
testSelectServerDialogue()
}

test("mix") {
Expand Down

0 comments on commit a6e1ac4

Please sign in to comment.