Skip to content

Commit 651fe54

Browse files
committed
add clippy-json target
Add a clippy-json target to the ninja script. This is useful for rust-analyzer, which requires an "external check command" to function when not using cargo. Also we add a "clippy-json-prereq" target, and invoke it in the clippy.py script. The prereq target tries to build as much of the project as possible with "-k0".
1 parent bfa96de commit 651fe54

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

docs/markdown/Rust.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ write files into the source directory). [See the upstream
9191
docs](https://rust-analyzer.github.io/book/non_cargo_based_projects.html) for
9292
more information on how to configure that.
9393

94+
### Clippy
95+
You can use the "clippy-json" build target as rust-analyer's "check command" to recieve clippy diagnostics in your editor.
96+
97+
Without overriding the check command, the LSP will function in a limited state, only showing certain errors (for example, no borrow checking errors are shown).
98+
99+
[Non cargo based projects](https://rust-analyzer.github.io/book/non_cargo_based_projects.html) shows how to override the check command, you probably want to set it to `ninja clippy-json -C build`.
100+
94101
## Linking with standard libraries
95102

96103
Meson will link the Rust standard libraries (e.g. libstd) statically, unless the
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# New "clippy-json" Ninja Target For rust-analyzer
2+
3+
A new `clippy-json` ninja target will now be generated for rust projects.
4+
5+
rust-analyzer supports non-cargo based projects so long as you provide it with a `rust-project.json` file and a custom "check command" to provide compiler errors.
6+
7+
Meson already for some time has generated a `rust-project.json` file for rust-analyzer, but had no way to hook up its rustc/clippy output to rust-analyzer.
8+
9+
To use the new feature, you want to override the rust-analyzer check command as shown [here](https://rust-analyzer.github.io/book/non_cargo_based_projects.html), and set it to `ninja clippy-json -C build` or something to the same effect.

mesonbuild/backend/ninjabackend.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3947,6 +3947,28 @@ def generate_clippy(self) -> None:
39473947
elem.add_dep(list(self.all_structured_sources))
39483948
self.add_build(elem)
39493949

3950+
def generate_clippy_json_prereq(self) -> None:
3951+
if 'clippy-json-prereq' in self.all_outputs or not self.have_language('rust'):
3952+
return
3953+
3954+
elem = self.create_phony_target('clippy-json-prereq', 'CUSTOM_COMMAND', 'PHONY')
3955+
for crate in self.rust_crates.values():
3956+
if crate.crate_type in {'rlib', 'dylib', 'proc-macro'}:
3957+
elem.add_dep(crate.target_name)
3958+
elem.add_dep(list(self.all_structured_sources))
3959+
self.add_build(elem)
3960+
3961+
def generate_clippy_json(self) -> None:
3962+
if 'clippy-json' in self.all_outputs or not self.have_language('rust'):
3963+
return
3964+
3965+
cmd = self.environment.get_build_command() + \
3966+
['--internal', 'clippy', self.environment.build_dir, '--error-format=json']
3967+
elem = self.create_phony_target('clippy-json', 'CUSTOM_COMMAND', 'PHONY')
3968+
elem.add_item('COMMAND', cmd)
3969+
elem.add_item('pool', 'console')
3970+
self.add_build(elem)
3971+
39503972
def generate_rustdoc(self) -> None:
39513973
if 'rustdoc' in self.all_outputs or not self.have_language('rust'):
39523974
return
@@ -4036,6 +4058,8 @@ def generate_utils(self) -> None:
40364058
self.generate_clangformat()
40374059
self.generate_clangtidy()
40384060
self.generate_clippy()
4061+
self.generate_clippy_json_prereq()
4062+
self.generate_clippy_json()
40394063
self.generate_rustdoc()
40404064
self.generate_tags('etags', 'TAGS')
40414065
self.generate_tags('ctags', 'ctags')

mesonbuild/scripts/clippy.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
import os
77
import tempfile
88
import typing as T
9+
import subprocess
910

1011
from .run_tool import run_tool_on_targets, run_with_buffered_output
1112
from .. import build, mlog
1213
from ..mesonlib import MachineChoice, PerMachine
14+
from ..tooldetect import detect_ninja
1315

1416
if T.TYPE_CHECKING:
1517
from ..compilers.rust import RustCompiler
1618

1719
class ClippyDriver:
18-
def __init__(self, build: build.Build, tempdir: str):
20+
def __init__(self, build: build.Build, tempdir: str, args: list[str]):
1921
self.tools: PerMachine[T.List[str]] = PerMachine([], [])
2022
self.warned: T.DefaultDict[str, bool] = defaultdict(lambda: False)
2123
self.tempdir = tempdir
@@ -24,6 +26,7 @@ def __init__(self, build: build.Build, tempdir: str):
2426
if 'rust' in compilers:
2527
compiler = T.cast('RustCompiler', compilers['rust'])
2628
self.tools[machine] = compiler.get_rust_tool('clippy-driver')
29+
self.args = args
2730

2831
def warn_missing_clippy(self, machine: str) -> None:
2932
if self.warned[machine]:
@@ -67,10 +70,17 @@ def __call__(self, target: T.Dict[str, T.Any]) -> T.Iterable[T.Coroutine[None, N
6770
cmdlist.append('metadata')
6871
cmdlist.append('--out-dir')
6972
cmdlist.append(self.tempdir)
73+
cmdlist += self.args
7074
yield run_with_buffered_output(cmdlist)
7175

7276
def run(args: T.List[str]) -> int:
7377
os.chdir(args[0])
7478
build_data = build.load(os.getcwd())
79+
80+
# Build as much of the project as possible, or else
81+
# we get errors about missing libraries in the build directory and
82+
# other related errors.
83+
subprocess.run(detect_ninja() + ['clippy-json-prereq', '-k0'])
84+
7585
with tempfile.TemporaryDirectory() as d:
76-
return run_tool_on_targets(ClippyDriver(build_data, d))
86+
return run_tool_on_targets(ClippyDriver(build_data, d, args[1:]))

0 commit comments

Comments
 (0)