forked from bazelbuild/rules_rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrust_analyzer.vm
More file actions
156 lines (126 loc) · 5.89 KB
/
rust_analyzer.vm
File metadata and controls
156 lines (126 loc) · 5.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#[[
## Overview
For [non-Cargo projects](https://rust-analyzer.github.io/manual.html#non-cargo-based-projects),
[rust-analyzer](https://rust-analyzer.github.io/) depends on either a `rust-project.json` file
at the root of the project that describes its structure or on build system specific
[project auto-discovery](https://rust-analyzer.github.io/manual.html#rust-analyzer.workspace.discoverConfig).
The `rust_analyzer` rules facilitate both approaches.
## rust-project.json approach
### Setup
First, ensure `rules_rust` is setup in your workspace. By default, `rust_register_toolchains` will
ensure a [rust_analyzer_toolchain](#rust_analyzer_toolchain) is registered within the WORKSPACE.
Next, load the dependencies for the `rust-project.json` generator tool:
```python
load("@rules_rust//tools/rust_analyzer:deps.bzl", "rust_analyzer_dependencies")
rust_analyzer_dependencies()
```
Finally, run `bazel run @rules_rust//tools/rust_analyzer:gen_rust_project`
whenever dependencies change to regenerate the `rust-project.json` file. It
should be added to `.gitignore` because it is effectively a build artifact.
Once the `rust-project.json` has been generated in the project root,
rust-analyzer can pick it up upon restart.
For users who do not use `rust_register_toolchains` to register toolchains, the following can be added
to their WORKSPACE to register a `rust_analyzer_toolchain`. Please make sure the Rust version used in
this toolchain matches the version used by the currently registered toolchain or the sources/documentation
will not match what's being compiled with and can lead to confusing results.
```python
load("@rules_rust//rust:repositories.bzl", "rust_analyzer_toolchain_repository")
register_toolchains(rust_analyzer_toolchain_repository(
name = "rust_analyzer_toolchain",
# This should match the currently registered toolchain.
version = "1.63.0",
))
```
#### VSCode
To set this up using [VSCode](https://code.visualstudio.com/), users should first install the
[rust_analyzer plugin](https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer).
With that in place, the following task can be added to the `.vscode/tasks.json` file of the workspace
to ensure a `rust-project.json` file is created and up to date when the editor is opened.
```json
{
"version": "2.0.0",
"tasks": [
{
"label": "Generate rust-project.json",
"command": "bazel",
"args": [
"run",
"@rules_rust//tools/rust_analyzer:gen_rust_project"
],
"options": {
"cwd": "${workspaceFolder}"
},
"group": "build",
"problemMatcher": [],
"presentation": {
"reveal": "never",
"panel": "dedicated"
},
"runOptions": {
"runOn": "folderOpen"
}
},
]
}
```
#### Alternative vscode option (prototype)
Add the following to your bazelrc:
```
build --@rules_rust//rust/settings:rustc_output_diagnostics=true --output_groups=+rust_lib_rustc_output,+rust_metadata_rustc_output
```
Then you can use a prototype [rust-analyzer plugin](https://marketplace.visualstudio.com/items?itemName=MattStark.bazel-rust-analyzer) that automatically collects the outputs whenever you recompile.
## Project auto-discovery
### Setup
Auto-discovery makes `rust-analyzer` behave in a Bazel project in a similar fashion to how it does
in a Cargo project. This is achieved by generating a structure similar to what `rust-project.json`
contains but, instead of writing that to a file, the data gets piped to `rust-analyzer` directly
through `stdout`. To use auto-discovery the `rust-analyzer` IDE settings must be configured similar to:
```json
"rust-analyzer": {
"workspace": {
"discoverConfig": {
"command": ["discover_bazel_rust_project.sh"],
"progressLabel": "rust_analyzer",
"filesToWatch": ["BUILD", "BUILD.bazel", "MODULE.bazel"]
}
}
}
```
The shell script passed to `discoverConfig.command` is typically meant to wrap the bazel rule invocation,
primarily for muting `stderr` (because `rust-analyzer` will consider that an error has occurred if anything
is passed through `stderr`) and, additionally, for specifying rule arguments. E.g:
```shell
#!/usr/bin/bash
bazel \
run \
@rules_rust//tools/rust_analyzer:discover_bazel_rust_project -- \
--bazel_startup_option=--output_base=~/ide_bazel \
--bazel_arg=--watchfs \
${1:+"$1"} 2>/dev/null
```
The script above also handles an optional CLI argument which gets passed when workspace splitting is
enabled. The script path should be either absolute or relative to the project root.
### Workspace splitting
The above configuration treats the entire project as a single workspace. However, large codebases might be
too much to handle for `rust-analyzer` all at once. This can be addressed by splitting the codebase in
multiple workspaces by extending the `discoverConfig.command` setting:
```json
"rust-analyzer": {
"workspace": {
"discoverConfig": {
"command": ["discover_bazel_rust_project.sh", "{arg}"],
"progressLabel": "rust_analyzer",
"filesToWatch": ["BUILD", "BUILD.bazel", "MODULE.bazel"]
}
}
}
```
`{arg}` acts as a placeholder that `rust-analyzer` replaces with the path of the source / build file
that gets opened.
The root of the workspace will, in this configuration, be the package the crate currently being worked on
belongs to. This means that only that package and its dependencies get built and indexed by `rust-analyzer`,
thus allowing for a smaller footprint.
`rust-analyzer` will switch workspaces whenever an out-of-tree file gets opened, essentially indexing that
crate and its dependencies separately. A caveat of this is that *dependents* of the crate currently being
worked on are not indexed and won't be tracked by `rust-analyzer`.
]]#