diff options
| author | Nathan <nathan.whitaker01@gmail.com> | 2019-07-30 13:48:39 -0400 |
|---|---|---|
| committer | nathanwhit <nathan.whitaker01@gmail.com> | 2019-08-12 10:14:07 -0400 |
| commit | 2f6cb5f75e080d7886129bd9fa2dbc9ee52b20ac (patch) | |
| tree | 26ef95268cacd059711ac0adb805141a8ba23af3 /src | |
| parent | 71415ef9bd697a49db34742172aacb792ce8d116 (diff) | |
| download | rust-2f6cb5f75e080d7886129bd9fa2dbc9ee52b20ac.tar.gz rust-2f6cb5f75e080d7886129bd9fa2dbc9ee52b20ac.zip | |
Add lint for excess trailing semicolons
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_lint/lib.rs | 3 | ||||
| -rw-r--r-- | src/librustc_lint/redundant_semicolon.rs | 52 |
2 files changed, 55 insertions, 0 deletions
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 3a540fdf4b9..fc416be8eeb 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -24,6 +24,7 @@ extern crate rustc; mod error_codes; mod nonstandard_style; +mod redundant_semicolon; pub mod builtin; mod types; mod unused; @@ -55,6 +56,7 @@ use session::Session; use lint::LintId; use lint::FutureIncompatibleInfo; +use redundant_semicolon::*; use nonstandard_style::*; use builtin::*; use types::*; @@ -98,6 +100,7 @@ macro_rules! early_lint_passes { WhileTrue: WhileTrue, NonAsciiIdents: NonAsciiIdents, IncompleteFeatures: IncompleteFeatures, + RedundantSemicolon: RedundantSemicolon, ]); ) } diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs new file mode 100644 index 00000000000..7c9df3578b5 --- /dev/null +++ b/src/librustc_lint/redundant_semicolon.rs @@ -0,0 +1,52 @@ +use crate::lint::{EarlyLintPass, LintPass, EarlyContext, LintArray, LintContext}; +use syntax::ast::{Stmt, StmtKind, ExprKind}; +use syntax::errors::Applicability; + +declare_lint! { + pub REDUNDANT_SEMICOLON, + Warn, + "detects unnecessary trailing semicolons" +} + +declare_lint_pass!(RedundantSemicolon => [REDUNDANT_SEMICOLON]); + +impl EarlyLintPass for RedundantSemicolon { + fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) { + if let StmtKind::Semi(expr) = &stmt.node { + if let ExprKind::Tup(ref v) = &expr.node { + if v.is_empty() { + // Strings of excess semicolons are encoded as empty tuple expressions + // during the parsing stage, so we check for empty tuple expressions + // which span only semicolons + if let Ok(source_str) = cx.sess().source_map().span_to_snippet(stmt.span) { + if source_str.chars().all(|c| c == ';') { + let multiple = (stmt.span.hi() - stmt.span.lo()).0 > 1; + let msg = if multiple { + "unnecessary trailing semicolons" + } else { + "unnecessary trailing semicolon" + }; + let mut err = cx.struct_span_lint( + REDUNDANT_SEMICOLON, + stmt.span, + &msg + ); + let suggest_msg = if multiple { + "remove these semicolons" + } else { + "remove this semicolon" + }; + err.span_suggestion( + stmt.span, + &suggest_msg, + String::new(), + Applicability::MaybeIncorrect + ); + err.emit(); + } + } + } + } + } + } +} |
