mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 23:20:39 +00:00
Merge pull request #586 from mcarton/print
Add a lint to warn about use of `print{,ln}!`
This commit is contained in:
commit
783b342bc1
5 changed files with 93 additions and 1 deletions
|
@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code.
|
|||
[Jump to usage instructions](#usage)
|
||||
|
||||
##Lints
|
||||
There are 100 lints included in this crate:
|
||||
There are 101 lints included in this crate:
|
||||
|
||||
name | default | meaning
|
||||
---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -73,6 +73,7 @@ name
|
|||
[out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing
|
||||
[panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!`
|
||||
[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught
|
||||
[print_stdout](https://github.com/Manishearth/rust-clippy/wiki#print_stdout) | allow | printing on stdout
|
||||
[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively
|
||||
[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator
|
||||
[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
// 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");
|
||||
}
|
||||
|
@ -77,6 +78,7 @@ pub mod misc_early;
|
|||
pub mod array_indexing;
|
||||
pub mod panic;
|
||||
pub mod derive;
|
||||
pub mod print;
|
||||
|
||||
mod reexport {
|
||||
pub use syntax::ast::{Name, NodeId};
|
||||
|
@ -141,6 +143,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
reg.register_late_lint_pass(box strings::StringLitAsBytes);
|
||||
reg.register_late_lint_pass(box derive::Derive);
|
||||
reg.register_late_lint_pass(box types::CharLitAsU8);
|
||||
reg.register_late_lint_pass(box print::PrintLint);
|
||||
|
||||
|
||||
reg.register_lint_group("clippy_pedantic", vec![
|
||||
|
@ -149,6 +152,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
methods::WRONG_PUB_SELF_CONVENTION,
|
||||
mut_mut::MUT_MUT,
|
||||
mutex_atomic::MUTEX_INTEGER,
|
||||
print::PRINT_STDOUT,
|
||||
shadow::SHADOW_REUSE,
|
||||
shadow::SHADOW_SAME,
|
||||
shadow::SHADOW_UNRELATED,
|
||||
|
|
49
src/print.rs
Normal file
49
src/print.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use utils::{IO_PRINT_PATH, is_expn_of, match_path, span_lint};
|
||||
|
||||
/// **What it does:** This lint warns whenever you print on *stdout*. This lint is `Allow` by
|
||||
/// default, the purpose is to catch debugging remnants.
|
||||
///
|
||||
/// **Why is this bad?** People often print on *stdout* while debugging an application and might
|
||||
/// forget to remove those prints afterward.
|
||||
///
|
||||
/// **Known problems:** Only catches `print!` and `println!` calls.
|
||||
///
|
||||
/// **Example:** `println!("Hello world!");`
|
||||
declare_lint! {
|
||||
pub PRINT_STDOUT,
|
||||
Allow,
|
||||
"printing on stdout"
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PrintLint;
|
||||
|
||||
impl LintPass for PrintLint {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(PRINT_STDOUT)
|
||||
}
|
||||
}
|
||||
|
||||
impl LateLintPass for PrintLint {
|
||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||
if let ExprCall(ref fun, _) = expr.node {
|
||||
if let ExprPath(_, ref path) = fun.node {
|
||||
if match_path(path, &IO_PRINT_PATH) {
|
||||
if let Some(span) = is_expn_of(cx, expr.span, "print") {
|
||||
let (span, name) = match is_expn_of(cx, span, "println") {
|
||||
Some(span) => (span, "println"),
|
||||
None => (span, "print"),
|
||||
};
|
||||
|
||||
span_lint(cx,
|
||||
PRINT_STDOUT,
|
||||
span,
|
||||
&format!("use of `{}!`", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
src/utils.rs
27
src/utils.rs
|
@ -29,6 +29,7 @@ pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]
|
|||
pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"];
|
||||
pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"];
|
||||
pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"];
|
||||
pub const IO_PRINT_PATH: [&'static str; 3] = ["std", "io", "_print"];
|
||||
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
|
||||
pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"];
|
||||
pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"];
|
||||
|
@ -645,3 +646,29 @@ fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the pre-expansion span is this comes from a expansion of the macro `name`.
|
||||
pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> {
|
||||
loop {
|
||||
let span_name_span = cx.tcx.sess.codemap().with_expn_info(span.expn_id, |expn| {
|
||||
expn.map(|ei| {
|
||||
(ei.callee.name(), ei.call_site)
|
||||
})
|
||||
});
|
||||
|
||||
return match span_name_span {
|
||||
Some((mac_name, new_span)) => {
|
||||
if mac_name.as_str() == name {
|
||||
Some(new_span)
|
||||
}
|
||||
else {
|
||||
span = new_span;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
11
tests/compile-fail/print.rs
Executable file
11
tests/compile-fail/print.rs
Executable file
|
@ -0,0 +1,11 @@
|
|||
#![feature(plugin)]
|
||||
#![plugin(clippy)]
|
||||
|
||||
#[deny(print_stdout)]
|
||||
|
||||
fn main() {
|
||||
println!("Hello"); //~ERROR use of `println!`
|
||||
print!("Hello"); //~ERROR use of `print!`
|
||||
|
||||
vec![1, 2];
|
||||
}
|
Loading…
Reference in a new issue