77 lines
3.0 KiB
Python
77 lines
3.0 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright 2024 The Meson development team
|
|
|
|
from __future__ import annotations
|
|
from collections import defaultdict
|
|
import os
|
|
import tempfile
|
|
import typing as T
|
|
|
|
from .run_tool import run_tool_on_targets, run_with_buffered_output
|
|
from .. import build, mlog
|
|
from ..mesonlib import MachineChoice, PerMachine
|
|
|
|
if T.TYPE_CHECKING:
|
|
from ..compilers.rust import RustCompiler
|
|
|
|
class ClippyDriver:
|
|
def __init__(self, build: build.Build, tempdir: str):
|
|
self.tools: PerMachine[T.List[str]] = PerMachine([], [])
|
|
self.warned: T.DefaultDict[str, bool] = defaultdict(lambda: False)
|
|
self.tempdir = tempdir
|
|
for machine in MachineChoice:
|
|
compilers = build.environment.coredata.compilers[machine]
|
|
if 'rust' in compilers:
|
|
compiler = T.cast('RustCompiler', compilers['rust'])
|
|
self.tools[machine] = compiler.get_rust_tool('clippy-driver', build.environment)
|
|
|
|
def warn_missing_clippy(self, machine: str) -> None:
|
|
if self.warned[machine]:
|
|
return
|
|
mlog.warning(f'clippy-driver not found for {machine} machine')
|
|
self.warned[machine] = True
|
|
|
|
def __call__(self, target: T.Dict[str, T.Any]) -> T.Iterable[T.Coroutine[None, None, int]]:
|
|
for src_block in target['target_sources']:
|
|
if 'compiler' in src_block and src_block['language'] == 'rust':
|
|
clippy = getattr(self.tools, src_block['machine'])
|
|
if not clippy:
|
|
self.warn_missing_clippy(src_block['machine'])
|
|
continue
|
|
|
|
cmdlist = list(clippy)
|
|
prev = None
|
|
lints_cap = None
|
|
for arg in src_block['parameters']:
|
|
if prev == '--cap-lints':
|
|
cmdlist.append(prev)
|
|
lints_cap = arg
|
|
prev = None
|
|
elif prev:
|
|
prev = None
|
|
continue
|
|
if arg in {'--emit', '--out-dir', '--cap-lints'}:
|
|
prev = arg
|
|
else:
|
|
cmdlist.append(arg)
|
|
|
|
# no use in running clippy if it wouldn't print anything anyway
|
|
if lints_cap == 'allow':
|
|
break
|
|
|
|
cmdlist.extend(src_block['sources'])
|
|
# the default for --emit is to go all the way to linking,
|
|
# and --emit dep-info= is not enough for clippy to do
|
|
# enough analysis, so use --emit metadata.
|
|
cmdlist.append('--emit')
|
|
cmdlist.append('metadata')
|
|
cmdlist.append('--out-dir')
|
|
cmdlist.append(self.tempdir)
|
|
yield run_with_buffered_output(cmdlist)
|
|
|
|
def run(args: T.List[str]) -> int:
|
|
os.chdir(args[0])
|
|
build_data = build.load(os.getcwd())
|
|
with tempfile.TemporaryDirectory() as d:
|
|
return run_tool_on_targets(ClippyDriver(build_data, d))
|