add structured suggestions
This commit is contained in:
parent
6a6b4a3ba8
commit
82b2eb13f8
4 changed files with 126 additions and 32 deletions
|
|
@ -1,5 +1,7 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{HasSession, snippet_with_applicability};
|
||||
use rustc_ast::ast::{Expr, ExprKind, MethodCall};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
|
||||
|
|
@ -24,7 +26,7 @@ declare_clippy_lint! {
|
|||
/// Use instead:
|
||||
/// ```no_run
|
||||
/// fn simple_no_parens() -> i32 {
|
||||
/// 0
|
||||
/// (0)
|
||||
/// }
|
||||
///
|
||||
/// # fn foo(bar: usize) {}
|
||||
|
|
@ -40,23 +42,51 @@ declare_lint_pass!(DoubleParens => [DOUBLE_PARENS]);
|
|||
|
||||
impl EarlyLintPass for DoubleParens {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
let span = match &expr.kind {
|
||||
ExprKind::Paren(in_paren) if matches!(in_paren.kind, ExprKind::Paren(_) | ExprKind::Tup(_)) => expr.span,
|
||||
ExprKind::Call(_, args) | ExprKind::MethodCall(box MethodCall { args, .. })
|
||||
if let [args] = &**args
|
||||
&& let ExprKind::Paren(_) = args.kind =>
|
||||
{
|
||||
args.span
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
match &expr.kind {
|
||||
// ((..))
|
||||
// ^^^^^^ expr
|
||||
// ^^^^ inner
|
||||
ExprKind::Paren(inner) if matches!(inner.kind, ExprKind::Paren(_) | ExprKind::Tup(_)) => {
|
||||
// suggest removing the outer parens
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let sugg = snippet_with_applicability(cx.sess(), inner.span, "_", &mut applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DOUBLE_PARENS,
|
||||
expr.span,
|
||||
"unnecessary parentheses",
|
||||
"remove them",
|
||||
sugg.to_string(),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
if !expr.span.from_expansion() {
|
||||
span_lint(
|
||||
cx,
|
||||
DOUBLE_PARENS,
|
||||
span,
|
||||
"consider removing unnecessary double parentheses",
|
||||
);
|
||||
|
||||
// func((n))
|
||||
// ^^^^^^^^^ expr
|
||||
// ^^^ arg
|
||||
// ^ inner
|
||||
ExprKind::Call(_, args) | ExprKind::MethodCall(box MethodCall { args, .. })
|
||||
if let [arg] = &**args
|
||||
&& let ExprKind::Paren(inner) = &arg.kind =>
|
||||
{
|
||||
// suggest removing the inner parens
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let sugg = snippet_with_applicability(cx.sess(), inner.span, "_", &mut applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DOUBLE_PARENS,
|
||||
arg.span,
|
||||
"unnecessary parentheses",
|
||||
"remove them",
|
||||
sugg.to_string(),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
63
tests/ui/double_parens.fixed
Normal file
63
tests/ui/double_parens.fixed
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#![warn(clippy::double_parens)]
|
||||
#![expect(clippy::eq_op)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![rustfmt::skip]
|
||||
|
||||
fn dummy_fn<T>(_: T) {}
|
||||
|
||||
struct DummyStruct;
|
||||
|
||||
impl DummyStruct {
|
||||
fn dummy_method<T>(self, _: T) {}
|
||||
}
|
||||
|
||||
fn simple_double_parens() -> i32 {
|
||||
(0)
|
||||
//~^ double_parens
|
||||
}
|
||||
|
||||
fn fn_double_parens() {
|
||||
dummy_fn(0);
|
||||
//~^ double_parens
|
||||
}
|
||||
|
||||
fn method_double_parens(x: DummyStruct) {
|
||||
x.dummy_method(0);
|
||||
//~^ double_parens
|
||||
}
|
||||
|
||||
fn tuple_double_parens() -> (i32, i32) {
|
||||
(1, 2)
|
||||
//~^ double_parens
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_unit)]
|
||||
fn unit_double_parens() {
|
||||
()
|
||||
//~^ double_parens
|
||||
}
|
||||
|
||||
fn fn_tuple_ok() {
|
||||
dummy_fn((1, 2));
|
||||
}
|
||||
|
||||
fn method_tuple_ok(x: DummyStruct) {
|
||||
x.dummy_method((1, 2));
|
||||
}
|
||||
|
||||
fn fn_unit_ok() {
|
||||
dummy_fn(());
|
||||
}
|
||||
|
||||
fn method_unit_ok(x: DummyStruct) {
|
||||
x.dummy_method(());
|
||||
}
|
||||
|
||||
// Issue #3206
|
||||
fn inside_macro() {
|
||||
assert_eq!((1, 2), (1, 2), "Error");
|
||||
assert_eq!((1, 2), (1, 2), "Error");
|
||||
//~^ double_parens
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -31,6 +31,7 @@ fn tuple_double_parens() -> (i32, i32) {
|
|||
//~^ double_parens
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_unit)]
|
||||
fn unit_double_parens() {
|
||||
(())
|
||||
//~^ double_parens
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
error: consider removing unnecessary double parentheses
|
||||
error: unnecessary parentheses
|
||||
--> tests/ui/double_parens.rs:15:5
|
||||
|
|
||||
LL | ((0))
|
||||
| ^^^^^
|
||||
| ^^^^^ help: remove them: `(0)`
|
||||
|
|
||||
= note: `-D clippy::double-parens` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::double_parens)]`
|
||||
|
||||
error: consider removing unnecessary double parentheses
|
||||
error: unnecessary parentheses
|
||||
--> tests/ui/double_parens.rs:20:14
|
||||
|
|
||||
LL | dummy_fn((0));
|
||||
| ^^^
|
||||
| ^^^ help: remove them: `0`
|
||||
|
||||
error: consider removing unnecessary double parentheses
|
||||
error: unnecessary parentheses
|
||||
--> tests/ui/double_parens.rs:25:20
|
||||
|
|
||||
LL | x.dummy_method((0));
|
||||
| ^^^
|
||||
| ^^^ help: remove them: `0`
|
||||
|
||||
error: consider removing unnecessary double parentheses
|
||||
error: unnecessary parentheses
|
||||
--> tests/ui/double_parens.rs:30:5
|
||||
|
|
||||
LL | ((1, 2))
|
||||
| ^^^^^^^^
|
||||
| ^^^^^^^^ help: remove them: `(1, 2)`
|
||||
|
||||
error: consider removing unnecessary double parentheses
|
||||
--> tests/ui/double_parens.rs:35:5
|
||||
error: unnecessary parentheses
|
||||
--> tests/ui/double_parens.rs:36:5
|
||||
|
|
||||
LL | (())
|
||||
| ^^^^
|
||||
| ^^^^ help: remove them: `()`
|
||||
|
||||
error: consider removing unnecessary double parentheses
|
||||
--> tests/ui/double_parens.rs:58:16
|
||||
error: unnecessary parentheses
|
||||
--> tests/ui/double_parens.rs:59:16
|
||||
|
|
||||
LL | assert_eq!(((1, 2)), (1, 2), "Error");
|
||||
| ^^^^^^^^
|
||||
| ^^^^^^^^ help: remove them: `(1, 2)`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue