mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
commit
855b292cda
@ -18,8 +18,9 @@ script:
|
||||
- remark -f README.md > /dev/null
|
||||
- python util/update_lints.py -c
|
||||
- cargo build --features debugging
|
||||
- rm -rf target/ Cargo.lock
|
||||
- cargo test --features debugging
|
||||
- SYSROOT=~/rust cargo install
|
||||
- cargo clippy --lib -- -D clippy
|
||||
|
||||
after_success:
|
||||
# only test regex_macros if it compiles
|
||||
|
@ -16,6 +16,12 @@ keywords = ["clippy", "lint", "plugin"]
|
||||
[lib]
|
||||
name = "clippy"
|
||||
plugin = true
|
||||
test = false
|
||||
|
||||
[[bin]]
|
||||
name = "cargo-clippy"
|
||||
path = "src/lib.rs"
|
||||
test = false
|
||||
|
||||
[dependencies]
|
||||
regex-syntax = "0.3.0"
|
||||
|
30
README.md
30
README.md
@ -173,6 +173,8 @@ More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/
|
||||
|
||||
## Usage
|
||||
|
||||
### As a Compiler Plugin
|
||||
|
||||
Compiler plugins are highly unstable and will only work with a nightly Rust for now.
|
||||
Since stable Rust is backwards compatible, you should be able to compile
|
||||
your stable programs with nightly Rust with clippy plugged in to circumvent
|
||||
@ -217,8 +219,28 @@ src/main.rs:8:5: 11:6 help: Try
|
||||
if let Some(y) = x { println!("{:?}", y) }
|
||||
```
|
||||
|
||||
An alternate way to use clippy is by compiling and using [`cargo clippy`](https://github.com/arcnmx/cargo-clippy),
|
||||
a custom cargo subcommand that runs clippy on a given project.
|
||||
### As a cargo subcommand (`cargo clippy`)
|
||||
|
||||
An alternate way to use clippy is by installing clippy through cargo as a cargo
|
||||
subcommand.
|
||||
|
||||
```terminal
|
||||
cargo install clippy
|
||||
```
|
||||
|
||||
Now you can run clippy by invoking `cargo clippy`, or
|
||||
`multirust run nightly cargo clippy` directly from a directory that is usually
|
||||
compiled with stable.
|
||||
|
||||
In case you are not using multirust, you need to set the environment flag
|
||||
`SYSROOT` during installation so clippy knows where to find `librustc` and
|
||||
similar crates.
|
||||
|
||||
```terminal
|
||||
SYSROOT=/path/to/rustc/sysroot cargo install clippy
|
||||
```
|
||||
|
||||
### Configuring clippy
|
||||
|
||||
You can add options to `allow`/`warn`/`deny`:
|
||||
|
||||
@ -234,6 +256,8 @@ You can add options to `allow`/`warn`/`deny`:
|
||||
|
||||
Note: `deny` produces errors instead of warnings
|
||||
|
||||
### Running clippy from the command line without installing
|
||||
|
||||
To have cargo compile your crate with clippy without needing `#![plugin(clippy)]`
|
||||
in your code, you can use:
|
||||
|
||||
@ -244,6 +268,8 @@ cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy
|
||||
*[Note](https://github.com/Manishearth/rust-clippy/wiki#a-word-of-warning):*
|
||||
Be sure that clippy was compiled with the same version of rustc that cargo invokes here!
|
||||
|
||||
### Optional dependency
|
||||
|
||||
If you want to make clippy an optional dependency, you can do the following:
|
||||
|
||||
In your `Cargo.toml`:
|
||||
|
144
src/lib.rs
144
src/lib.rs
@ -9,11 +9,145 @@
|
||||
#![allow(indexing_slicing, shadow_reuse, unknown_lints)]
|
||||
#![allow(float_arithmetic, integer_arithmetic)]
|
||||
|
||||
// this only exists to allow the "dogfood" integration test to work
|
||||
#[allow(dead_code)]
|
||||
#[allow(print_stdout)]
|
||||
fn main() {
|
||||
println!("What are you doing? Don't run clippy as an executable");
|
||||
extern crate rustc_driver;
|
||||
extern crate getopts;
|
||||
|
||||
use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
|
||||
use rustc::session::{config, Session};
|
||||
use rustc::session::config::{Input, ErrorOutputType};
|
||||
use syntax::diagnostics;
|
||||
use std::path::PathBuf;
|
||||
|
||||
struct ClippyCompilerCalls(RustcDefaultCalls);
|
||||
|
||||
impl std::default::Default for ClippyCompilerCalls {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ClippyCompilerCalls {
|
||||
fn new() -> Self {
|
||||
ClippyCompilerCalls(RustcDefaultCalls)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
|
||||
fn early_callback(&mut self,
|
||||
matches: &getopts::Matches,
|
||||
sopts: &config::Options,
|
||||
descriptions: &diagnostics::registry::Registry,
|
||||
output: ErrorOutputType)
|
||||
-> Compilation {
|
||||
self.0.early_callback(matches, sopts, descriptions, output)
|
||||
}
|
||||
fn no_input(&mut self,
|
||||
matches: &getopts::Matches,
|
||||
sopts: &config::Options,
|
||||
odir: &Option<PathBuf>,
|
||||
ofile: &Option<PathBuf>,
|
||||
descriptions: &diagnostics::registry::Registry)
|
||||
-> Option<(Input, Option<PathBuf>)> {
|
||||
self.0.no_input(matches, sopts, odir, ofile, descriptions)
|
||||
}
|
||||
fn late_callback(&mut self,
|
||||
matches: &getopts::Matches,
|
||||
sess: &Session,
|
||||
input: &Input,
|
||||
odir: &Option<PathBuf>,
|
||||
ofile: &Option<PathBuf>)
|
||||
-> Compilation {
|
||||
self.0.late_callback(matches, sess, input, odir, ofile)
|
||||
}
|
||||
fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
|
||||
let mut control = self.0.build_controller(sess, matches);
|
||||
|
||||
let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
|
||||
control.after_parse.callback = Box::new(move |state| {
|
||||
{
|
||||
let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed"));
|
||||
registry.args_hidden = Some(Vec::new());
|
||||
plugin_registrar(&mut registry);
|
||||
|
||||
let rustc_plugin::registry::Registry { early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, mir_passes, .. } = registry;
|
||||
let sess = &state.session;
|
||||
let mut ls = sess.lint_store.borrow_mut();
|
||||
for pass in early_lint_passes {
|
||||
ls.register_early_pass(Some(sess), true, pass);
|
||||
}
|
||||
for pass in late_lint_passes {
|
||||
ls.register_late_pass(Some(sess), true, pass);
|
||||
}
|
||||
|
||||
for (name, to) in lint_groups {
|
||||
ls.register_group(Some(sess), true, name, to);
|
||||
}
|
||||
|
||||
sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
|
||||
sess.mir_passes.borrow_mut().extend(mir_passes);
|
||||
sess.plugin_attributes.borrow_mut().extend(attributes);
|
||||
}
|
||||
old(state);
|
||||
});
|
||||
|
||||
control
|
||||
}
|
||||
}
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
pub fn main() {
|
||||
use std::env;
|
||||
|
||||
if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps");
|
||||
let sys_root = match (option_env!("MULTIRUST_HOME"), option_env!("MULTIRUST_TOOLCHAIN")) {
|
||||
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
|
||||
_ => option_env!("SYSROOT").expect("need to specify SYSROOT env var during clippy compilation or use multirust").to_owned(),
|
||||
};
|
||||
|
||||
if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
|
||||
let args = wrap_args(std::env::args().skip(2), dep_path, sys_root);
|
||||
let path = std::env::current_exe().expect("current executable path invalid");
|
||||
let run = std::process::Command::new("cargo")
|
||||
.args(&args)
|
||||
.env("RUSTC", path)
|
||||
.spawn().expect("could not run cargo")
|
||||
.wait().expect("failed to wait for cargo?")
|
||||
.success();
|
||||
assert!(run, "cargo rustc failed");
|
||||
} else {
|
||||
let args: Vec<String> = if env::args().any(|s| s == "--sysroot") {
|
||||
env::args().collect()
|
||||
} else {
|
||||
env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect()
|
||||
};
|
||||
rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new());
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_args<P, I>(old_args: I, dep_path: P, sysroot: String) -> Vec<String>
|
||||
where P: AsRef<Path>, I: Iterator<Item=String> {
|
||||
|
||||
let mut args = vec!["rustc".to_owned()];
|
||||
|
||||
let mut found_dashes = false;
|
||||
for arg in old_args {
|
||||
found_dashes |= arg == "--";
|
||||
args.push(arg);
|
||||
}
|
||||
if !found_dashes {
|
||||
args.push("--".to_owned());
|
||||
}
|
||||
args.push("-L".to_owned());
|
||||
args.push(dep_path.as_ref().to_string_lossy().into_owned());
|
||||
args.push(String::from("--sysroot"));
|
||||
args.push(sysroot);
|
||||
args.push("-Zno-trans".to_owned());
|
||||
args
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
|
@ -1,9 +1,11 @@
|
||||
#![feature(test)]
|
||||
#![feature(test, plugin)]
|
||||
#![plugin(clippy)]
|
||||
#![deny(clippy, clippy_pedantic)]
|
||||
|
||||
extern crate compiletest_rs as compiletest;
|
||||
extern crate test;
|
||||
|
||||
use std::env::var;
|
||||
use std::env::{var, set_var};
|
||||
use std::path::PathBuf;
|
||||
use test::TestPaths;
|
||||
|
||||
@ -11,15 +13,14 @@ use test::TestPaths;
|
||||
fn dogfood() {
|
||||
let mut config = compiletest::default_config();
|
||||
|
||||
let cfg_mode = "run-pass".parse().ok().expect("Invalid mode");
|
||||
let cfg_mode = "run-pass".parse().expect("Invalid mode");
|
||||
let mut s = String::new();
|
||||
s.push_str(" -L target/debug/");
|
||||
s.push_str(" -L target/debug/deps");
|
||||
s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy");
|
||||
config.target_rustcflags = Some(s);
|
||||
if let Ok(name) = var::<&str>("TESTNAME") {
|
||||
let s : String = name.to_owned();
|
||||
config.filter = Some(s)
|
||||
if let Ok(name) = var("TESTNAME") {
|
||||
config.filter = Some(name.to_owned())
|
||||
}
|
||||
|
||||
config.mode = cfg_mode;
|
||||
@ -29,5 +30,8 @@ fn dogfood() {
|
||||
file: PathBuf::from("src/lib.rs"),
|
||||
relative_dir: PathBuf::new(),
|
||||
};
|
||||
|
||||
set_var("CLIPPY_DOGFOOD", "tastes like chicken");
|
||||
|
||||
compiletest::runtest::run(config, &paths);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user