mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Add a lint to warn about use of print{,ln}!
This commit is contained in:
parent
3edba6db9e
commit
da93643357
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)
|
[Jump to usage instructions](#usage)
|
||||||
|
|
||||||
##Lints
|
##Lints
|
||||||
There are 100 lints included in this crate:
|
There are 101 lints included in this crate:
|
||||||
|
|
||||||
name | default | meaning
|
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
|
[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!`
|
[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
|
[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
|
[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_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
|
[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
|
// this only exists to allow the "dogfood" integration test to work
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[allow(print_stdout)]
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("What are you doing? Don't run clippy as an executable");
|
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 array_indexing;
|
||||||
pub mod panic;
|
pub mod panic;
|
||||||
pub mod derive;
|
pub mod derive;
|
||||||
|
pub mod print;
|
||||||
|
|
||||||
mod reexport {
|
mod reexport {
|
||||||
pub use syntax::ast::{Name, NodeId};
|
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 strings::StringLitAsBytes);
|
||||||
reg.register_late_lint_pass(box derive::Derive);
|
reg.register_late_lint_pass(box derive::Derive);
|
||||||
reg.register_late_lint_pass(box types::CharLitAsU8);
|
reg.register_late_lint_pass(box types::CharLitAsU8);
|
||||||
|
reg.register_late_lint_pass(box print::PrintLint);
|
||||||
|
|
||||||
|
|
||||||
reg.register_lint_group("clippy_pedantic", vec![
|
reg.register_lint_group("clippy_pedantic", vec![
|
||||||
|
@ -149,6 +152,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||||
methods::WRONG_PUB_SELF_CONVENTION,
|
methods::WRONG_PUB_SELF_CONVENTION,
|
||||||
mut_mut::MUT_MUT,
|
mut_mut::MUT_MUT,
|
||||||
mutex_atomic::MUTEX_INTEGER,
|
mutex_atomic::MUTEX_INTEGER,
|
||||||
|
print::PRINT_STDOUT,
|
||||||
shadow::SHADOW_REUSE,
|
shadow::SHADOW_REUSE,
|
||||||
shadow::SHADOW_SAME,
|
shadow::SHADOW_SAME,
|
||||||
shadow::SHADOW_UNRELATED,
|
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_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"];
|
||||||
pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"];
|
pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"];
|
||||||
pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"];
|
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 LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
|
||||||
pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"];
|
pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"];
|
||||||
pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"];
|
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,
|
_ => 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