mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 21:23:56 +00:00
Add PRINTLN_EMPTY_STRING lint.
This commit is contained in:
parent
4d9ed8beef
commit
22f3ca0e2c
4 changed files with 78 additions and 16 deletions
|
@ -530,6 +530,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||||
partialeq_ne_impl::PARTIALEQ_NE_IMPL,
|
partialeq_ne_impl::PARTIALEQ_NE_IMPL,
|
||||||
precedence::PRECEDENCE,
|
precedence::PRECEDENCE,
|
||||||
print::PRINT_WITH_NEWLINE,
|
print::PRINT_WITH_NEWLINE,
|
||||||
|
print::PRINTLN_EMPTY_STRING,
|
||||||
ptr::CMP_NULL,
|
ptr::CMP_NULL,
|
||||||
ptr::MUT_FROM_REF,
|
ptr::MUT_FROM_REF,
|
||||||
ptr::PTR_ARG,
|
ptr::PTR_ARG,
|
||||||
|
|
|
@ -1,11 +1,30 @@
|
||||||
|
use std::ops::Deref;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::map::Node::{NodeImplItem, NodeItem};
|
use rustc::hir::map::Node::{NodeImplItem, NodeItem};
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use syntax::ast::LitKind;
|
use syntax::ast::LitKind;
|
||||||
use syntax::symbol::InternedString;
|
use syntax::symbol::InternedString;
|
||||||
|
use syntax_pos::Span;
|
||||||
use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint};
|
use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint};
|
||||||
use utils::{paths, opt_def_id};
|
use utils::{paths, opt_def_id};
|
||||||
|
|
||||||
|
/// **What it does:** This lint warns when you using `println!("")` to
|
||||||
|
/// print a newline.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** You should use `println!()`, which is simpler.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None.
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
/// ```rust
|
||||||
|
/// println!("");
|
||||||
|
/// ```
|
||||||
|
declare_lint! {
|
||||||
|
pub PRINTLN_EMPTY_STRING,
|
||||||
|
Warn,
|
||||||
|
"using `print!()` with a format string that ends in a newline"
|
||||||
|
}
|
||||||
|
|
||||||
/// **What it does:** This lint warns when you using `print!()` with a format
|
/// **What it does:** This lint warns when you using `print!()` with a format
|
||||||
/// string that
|
/// string that
|
||||||
/// ends in a newline.
|
/// ends in a newline.
|
||||||
|
@ -64,7 +83,7 @@ pub struct Pass;
|
||||||
|
|
||||||
impl LintPass for Pass {
|
impl LintPass for Pass {
|
||||||
fn get_lints(&self) -> LintArray {
|
fn get_lints(&self) -> LintArray {
|
||||||
lint_array!(PRINT_WITH_NEWLINE, PRINT_STDOUT, USE_DEBUG)
|
lint_array!(PRINT_WITH_NEWLINE, PRINTLN_EMPTY_STRING, PRINT_STDOUT, USE_DEBUG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,10 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||||
|
|
||||||
span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name));
|
span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name));
|
||||||
|
|
||||||
// Check print! with format string ending in "\n".
|
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
name == "print",
|
|
||||||
|
|
||||||
// ensure we're calling Arguments::new_v1
|
// ensure we're calling Arguments::new_v1
|
||||||
args.len() == 1,
|
args.len() == 1,
|
||||||
let ExprCall(ref args_fun, ref args_args) = args[0].node,
|
let ExprCall(ref args_fun, ref args_args) = args[0].node,
|
||||||
|
@ -102,20 +118,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||||
let ExprAddrOf(_, ref match_expr) = args_args[1].node,
|
let ExprAddrOf(_, ref match_expr) = args_args[1].node,
|
||||||
let ExprMatch(ref args, _, _) = match_expr.node,
|
let ExprMatch(ref args, _, _) = match_expr.node,
|
||||||
let ExprTup(ref args) = args.node,
|
let ExprTup(ref args) = args.node,
|
||||||
|
|
||||||
// collect the format string parts and check the last one
|
|
||||||
let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]),
|
let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]),
|
||||||
let Some('\n') = fmtstr.chars().last(),
|
|
||||||
|
|
||||||
// "foo{}bar" is made into two strings + one argument,
|
|
||||||
// if the format string starts with `{}` (eg. "{}foo"),
|
|
||||||
// the string array is prepended an empty string "".
|
|
||||||
// We only want to check the last string after any `{}`:
|
|
||||||
args.len() < fmtlen,
|
|
||||||
], {
|
], {
|
||||||
span_lint(cx, PRINT_WITH_NEWLINE, span,
|
match name {
|
||||||
"using `print!()` with a format string that ends in a \
|
"print" => check_print(cx, span, args, fmtstr, fmtlen),
|
||||||
newline, consider using `println!()` instead");
|
"println" => check_println(cx, span, fmtstr, fmtlen),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,6 +144,46 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for print!("... \n", ...).
|
||||||
|
fn check_print<'a, 'tcx>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
span: Span,
|
||||||
|
args: &HirVec<Expr>,
|
||||||
|
fmtstr: InternedString,
|
||||||
|
fmtlen: usize,
|
||||||
|
) {
|
||||||
|
if_let_chain!{[
|
||||||
|
// check the final format string part
|
||||||
|
let Some('\n') = fmtstr.chars().last(),
|
||||||
|
|
||||||
|
// "foo{}bar" is made into two strings + one argument,
|
||||||
|
// if the format string starts with `{}` (eg. "{}foo"),
|
||||||
|
// the string array is prepended an empty string "".
|
||||||
|
// We only want to check the last string after any `{}`:
|
||||||
|
args.len() < fmtlen,
|
||||||
|
], {
|
||||||
|
span_lint(cx, PRINT_WITH_NEWLINE, span,
|
||||||
|
"using `print!()` with a format string that ends in a \
|
||||||
|
newline, consider using `println!()` instead");
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check for println!("")
|
||||||
|
fn check_println<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) {
|
||||||
|
if_let_chain!{[
|
||||||
|
// check that the string is empty
|
||||||
|
fmtlen == 1,
|
||||||
|
fmtstr.deref() == "\n",
|
||||||
|
|
||||||
|
// check the presence of that string
|
||||||
|
let Ok(snippet) = cx.sess().codemap().span_to_snippet(span),
|
||||||
|
snippet.contains("\"\""),
|
||||||
|
], {
|
||||||
|
span_lint(cx, PRINT_WITH_NEWLINE, span,
|
||||||
|
"using `println!(\"\")`, consider using `println!()` instead");
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
|
fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
|
||||||
let map = &cx.tcx.hir;
|
let map = &cx.tcx.hir;
|
||||||
|
|
||||||
|
|
4
tests/ui/println_empty_string.rs
Normal file
4
tests/ui/println_empty_string.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
fn main() {
|
||||||
|
println!();
|
||||||
|
println!("");
|
||||||
|
}
|
8
tests/ui/println_empty_string.stderr
Normal file
8
tests/ui/println_empty_string.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error: using `println!("")`, consider using `println!()` instead
|
||||||
|
--> $DIR/println_empty_string.rs:3:5
|
||||||
|
|
|
||||||
|
3 | println!("");
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D print-with-newline` implied by `-D warnings`
|
||||||
|
|
Loading…
Reference in a new issue