bazelbuild / rules_rust

Rust rules for Bazel
https://bazelbuild.github.io/rules_rust/
Apache License 2.0
671 stars 434 forks source link

rust-project.json not picked up by rust-analyzer on third_party code #2175

Open brt-adam-snaider opened 1 year ago

brt-adam-snaider commented 1 year ago

I ran bazel run @rules_rust//tools/rust_analyzer:gen_rust_project and it generates a rust-project.json that provides LSP funcitonality for all first-party code. However, I have some vendored third-party dependencies that I would like to get LSP functionality for as well. Can this be done? I tried passing in @my_third_party//... to the list of targets when running gen_rust_project, but that only adds the targets in the exec root, so the LSP doesn't pick it up when editing the third-party code directly.

Even if I generate the rust-project.json specifically for the third_party code, that doesn't work because rust-analyzer picks up the wrong rust-project.json as far as I can tell.

Any thoughts on how to support this functionality? I'm happy to make PR to work once I have a path forward.

Thanks!

brt-adam-snaider commented 1 year ago

Fyi, I'm using this patch to get around this. Not sure if this is something we'll want to merge in

diff --git a/rust/private/rust_analyzer.bzl b/rust/private/rust_analyzer.bzl
index 3eea6c08..e2111671 100644
--- a/rust/private/rust_analyzer.bzl
+++ b/rust/private/rust_analyzer.bzl
@@ -204,10 +204,9 @@ def _create_single_crate(ctx, info):
     # TODO: Some folks may want to override this for vendored dependencies.
     is_external = info.crate.root.path.startswith("external/")
     is_generated = not info.crate.root.is_source
-    path_prefix = _EXEC_ROOT_TEMPLATE if is_external or is_generated else ""
-    crate["is_workspace_member"] = not is_external
-    crate["root_module"] = path_prefix + info.crate.root.path
-    crate_root = path_prefix + info.crate.root.dirname
+    crate["is_workspace_member"] = True
+    crate["root_module"] = info.crate.root.path
+    crate_root = info.crate.root.dirname

     if info.build_info != None:
         out_dir_path = info.build_info.out_dir.path
diff --git a/tools/rust_analyzer/aquery.rs b/tools/rust_analyzer/aquery.rs
index 98f145be..fda67a04 100644
--- a/tools/rust_analyzer/aquery.rs
+++ b/tools/rust_analyzer/aquery.rs
@@ -100,6 +100,14 @@ pub fn get_crate_specs(
             serde_json::from_reader(f)
                 .with_context(|| format!("Failed to deserialize file: {}", file.display()))
         })
+        .map(|krate| {
+            let mut krate: CrateSpec = krate?;
+            let fullpath = workspace.join(&krate.root_module);
+            if let Ok(path) = std::fs::canonicalize(&fullpath) {
+                krate.root_module = path.into_os_string().into_string().unwrap();
+            }
+            Ok(krate)
+        })
         .collect::<anyhow::Result<Vec<CrateSpec>>>()?;

     consolidate_crate_specs(crate_specs)