Add suggestion for explicit_write lint
This commit is contained in:
parent
e2608fc272
commit
c4c9d9fc62
@ -10,8 +10,8 @@
|
|||||||
use crate::rustc::hir::*;
|
use crate::rustc::hir::*;
|
||||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
use crate::rustc::{declare_tool_lint, lint_array};
|
use crate::rustc::{declare_tool_lint, lint_array};
|
||||||
use crate::utils::opt_def_id;
|
use crate::syntax::ast::LitKind;
|
||||||
use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint};
|
use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
|
|
||||||
/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be
|
/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be
|
||||||
@ -51,6 +51,12 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
|||||||
if unwrap_args.len() > 0;
|
if unwrap_args.len() > 0;
|
||||||
if let ExprKind::MethodCall(ref write_fun, _, ref write_args) =
|
if let ExprKind::MethodCall(ref write_fun, _, ref write_args) =
|
||||||
unwrap_args[0].node;
|
unwrap_args[0].node;
|
||||||
|
// Obtain the string that should be printed
|
||||||
|
if let ExprKind::Call(_, ref output_args) = write_args[1].node;
|
||||||
|
if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node;
|
||||||
|
if let ExprKind::Array(ref string_exprs) = output_string_expr.node;
|
||||||
|
if let ExprKind::Lit(ref lit) = string_exprs[0].node;
|
||||||
|
if let LitKind::Str(ref write_output, _) = lit.node;
|
||||||
if write_fun.ident.name == "write_fmt";
|
if write_fun.ident.name == "write_fmt";
|
||||||
// match calls to std::io::stdout() / std::io::stderr ()
|
// match calls to std::io::stdout() / std::io::stderr ()
|
||||||
if write_args.len() > 0;
|
if write_args.len() > 0;
|
||||||
@ -81,29 +87,35 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
|||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We need to remove the last trailing newline from the string because the
|
||||||
|
// underlying `fmt::write` function doesn't know wether `println!` or `print!` was
|
||||||
|
// used.
|
||||||
|
let mut write_output: String = write_output.to_string();
|
||||||
|
if write_output.ends_with('\n') {
|
||||||
|
write_output.truncate(write_output.len() - 1)
|
||||||
|
}
|
||||||
if let Some(macro_name) = calling_macro {
|
if let Some(macro_name) = calling_macro {
|
||||||
span_lint(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
EXPLICIT_WRITE,
|
EXPLICIT_WRITE,
|
||||||
expr.span,
|
expr.span,
|
||||||
&format!(
|
&format!(
|
||||||
"use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead",
|
"use of `{}!({}(), ...).unwrap()`",
|
||||||
macro_name,
|
macro_name,
|
||||||
dest_name,
|
dest_name
|
||||||
prefix,
|
),
|
||||||
macro_name.replace("write", "print")
|
"try this",
|
||||||
)
|
format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default())
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
span_lint(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
EXPLICIT_WRITE,
|
EXPLICIT_WRITE,
|
||||||
expr.span,
|
expr.span,
|
||||||
&format!(
|
&format!("use of `{}().write_fmt(...).unwrap()`", dest_name),
|
||||||
"use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead",
|
"try this",
|
||||||
dest_name,
|
format!("{}print!(\"{}\")", prefix, write_output.escape_default())
|
||||||
prefix,
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
#![feature(range_contains)]
|
#![feature(range_contains)]
|
||||||
|
#![feature(str_escape)]
|
||||||
#![allow(clippy::missing_docs_in_private_items)]
|
#![allow(clippy::missing_docs_in_private_items)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
|
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
|
||||||
|
@ -27,6 +27,10 @@ fn main() {
|
|||||||
writeln!(std::io::stderr(), "test").unwrap();
|
writeln!(std::io::stderr(), "test").unwrap();
|
||||||
std::io::stdout().write_fmt(format_args!("test")).unwrap();
|
std::io::stdout().write_fmt(format_args!("test")).unwrap();
|
||||||
std::io::stderr().write_fmt(format_args!("test")).unwrap();
|
std::io::stderr().write_fmt(format_args!("test")).unwrap();
|
||||||
|
|
||||||
|
// including newlines
|
||||||
|
writeln!(std::io::stdout(), "test\ntest").unwrap();
|
||||||
|
writeln!(std::io::stderr(), "test\ntest").unwrap();
|
||||||
}
|
}
|
||||||
// these should not warn, different destination
|
// these should not warn, different destination
|
||||||
{
|
{
|
||||||
|
@ -1,40 +1,52 @@
|
|||||||
error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead
|
error: use of `write!(stdout(), ...).unwrap()`
|
||||||
--> $DIR/explicit_write.rs:24:9
|
--> $DIR/explicit_write.rs:28:9
|
||||||
|
|
|
|
||||||
24 | write!(std::io::stdout(), "test").unwrap();
|
28 | write!(std::io::stdout(), "test").unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")`
|
||||||
|
|
|
|
||||||
= note: `-D clippy::explicit-write` implied by `-D warnings`
|
= note: `-D clippy::explicit-write` implied by `-D warnings`
|
||||||
|
|
||||||
error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead
|
error: use of `write!(stderr(), ...).unwrap()`
|
||||||
--> $DIR/explicit_write.rs:25:9
|
|
||||||
|
|
|
||||||
25 | write!(std::io::stderr(), "test").unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead
|
|
||||||
--> $DIR/explicit_write.rs:26:9
|
|
||||||
|
|
|
||||||
26 | writeln!(std::io::stdout(), "test").unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead
|
|
||||||
--> $DIR/explicit_write.rs:27:9
|
|
||||||
|
|
|
||||||
27 | writeln!(std::io::stderr(), "test").unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead
|
|
||||||
--> $DIR/explicit_write.rs:28:9
|
|
||||||
|
|
|
||||||
28 | std::io::stdout().write_fmt(format_args!("test")).unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead
|
|
||||||
--> $DIR/explicit_write.rs:29:9
|
--> $DIR/explicit_write.rs:29:9
|
||||||
|
|
|
|
||||||
29 | std::io::stderr().write_fmt(format_args!("test")).unwrap();
|
29 | write!(std::io::stderr(), "test").unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")`
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: use of `writeln!(stdout(), ...).unwrap()`
|
||||||
|
--> $DIR/explicit_write.rs:30:9
|
||||||
|
|
|
||||||
|
30 | writeln!(std::io::stdout(), "test").unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")`
|
||||||
|
|
||||||
|
error: use of `writeln!(stderr(), ...).unwrap()`
|
||||||
|
--> $DIR/explicit_write.rs:31:9
|
||||||
|
|
|
||||||
|
31 | writeln!(std::io::stderr(), "test").unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")`
|
||||||
|
|
||||||
|
error: use of `stdout().write_fmt(...).unwrap()`
|
||||||
|
--> $DIR/explicit_write.rs:32:9
|
||||||
|
|
|
||||||
|
32 | std::io::stdout().write_fmt(format_args!("test")).unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")`
|
||||||
|
|
||||||
|
error: use of `stderr().write_fmt(...).unwrap()`
|
||||||
|
--> $DIR/explicit_write.rs:33:9
|
||||||
|
|
|
||||||
|
33 | std::io::stderr().write_fmt(format_args!("test")).unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")`
|
||||||
|
|
||||||
|
error: use of `writeln!(stdout(), ...).unwrap()`
|
||||||
|
--> $DIR/explicit_write.rs:36:9
|
||||||
|
|
|
||||||
|
36 | writeln!(std::io::stdout(), "test/ntest").unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")`
|
||||||
|
|
||||||
|
error: use of `writeln!(stderr(), ...).unwrap()`
|
||||||
|
--> $DIR/explicit_write.rs:37:9
|
||||||
|
|
|
||||||
|
37 | writeln!(std::io::stderr(), "test/ntest").unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")`
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user