Skip to content

Commit

Permalink
reconnect on .bsp change
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Nov 21, 2023
1 parent 874c26f commit ede54d8
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 27 deletions.
12 changes: 6 additions & 6 deletions metals/src/main/scala/scala/meta/internal/bsp/BspConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import scala.concurrent.ExecutionContext
import scala.concurrent.Future

import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.builds.BloopInstallProvider
import scala.meta.internal.builds.BuildServerProvider
import scala.meta.internal.builds.BuildTool
import scala.meta.internal.builds.BuildTools
Expand Down Expand Up @@ -47,7 +46,7 @@ class BspConnector(
*/
def resolve(buildTool: Option[BuildTool]): BspResolvedResult = {
resolveExplicit().getOrElse {
if (buildTool.isInstanceOf[BloopInstallProvider] || buildTools.isBloop)
if (buildTool.exists(_.isBloopInstallProvider) || buildTools.isBloop)
ResolvedBloop
else bspServers.resolve()
}
Expand Down Expand Up @@ -179,9 +178,10 @@ class BspConnector(
possibleBuildServerConn match {
case None => Future.successful(None)
case Some(buildServerConn)
if buildServerConn.isBloop && buildTool.exists(
_.isInstanceOf[SbtBuildTool]
) =>
if buildServerConn.isBloop && buildTool.exists {
case _: SbtBuildTool => true
case _ => false
} =>
// NOTE: (ckipp01) we special case this here since sbt bsp server
// doesn't yet support metabuilds. So in the future when that
// changes, re-work this and move the creation of this out above
Expand Down Expand Up @@ -280,7 +280,7 @@ class BspConnector(
if (
bloopPresent || buildTools
.loadSupported()
.exists(_.isInstanceOf[BloopInstallProvider])
.exists(_.isBloopInstallProvider)
)
new BspConnectionDetails(
BloopServers.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import scala.meta.io.AbsolutePath
trait BloopInstallProvider extends BuildTool {

/**
* Method used to generate the necesary .bloop files for the
* Method used to generate the necessary .bloop files for the
* build tool.
*/
def bloopInstall(
Expand All @@ -22,4 +22,6 @@ trait BloopInstallProvider extends BuildTool {
* Args necessary for build tool to generate the .bloop files.
*/
def bloopInstallArgs(workspace: AbsolutePath): List[String]

override val isBloopInstallProvider = true
}
12 changes: 11 additions & 1 deletion metals/src/main/scala/scala/meta/internal/builds/BspOnly.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package scala.meta.internal.builds

import java.security.MessageDigest

import scala.meta.internal.builds.Digest
import scala.meta.internal.mtags.MD5
import scala.meta.io.AbsolutePath

/**
Expand All @@ -9,6 +13,12 @@ case class BspOnly(
override val executableName: String,
override val projectRoot: AbsolutePath,
) extends BuildTool {
override def digest(workspace: AbsolutePath): Option[String] = Some("OK")
override def digest(workspace: AbsolutePath): Option[String] = {
val digest = MessageDigest.getInstance("MD5")
val isSuccess =
Digest.digestJson(workspace.resolve(s"$executableName.json"), digest)
if (isSuccess) Some(MD5.bytesToHex(digest.digest()))
else None
}
override val forcesBuildServer = true
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ trait BuildTool {

val forcesBuildServer = false

val isBloopInstallProvider = false

}

object BuildTool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,15 @@ final class BuildTools(
.listFiles()
.collect {
case file
if file.isFile() && file.getName().endsWith(".json") && !knowBsps(
file.getName().stripSuffix(".json")
) =>
if file.isFile() && file.getName().endsWith(".json") &&
!knownBsps(file.getName().stripSuffix(".json")) =>
BspOnly(file.getName().stripSuffix(".json"), root)
}
.toList
} else Nil
}

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

private def customProjectRoot =
Expand Down Expand Up @@ -230,6 +229,11 @@ final class BuildTools(
Some(MavenBuildTool.name)
else if (isMill && MillBuildTool.isMillRelatedPath(path))
Some(MillBuildTool.name)
else if (
path.isFile && path.filename.endsWith(".json") &&
path.parent.filename == ".bsp"
)
Some(path.filename.stripSuffix(".json"))
else None
}

Expand Down
17 changes: 17 additions & 0 deletions metals/src/main/scala/scala/meta/internal/builds/Digest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.security.MessageDigest

import scala.util.Success
import scala.util.Try
import scala.util.control.NonFatal
import scala.xml.Comment
import scala.xml.Node
Expand All @@ -15,6 +17,8 @@ import scala.meta.internal.mtags.MD5
import scala.meta.internal.parsing.Trees
import scala.meta.io.AbsolutePath

import ujson.BytesRenderer

case class Digest(
md5: String,
status: Status,
Expand Down Expand Up @@ -174,6 +178,19 @@ object Digest {
false
}
}

def digestJson(
file: AbsolutePath,
digest: MessageDigest,
): Boolean = {
Try(ujson.read(file.readText)) match {
case Success(json) =>
val bytes = json.transform(BytesRenderer()).toByteArray()
digest.update(bytes)
true
case _ => false
}
}
}

trait Digestable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ object Configs {
new FileSystemWatcher(
Either.forLeft(s"$root/project/build.properties")
),
new FileSystemWatcher(Either.forLeft(s"$root/.bsp/*.json")),
).asJava
)
}
Expand Down
39 changes: 24 additions & 15 deletions metals/src/main/scala/scala/meta/internal/metals/Indexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import scala.meta.dialects._
import scala.meta.inputs.Input
import scala.meta.internal.bsp.BspSession
import scala.meta.internal.bsp.BuildChange
import scala.meta.internal.builds.BspOnly
import scala.meta.internal.builds.BuildTool
import scala.meta.internal.builds.BuildTools
import scala.meta.internal.builds.Digest.Status
Expand Down Expand Up @@ -88,25 +89,33 @@ final case class Indexer(
buildTool: BuildTool,
checksum: String,
importBuild: BspSession => Future[Unit],
reconnectToBuildServer: () => Future[BuildChange],
): Future[BuildChange] = {
def reloadAndIndex(session: BspSession): Future[BuildChange] = {
workspaceReload().persistChecksumStatus(Status.Started, buildTool)

session
.workspaceReload()
.flatMap(_ => importBuild(session))
.map { _ =>
scribe.info("Correctly reloaded workspace")
profiledIndexWorkspace(doctorCheck)
workspaceReload().persistChecksumStatus(Status.Installed, buildTool)
BuildChange.Reloaded
}
.recoverWith { case NonFatal(e) =>
scribe.error(s"Unable to reload workspace: ${e.getMessage()}")
workspaceReload().persistChecksumStatus(Status.Failed, buildTool)
languageClient.showMessage(Messages.ReloadProjectFailed)
Future.successful(BuildChange.Failed)
}
buildTool match {
case _: BspOnly => reconnectToBuildServer()
case _ =>
session
.workspaceReload()
.flatMap(_ => importBuild(session))
.map { _ =>
scribe.info("Correctly reloaded workspace")
profiledIndexWorkspace(doctorCheck)
workspaceReload().persistChecksumStatus(
Status.Installed,
buildTool,
)
BuildChange.Reloaded
}
.recoverWith { case NonFatal(e) =>
scribe.error(s"Unable to reload workspace: ${e.getMessage()}")
workspaceReload().persistChecksumStatus(Status.Failed, buildTool)
languageClient.showMessage(Messages.ReloadProjectFailed)
Future.successful(BuildChange.Failed)
}
}
}

bspSession() match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2148,6 +2148,7 @@ class MetalsLspService(
found.buildTool,
found.digest,
importBuild,
quickConnectToBuildServer,
)
case None =>
Future.successful(BuildChange.None)
Expand Down

0 comments on commit ede54d8

Please sign in to comment.