Skip to content
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

improvement: Remove bazel specific directories when running full clean #6205

Merged
merged 1 commit into from Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -10,6 +10,7 @@ import scala.util.control.NonFatal
import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.builds.BuildServerProvider
import scala.meta.internal.builds.ShellRunner
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.Messages.BspProvider
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.StatusBar
Expand Down Expand Up @@ -45,10 +46,9 @@ final class BspConfigGenerator(
.map {
case Generated if buildTool.projectRoot != workspace =>
try {
val bsp = ".bsp"
workspace.resolve(bsp).createDirectories()
val buildToolBspDir = buildTool.projectRoot.resolve(bsp)
val workspaceBspDir = workspace.resolve(bsp).toNIO
workspace.resolve(Directories.bsp).createDirectories()
val buildToolBspDir = buildTool.projectRoot.resolve(Directories.bsp)
val workspaceBspDir = workspace.resolve(Directories.bsp).toNIO
buildToolBspDir.toFile.listFiles().foreach { file =>
val path = file.toPath()
if (!file.isDirectory() && path.filename.endsWith(".json")) {
Expand Down
Expand Up @@ -14,6 +14,7 @@ import scala.meta.internal.io.FileIO
import scala.meta.internal.metals.BuildServerConnection
import scala.meta.internal.metals.Cancelable
import scala.meta.internal.metals.ClosableOutputStream
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.JdkSources
import scala.meta.internal.metals.MetalsBuildClient
import scala.meta.internal.metals.MetalsEnrichments._
Expand Down Expand Up @@ -183,8 +184,8 @@ final class BspServers(
buf += p
}
}
visit(mainWorkspace.resolve(".bsp"))
customProjectRoot.map(_.resolve(".bsp")).foreach(visit)
visit(mainWorkspace.resolve(Directories.bsp))
customProjectRoot.map(_.resolve(Directories.bsp)).foreach(visit)
bspGlobalInstallDirectories.foreach(visit)
buf.result()
}
Expand Down
Expand Up @@ -4,6 +4,7 @@ import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardCopyOption

import scala.meta.internal.metals.Directories
import scala.meta.io.AbsolutePath

trait BuildTool {
Expand Down Expand Up @@ -38,7 +39,7 @@ trait BuildTool {

def isBspGenerated(workspace: AbsolutePath): Boolean =
possibleBuildServerNames
.map(name => workspace.resolve(".bsp").resolve(s"$name.json"))
.map(name => workspace.resolve(Directories.bsp).resolve(s"$name.json"))
.exists(_.isFile)
}

Expand Down
15 changes: 12 additions & 3 deletions metals/src/main/scala/scala/meta/internal/builds/BuildTools.scala
Expand Up @@ -7,6 +7,7 @@ import java.util.concurrent.atomic.AtomicReference
import scala.meta.internal.bsp.ScalaCliBspScope
import scala.meta.internal.io.PathIO
import scala.meta.internal.metals.BloopServers
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.UserConfiguration
import scala.meta.internal.metals.scalacli.ScalaCli
Expand Down Expand Up @@ -54,14 +55,22 @@ final class BuildTools(
def bloopProject: Option[AbsolutePath] = searchForBuildTool(isBloop)
def isBloop: Boolean = bloopProject.isDefined
def isBsp: Boolean = {
hasJsonFile(workspace.resolve(".bsp")) ||
customProjectRoot.exists(root => hasJsonFile(root.resolve(".bsp"))) ||
hasJsonFile(workspace.resolve(Directories.bsp)) ||
customProjectRoot.exists(root =>
hasJsonFile(root.resolve(Directories.bsp))
) ||
bspGlobalDirectories.exists(hasJsonFile)
}
private def hasJsonFile(dir: AbsolutePath): Boolean = {
dir.list.exists(_.extension == "json")
}

def isBazelBsp: Boolean = {
workspace.resolve(Directories.bazelBsp).isDirectory &&
BazelBuildTool.existingProjectView(workspace).nonEmpty &&
isBsp
}

// Returns true if there's a build.sbt file or project/build.properties with sbt.version
def sbtProject: Option[AbsolutePath] = searchForBuildTool { root =>
root.resolve("build.sbt").isFile || {
Expand Down Expand Up @@ -130,7 +139,7 @@ final class BuildTools(
private def customBsps: List[BspOnly] = {
val bspFolders =
(workspace :: customProjectRoot.toList).distinct
.map(_.resolve(".bsp")) ++ bspGlobalDirectories
.map(_.resolve(Directories.bsp)) ++ bspGlobalDirectories
val root = customProjectRoot.getOrElse(workspace)
for {
bspFolder <- bspFolders
Expand Down
Expand Up @@ -67,7 +67,7 @@ case class SbtBuildTool(
): Option[List[String]] =
Option.when(workspaceSupportsBsp(projectRoot)) {
val bspConfigArgs = List[String]("bspConfig")
val bspDir = workspace.resolve(".bsp").toNIO
val bspDir = workspace.resolve(Directories.bsp).toNIO
composeArgs(bspConfigArgs, projectRoot, bspDir)
}

Expand Down Expand Up @@ -449,7 +449,7 @@ object SbtBuildTool {
workspace: AbsolutePath,
userJavaHome: Option[String],
): Boolean = {
val bspConfigFile = workspace.resolve(".bsp").resolve("sbt.json")
val bspConfigFile = workspace.resolve(Directories.bsp).resolve("sbt.json")
if (bspConfigFile.isFile) {
val matchesSbtJavaHome =
for {
Expand Down
Expand Up @@ -6,6 +6,7 @@ import scala.concurrent.Future

import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.metals.BuildInfo
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.StatusBar
import scala.meta.internal.metals.UserConfiguration
Expand All @@ -30,7 +31,8 @@ class ScalaCliBuildTool(
): Future[BspConfigGenerationStatus] =
createBspFileArgs(workspace).map(systemProcess).getOrElse {
// fallback to creating `.bsp/scala-cli.json` that starts JVM launcher
val bspConfig = workspace.resolve(".bsp").resolve("scala-cli.json")
val bspConfig =
workspace.resolve(Directories.bsp).resolve("scala-cli.json")
statusBar.addMessage("scala-cli bspConfig")
bspConfig.writeText(
ScalaCli.scalaCliBspJsonContent(projectRoot = projectRoot.toString())
Expand Down Expand Up @@ -69,7 +71,7 @@ object ScalaCliBuildTool {

def pathsToScalaCliBsp(root: AbsolutePath): List[AbsolutePath] =
ScalaCli.names.toList.map(name =>
root.resolve(".bsp").resolve(s"$name.json")
root.resolve(Directories.bsp).resolve(s"$name.json")
)

def apply(
Expand Down
Expand Up @@ -22,6 +22,10 @@ object Directories {
RelativePath(".metals").resolve("workspace-symbol.md")
def stacktrace: RelativePath =
RelativePath(".metals").resolve(stacktraceFilename)
def bazelBsp: RelativePath =
RelativePath(".bazelbsp")
def bsp: RelativePath =
RelativePath(".bsp")

val stacktraceFilename = "stacktrace.scala"
val dependenciesName = "dependencies"
Expand Down
Expand Up @@ -342,6 +342,18 @@ object MetalsEnrichments

implicit class XtensionAbsolutePathBuffers(path: AbsolutePath) {

def isBazelRelatedPath: Boolean = {
val filename = path.toNIO.getFileName.toString
filename == "WORKSPACE" ||
filename == "BUILD" ||
filename == "BUILD.bazel" ||
filename.endsWith(".bzl") ||
filename.endsWith(".bazelproject")
}
def isInBspDirectory(workspace: AbsolutePath): Boolean =
path.toNIO.startsWith(workspace.resolve(Directories.bsp).toNIO)
def isInBazelBspDirectory(workspace: AbsolutePath): Boolean =
path.toNIO.startsWith(workspace.resolve(Directories.bazelBsp).toNIO)
def isScalaProject(): Boolean =
containsProjectFilesSatisfying(_.isScala)
def isMetalsProject(): Boolean =
Expand Down
Expand Up @@ -2797,17 +2797,42 @@ class MetalsLspService(
}
}

private def clearFolders(folders: AbsolutePath*): Unit = {
try {
folders.foreach(_.deleteRecursively())
} catch {
case e: Throwable =>
languageClient.showMessage(Messages.ResetWorkspaceFailed)
scribe.error(
s"Error while deleting directories inside ${folders.mkString(", ")}",
e,
)
}
}

def resetWorkspace(): Future[Unit] =
for {
_ <- disconnectOldBuildServer()
_ = optProjectRoot match {
shouldImport = optProjectRoot match {
case Some(path) if buildTools.isBloop(path) =>
bloopServers.shutdownServer()
clearBloopDir(path)
case _ =>
false
case Some(path) if buildTools.isBazelBsp =>
tgodzik marked this conversation as resolved.
Show resolved Hide resolved
clearFolders(
path.resolve(Directories.bazelBsp),
path.resolve(Directories.bsp),
)
true
case Some(path) if buildTools.isBsp =>
clearFolders(path.resolve(Directories.bsp))
true
case _ => false
}
_ = tables.cleanAll()
_ <- autoConnectToBuildServer().map(_ => ())
_ <-
if (shouldImport) slowConnectToBuildServer(true)
else autoConnectToBuildServer().map(_ => ())
} yield ()

def getTastyForURI(uri: URI): Future[Either[String, String]] =
Expand Down
Expand Up @@ -345,21 +345,6 @@ trait ScalametaCommonEnrichments extends CommonMtagsEnrichments {
path.toURI.toString
}

def isBazelRelatedPath: Boolean = {
val filename = path.toNIO.getFileName.toString
filename == "WORKSPACE" ||
filename == "BUILD" ||
filename == "BUILD.bazel" ||
filename.endsWith(".bzl") ||
filename.endsWith(".bazelproject")
}

def isInBazelBspDirectory(workspace: AbsolutePath): Boolean =
path.toNIO.startsWith(workspace.resolve(".bazelbsp").toNIO)

def isInBspDirectory(workspace: AbsolutePath): Boolean =
path.toNIO.startsWith(workspace.resolve(".bsp").toNIO)

/*
* This checks if the file has an extension that indicates it's a
* Java or Scala file.
Expand Down
36 changes: 26 additions & 10 deletions tests/slow/src/test/scala/tests/bazel/BazelLspSuite.scala
Expand Up @@ -5,12 +5,14 @@ import scala.concurrent.Promise
import scala.meta.internal.builds.BazelBuildTool
import scala.meta.internal.builds.BazelDigest
import scala.meta.internal.metals.FileDecoderProvider
import scala.meta.internal.metals.Messages
import scala.meta.internal.metals.Messages._
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.ServerCommands
import scala.meta.internal.metals.{BuildInfo => V}
import scala.meta.io.AbsolutePath

import org.eclipse.lsp4j.MessageActionItem
import tests.BaseImportSuite
import tests.BazelBuildLayout
import tests.BazelServerInitializer
Expand Down Expand Up @@ -133,11 +135,21 @@ class BazelLspSuite
}
}

test("import-build") {
test("import-reset-build") {
cleanWorkspace()
writeLayout(
BazelBuildLayout(workspaceLayout, V.bazelScalaVersion, bazelVersion)
)

def getTargetInfo(target: String) = {
server
.executeDecodeFileCommand(
FileDecoderProvider
.createBuildTargetURI(workspace, target)
.toString
)
.map(_.value.linesIterator.take(14).mkString("\n"))
}
for {
_ <- server.initialize()
_ <- server.initialized()
Expand All @@ -155,13 +167,8 @@ class BazelLspSuite
// We need to wait a bit just to ensure the connection is made
_ <- server.server.buildServerPromise.future
targets <- server.listBuildTargets
result <- server.executeDecodeFileCommand(
FileDecoderProvider
.createBuildTargetURI(workspace, targets.head.bazelEscapedDisplayName)
.toString
)
_ = assertNoDiff(
result.value.linesIterator.take(14).mkString("\n"),
result <- getTargetInfo(targets.head.bazelEscapedDisplayName)
expectedTarget =
"""|Target
| @//:hello1
|
Expand All @@ -175,14 +182,23 @@ class BazelLspSuite
| Debug <- NOT SUPPORTED
| Run
| Test <- NOT SUPPORTED
| Compile""".stripMargin,
)
| Compile""".stripMargin
_ = assertNoDiff(result, expectedTarget)
_ = server.server.buildServerPromise = Promise()
_ = client.resetWorkspace =
new MessageActionItem(Messages.ResetWorkspace.resetWorkspace)
_ <- server.executeCommand(ServerCommands.ResetWorkspace)
_ <- server.server.buildServerPromise.future
resultAfter <- getTargetInfo(targets.head.bazelEscapedDisplayName)
_ = assertNoDiff(resultAfter, expectedTarget)
} yield {
assertNoDiff(
client.workspaceMessageRequests,
List(
"bazelbsp bspConfig",
bazelNavigationMessage,
Messages.ResetWorkspace.message,
"bazelbsp bspConfig",
).mkString("\n"),
)
assert(bazelBspConfig.exists)
Expand Down
18 changes: 11 additions & 7 deletions tests/unit/src/main/scala/bill/Bill.scala
Expand Up @@ -30,6 +30,7 @@ import scala.util.Try
import scala.util.control.NonFatal

import scala.meta.internal.metals.BuildInfo
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.Embedded
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.PositionSyntax._
Expand Down Expand Up @@ -476,23 +477,26 @@ object Bill {
* Installed this build tool only for the local workspace
*/
def installWorkspace(
directory: Path,
directory: AbsolutePath,
name: String = "Bill",
): Unit = {
handleInstall(directory.resolve(".bsp"), name)
handleInstall(directory.resolve(Directories.bsp), name)
}

/**
* Installed this build server globally for the machine
*/
def installGlobal(
directory: Path,
directory: AbsolutePath,
name: String = "Bill",
): Unit = {
handleInstall(directory.resolve("bsp"), name)
}

private def handleInstall(directory: Path, name: String = "Bill"): Unit = {
private def handleInstall(
directory: AbsolutePath,
name: String = "Bill",
): Unit = {
val java =
Paths.get(System.getProperty("java.home")).resolve("bin").resolve("java")
val classpath = myClasspath.mkString(File.pathSeparator)
Expand All @@ -511,8 +515,8 @@ object Bill {
)
val json = new GsonBuilder().setPrettyPrinting().create().toJson(details)
val bspJson = directory.resolve(s"${name.toLowerCase()}.json")
Files.createDirectories(directory)
Files.write(bspJson, json.getBytes(StandardCharsets.UTF_8))
directory.createDirectories()
bspJson.writeText(json)
println(s"installed: $bspJson")
}

Expand Down Expand Up @@ -586,7 +590,7 @@ object Bill {
def main(args: Array[String]): Unit = {
args.toList match {
case List("help" | "--help" | "-help" | "-h") => handleHelp()
case List("install") => handleInstall(cwd)
case List("install") => handleInstall(AbsolutePath(cwd))
case List("bsp") => handleBsp()
case List("compile") => handleCompile(cwd)
case List("compile", wd) => handleCompile(Paths.get(wd))
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/src/main/scala/tests/BuildServerInitializer.scala
Expand Up @@ -6,6 +6,7 @@ import scala.util.Properties

import scala.meta.internal.builds.BuildTool
import scala.meta.internal.builds.SbtBuildTool
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.Messages.GenerateBspAndConnect
import scala.meta.internal.metals.Messages.ImportBuild
import scala.meta.internal.metals.MetalsEnrichments._
Expand Down Expand Up @@ -138,7 +139,7 @@ object SbtServerInitializer extends BuildServerInitializer {
workspace: AbsolutePath,
sbtVersion: String,
): Unit = {
val bspFolder = workspace.resolve(".bsp")
val bspFolder = workspace.resolve(Directories.bsp)
val sbtJson = bspFolder.resolve("sbt.json")
// don't overwrite existing BSP config
if (!sbtJson.isFile) {
Expand Down