| #!/usr/bin/env python |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| ### Runs `cargo clippy` on a target or on a set of files. |
| |
| import argparse |
| import json |
| import os |
| import subprocess |
| import sys |
| |
| from contextlib import contextmanager |
| |
| import rust |
| from rust import FUCHSIA_BUILD_DIR, HOST_PLATFORM, PREBUILT_THIRD_PARTY_DIR, \ |
| get_rust_target_from_file |
| |
| PATH = os.environ["PATH"] |
| THIRD_PARTY_DEPS_DATA = os.path.join( |
| FUCHSIA_BUILD_DIR, 'rust_third_party_crates', 'deps_data.json') |
| HOST_THIRD_PARTY_DEPS_DATA = os.path.join( |
| FUCHSIA_BUILD_DIR, 'host_x64', 'rust_third_party_crates', 'deps_data.json') |
| |
| # Cargo args to ignore from the deps_data.json files. |
| CARGO_IGNORE_ARGS = ['--frozen', '--locked'] |
| |
| @contextmanager |
| def cwd(dir): |
| previous = os.getcwd() |
| os.chdir(dir) |
| try: |
| yield |
| finally: |
| os.chdir(previous) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser("Run cargo clippy on a file or target.") |
| parser.add_argument( |
| "--target", |
| help="GN target on which to run clippy", |
| default=None) |
| parser.add_argument( |
| "--file", |
| dest="files", |
| help="file on which to run clippy", |
| action="append", |
| default=[]) |
| parser.add_argument( |
| "-v", help="verbose", action="store_true", default=False) |
| args = parser.parse_args() |
| |
| targets = set() |
| if args.target: |
| try: |
| targets.add(rust.GnTarget(target)) |
| except ValueError as e: |
| # The target may not be a Rust one, so it's okay if it didn't find the Cargo.toml. |
| if args.v: |
| print "No Rust target found for %s: %s" % (target, e) |
| |
| for file in args.files: |
| # Skip non-rust files. |
| if not file.endswith(".rs"): |
| continue |
| |
| try: |
| target = get_rust_target_from_file(file) |
| if not target: |
| return 1 |
| except ValueError as e: |
| # The target should be a Rust one, so any error is bad. |
| print "No Rust target found for %s: %s" % (file, e) |
| return 1 |
| |
| targets.add(target) |
| |
| cargos = set() |
| for target in targets: |
| cargo = target.manifest_path(FUCHSIA_BUILD_DIR) |
| if cargo and os.path.isfile(cargo): |
| cargos.add(cargo) |
| else: |
| print "Cargo.toml file not found for %s, try running fx build." % target |
| return 1 |
| |
| rust_tool_prebuilts = \ |
| os.path.join(PREBUILT_THIRD_PARTY_DIR, "rust_tools", HOST_PLATFORM, "bin") |
| rust_prebuilts = os.path.join(PREBUILT_THIRD_PARTY_DIR, "rust", HOST_PLATFORM, "bin") |
| |
| # The third_party build records the arguments it used to invoke cargo. Use the same ones for |
| # the clippy invocation. |
| third_party_deps_data = json.load(open(THIRD_PARTY_DEPS_DATA, 'r')) |
| host_third_party_deps_data = json.load( |
| open(HOST_THIRD_PARTY_DEPS_DATA, 'r')) |
| |
| env = {} |
| env['PATH'] = ":".join([rust_tool_prebuilts, rust_prebuilts, PATH]) |
| call_args = [ |
| "cargo", |
| "clippy", |
| ] |
| |
| if args.v: |
| call_args.append("-v") |
| |
| for cargo in cargos: |
| if 'host_x64' in cargo: |
| cargo_args = host_third_party_deps_data['cargo_args'] |
| else: |
| cargo_args = third_party_deps_data['cargo_args'] |
| cargo_args = filter(lambda arg: arg not in CARGO_IGNORE_ARGS, cargo_args) |
| # Some crates use #![deny(warnings)], which will cause clippy to fail entirely if it finds |
| # issues in those crates. Cap all lints at `warn` to avoid this. |
| cargo_args += ['--', '--cap-lints', 'warn'] |
| if args.v: |
| print " ".join(call_args + cargo_args) |
| with cwd(os.path.dirname(cargo)): |
| return subprocess.call(call_args + cargo_args, env=env) |
| |
| return 0 |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |