about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNathan <nathan.whitaker01@gmail.com>2019-07-30 13:48:39 -0400
committernathanwhit <nathan.whitaker01@gmail.com>2019-08-12 10:14:07 -0400
commit2f6cb5f75e080d7886129bd9fa2dbc9ee52b20ac (patch)
tree26ef95268cacd059711ac0adb805141a8ba23af3 /src
parent71415ef9bd697a49db34742172aacb792ce8d116 (diff)
downloadrust-2f6cb5f75e080d7886129bd9fa2dbc9ee52b20ac.tar.gz
rust-2f6cb5f75e080d7886129bd9fa2dbc9ee52b20ac.zip
Add lint for excess trailing semicolons
Diffstat (limited to 'src')
-rw-r--r--src/librustc_lint/lib.rs3
-rw-r--r--src/librustc_lint/redundant_semicolon.rs52
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();
+                        }
+                    }
+                }
+            }
+        }
+    }
+}