-
Notifications
You must be signed in to change notification settings - Fork 337
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
feature: Support Bazel as a build tool #3233
Conversation
I managed to generate SemanticDB in my test-project but it turns out that bazel doesn't have any folder where it stores compilation artifacts (at least I didn't find anything + metals decode command didn't point me to any useful directory), everything is loaded directly to the jar in |
While we can generate `.bsp/bazelbsp.json` by `cs launch org.jetbrains.bsp;bazel-bsp:2.6.1 -M org.jetbrains.bsp.bazel.instal.Install` https://github.com/JetBrains/bazel-bsp#easy-way-coursier Metals couldn't connect to the bazel-bsp because it wan't autoConnectable. This change enable Metals to see bazel-bsp as autoConnectable, and Metals will spawn and connct to bazel bsp if there's `.bsp/bazelbsp.json`. As @kpodsiad did in scalameta#3233 we should - reindex if the build configuration changed - I'm wondering we should check all *.bzl files and WORKSPACE and BUILD / BUILD.bazel files. And maybe we should honor the project view settings. - Auto install bazel-bsp when we see `WORKSPACE` file. scalameta#5138 partially fix for scalameta#5064
While we can generate `.bsp/bazelbsp.json` by `cs launch org.jetbrains.bsp;bazel-bsp:2.6.1 -M org.jetbrains.bsp.bazel.instal.Install` https://github.com/JetBrains/bazel-bsp#easy-way-coursier Metals couldn't connect to the bazel-bsp because it wan't autoConnectable. This change enable Metals to see bazel-bsp as autoConnectable, and Metals will spawn and connct to bazel bsp if there's `.bsp/bazelbsp.json`. As @kpodsiad did in #3233 we should - reindex if the build configuration changed - I'm wondering we should check all *.bzl files and WORKSPACE and BUILD / BUILD.bazel files. And maybe we should honor the project view settings. - Auto install bazel-bsp when we see `WORKSPACE` file. #5138 partially fix for #5064
If `WORKSPACE` is found, and `.bsp/bazelbsp.json` is not found, install bazel-bsp 2.7.1 and write the config file to `.bsp/bazelbsp.json`.
we should update metals-vscode so it fires textDocument/didSave
I added some changes so that
have to fix tests |
Do you need any help to finish? If you don't have time we can take over. |
Thanks @tgodzik maybe it's better someone picks up to take over this and finishing it up :) Scope
SemanticDB support shouldn't be a scope of this PR. Future work
You should be able to test against a small Bazel project here: https://github.com/tanishiking/bazel-playground/tree/main/01-scala-tutorial By default, rules_scala will use Scala 2.13.6. |
@jkciesluk kindly took over the rest of work 💯 |
When aths where empty, FileWatcher was watching the entire file system
Adds two improvements: 1. After changing BUILD, WORKSPACE or *.bzl file, user will be prompted to import build. 2. If .bazelbsp is not present, user will be asked if they want to create it (the same way as with .bloop)
Previously cheksum was not persisted there, so first save of build file would result in unnecessary reload
Adds tests for connecting to build server using GenerateBspConfig and ImportBuild commands
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few generic comments:
- It would be great to have some docs about bazel suport.
- It seems we don't have
semanticdb
and so on for bazel, and this results inmultiple problems detected
, it'd be great to let the user know, that this is expected for bazel not actual problem with their build. So maybe a different message? - When I tired changing the scala version I got:
bazelbsp does not support `workspace/reload`, unable to reload
in logs, and those changes weren't actually imported. Am I missing something?
metals/src/main/scala/scala/meta/internal/bsp/BspConnector.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/builds/BazelBuildTool.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala
Outdated
Show resolved
Hide resolved
!tables.buildServers | ||
.selectedServer() | ||
.contains(path.filename.stripSuffix(".json")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it ever actually switch between build servers? Or can we check tables.buildServers.isEmpty
&& no bloop instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it works good? If the currently chosen server is the same as the one that appeared in the .bsp
, we don't want to call quickConnectToBuildServer
, because it's most likely already been called in other place, but if some other build server appears we want to notify the user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have an explicitly chosen build server (saved in tables.buildServers
) and call quickConnectToBuildServer
it will connect to that choice and ignore other possibilities. So you'll just reconnect to the same build server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So maybe if the newly added build tool is different from the one in tables.buildServers
, we can clean this table and then call quickConnectToBuildServer
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If someone adds sbt
you'll have to call slowConnect
for the bloop config to generate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can wait for someone invoking Switch build server command
in that case I think. If they are already using a bsp server. This will be a rare enough scenario.
metals/src/main/scala/scala/meta/internal/metals/Compilations.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/metals/MetalsEnrichments.scala
Show resolved
Hide resolved
_ <- server.fullServer | ||
.didChangeWatchedFiles( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that needed? Shouldn't the file watcher detect the change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File watcher detects changes from the other didChangeWatchedFiles
, but this change is from lsp workspace/didChangeWatchedFiles
. I'm not sure why we need both and which notifications should belong where
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that we need both, since not all editors do workspace/didChangeWatchedFiles
(at least not reliably), so workspace/didChangeWatchedFiles
is sort of "additional". @tgodzik, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, at least from what I remember. For build tool files we use the LSP since this should be fairly reliable.
metals/src/main/scala/scala/meta/internal/bsp/BspConnector.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/bsp/BspConnector.scala
Outdated
Show resolved
Hide resolved
@@ -343,7 +343,8 @@ object MetalsEnrichments | |||
|
|||
def isDependencySource(workspace: AbsolutePath): Boolean = { | |||
(isLocalFileSystem(workspace) && | |||
isInReadonlyDirectory(workspace)) || isJarFileSystem | |||
(isInReadonlyDirectory(workspace) || isInTmpDirectory(workspace))) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When do we put sources into tmp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In ScalafixProvier.load()
, but looks like this check is not needed anymore, I will remove it.
!tables.buildServers | ||
.selectedServer() | ||
.contains(path.filename.stripSuffix(".json")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can wait for someone invoking Switch build server command
in that case I think. If they are already using a bsp server. This will be a rare enough scenario.
1648f50
to
e5ec695
Compare
It also looks like the presentation compiler is not started with the right classpath, I can't see any hover or completions from dependency module (like Hello in the sample). |
def multipleProblemsDetected: String = | ||
s"Multiple problems detected in your build." | ||
|
||
def bazelNavigation: String = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we suggest the flag to use to enable it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently there is no easy way to enable this, it would require changes in both metals and the users project. I think its best to work on it in a follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two minor things otherwise LGTM
@@ -176,16 +176,30 @@ class ProblemResolver( | |||
futureMessage, | |||
).flatten | |||
|
|||
def noSemanticDBMessages = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we instead create bazel message instead of the basic semanticdb ones if the current build server is bazel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, we do (see Messages.CheckDoctor.bazelNavigation
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I mean is that noSemanticDBMessages
is used to figure out if there are no semanticdb messages, why do we need this as a fllback, instead of checking for semanticdb flags together with bazel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right, I will try to change that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Let's make sure we squash here, great work @jkciesluk ! 🚀 |
Add support for Bazel.
I created a simple project which uses Bazel and could be used for testing this integration.
Known todos:
SemanticDB Generation (gives find references) JetBrains/bazel-bsp#105SemanticDB phases bazelbuild/rules_scala#952 - without semanticDB metals capabilities are very limited. However, one can add to his BUILD scalac option which enables semanticdb plugin -scalacopts = ["-Xplugin:<path_to_semanticdb_jar>", "-Yrangepos", "-P:semanticdb:targetroot:<path_to_generated_semanticdb>"]
Attempt to generate bsp config for build tool
and thenswitch build server
. This could be done automatically, I think.