From 8552c61c5a8e91b30bd35e4711d39d470c83cbb1 Mon Sep 17 00:00:00 2001 From: Kevin Leimkuhler Date: Mon, 1 Oct 2018 22:32:26 -0700 Subject: [PATCH] Add initial impl of check_pat() for UnusedParens This uses a copied version of `check_unused_parens_expr` that is specific to `ast::Pat`. `check_unused_parens_` could possibly be made more generic to work with any `ast::*` that has `node` and `span` fields. This also only checks for the case of parens around the wildcard pattern. It covers the case highlighted in the issue, but could check for a lot more. --- src/librustc_lint/unused.rs | 72 ++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index ae178888b6a..b559b7b8cd8 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -264,7 +264,7 @@ declare_lint! { pub struct UnusedParens; impl UnusedParens { - fn check_unused_parens_core(&self, + fn check_unused_parens_expr(&self, cx: &EarlyContext, value: &ast::Expr, msg: &str, @@ -313,6 +313,56 @@ impl UnusedParens { } } } + + fn check_unused_parens_pat(&self, + cx: &EarlyContext, + value: &ast::Pat, + msg: &str, + struct_lit_needs_parens: bool) { + if let ast::PatKind::Paren(_) = value.node { + // Does there need to be a check similar to `parser::contains_exterior_struct_lit` + // here? + if !struct_lit_needs_parens { + let span_msg = format!("unnecessary parentheses around {}", msg); + let mut err = cx.struct_span_lint(UNUSED_PARENS, + value.span, + &span_msg); + // Remove exactly one pair of parentheses (rather than naïvely + // stripping all paren characters) + let mut ate_left_paren = false; + let mut ate_right_paren = false; + let parens_removed = pprust::pat_to_string(value) + .trim_matches(|c| { + match c { + '(' => { + if ate_left_paren { + false + } else { + ate_left_paren = true; + true + } + }, + ')' => { + if ate_right_paren { + false + } else { + ate_right_paren = true; + true + } + }, + _ => false, + } + }).to_owned(); + err.span_suggestion_short_with_applicability( + value.span, + "remove these parentheses", + parens_removed, + Applicability::MachineApplicable + ); + err.emit(); + } + } + } } impl LintPass for UnusedParens { @@ -354,18 +404,32 @@ impl EarlyLintPass for UnusedParens { } let msg = format!("{} argument", call_kind); for arg in args_to_check { - self.check_unused_parens_core(cx, arg, &msg, false); + self.check_unused_parens_expr(cx, arg, &msg, false); } return; } }; - self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens); + self.check_unused_parens_expr(cx, &value, msg, struct_lit_needs_parens); + } + + fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) { + use ast::PatKind::*; + let (value, msg) = match p.node { + Paren(ref pat) => { + match pat.node { + Wild => (p, "wildcard pattern"), + _ => return, + } + } + _ => return, + }; + self.check_unused_parens_pat(cx, &value, msg, false); } fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { if let ast::StmtKind::Local(ref local) = s.node { if let Some(ref value) = local.init { - self.check_unused_parens_core(cx, &value, "assigned value", false); + self.check_unused_parens_expr(cx, &value, "assigned value", false); } } }