]> git.lizzy.rs Git - rust.git/commitdiff
Handle common assert! misuses
authorAlexey Shmalko <rasen.dubi@gmail.com>
Wed, 24 Apr 2019 22:44:28 +0000 (01:44 +0300)
committerAlexey Shmalko <rasen.dubi@gmail.com>
Wed, 24 Apr 2019 23:06:38 +0000 (02:06 +0300)
src/libsyntax_ext/assert.rs
src/test/ui/macros/assert-trailing-junk.rs
src/test/ui/macros/assert-trailing-junk.stderr

index f1974ed30f6eb23b5eb40395a8dcf1ff964591fd..cd69733571d5af6a12f4d9b6c8f9ad161e337d44 100644 (file)
@@ -1,10 +1,11 @@
-use errors::DiagnosticBuilder;
+use errors::{Applicability, DiagnosticBuilder};
 
 use syntax::ast::{self, *};
 use syntax::source_map::Spanned;
 use syntax::ext::base::*;
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token;
+use syntax::parse::parser::Parser;
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::symbol::Symbol;
@@ -74,18 +75,54 @@ fn parse_assert<'a>(
         return Err(err);
     }
 
-    let assert = Assert {
-        cond_expr: parser.parse_expr()?,
-        custom_message: if parser.eat(&token::Comma) {
-            let ts = parser.parse_tokens();
-            if !ts.is_empty() {
-                Some(ts)
-            } else {
-                None
-            }
-        } else {
-            None
-        },
+    let cond_expr = parser.parse_expr()?;
+
+    // Some crates use the `assert!` macro in the following form (note extra semicolon):
+    //
+    // assert!(
+    //     my_function();
+    // );
+    //
+    // Warn about semicolon and suggest removing it. Eventually, this should be turned into an
+    // error.
+    if parser.token == token::Semi {
+        let mut err = cx.struct_span_warn(sp, "macro requires an expression as an argument");
+        err.span_suggestion(
+            parser.span,
+            "try removing semicolon",
+            String::new(),
+            Applicability::MaybeIncorrect
+        );
+        err.note("this is going to be an error in the future");
+        err.emit();
+
+        parser.bump();
+    }
+
+    // Some crates use the `assert!` macro in the following form (note missing comma before
+    // message):
+    //
+    // assert!(true "error message");
+    //
+    // Parse this as an actual message, and suggest inserting a comma. Eventually, this should be
+    // turned into an error.
+    let custom_message = if let token::Literal(token::Lit::Str_(_), _) = parser.token {
+        let mut err = cx.struct_span_warn(parser.span, "unexpected string literal");
+        let comma_span = cx.source_map().next_point(parser.prev_span);
+        err.span_suggestion_short(
+            comma_span,
+            "try adding a comma",
+            ", ".to_string(),
+            Applicability::MaybeIncorrect
+        );
+        err.note("this is going to be an error in the future");
+        err.emit();
+
+        parse_custom_message(&mut parser)
+    } else if parser.eat(&token::Comma) {
+        parse_custom_message(&mut parser)
+    } else {
+        None
     };
 
     if parser.token != token::Eof {
@@ -93,5 +130,14 @@ fn parse_assert<'a>(
         unreachable!();
     }
 
-    Ok(assert)
+    Ok(Assert { cond_expr, custom_message })
+}
+
+fn parse_custom_message<'a>(parser: &mut Parser<'a>) -> Option<TokenStream> {
+    let ts = parser.parse_tokens();
+    if !ts.is_empty() {
+        Some(ts)
+    } else {
+        None
+    }
 }
index 66de6de3ee8f59d52a00c910c581970eb085aa84..676ae05bf0fa67b4c1516408ca6a1636651338ec 100644 (file)
@@ -11,4 +11,14 @@ fn main() {
 
     assert!(true, "whatever" blah);
     //~^ ERROR no rules expected
+
+    assert!(true "whatever" blah);
+    //~^ WARN unexpected string literal
+    //~^^ ERROR no rules expected
+
+    assert!(true;);
+    //~^ WARN macro requires an expression
+
+    assert!(false || true "error message");
+    //~^ WARN unexpected string literal
 }
index 3f7d8dcaf790ca5ab89e3828f1dda248f0484423..6fc0a278461097b3c68b1cafe4abe9b59d3348cd 100644 (file)
@@ -18,5 +18,43 @@ LL |     assert!(true, "whatever" blah);
    |                             |
    |                             help: missing comma here
 
-error: aborting due to 3 previous errors
+warning: unexpected string literal
+  --> $DIR/assert-trailing-junk.rs:15:18
+   |
+LL |     assert!(true "whatever" blah);
+   |                 -^^^^^^^^^^
+   |                 |
+   |                 help: try adding a comma
+   |
+   = note: this is going to be an error in the future
+
+error: no rules expected the token `blah`
+  --> $DIR/assert-trailing-junk.rs:15:29
+   |
+LL |     assert!(true "whatever" blah);
+   |                            -^^^^ no rules expected this token in macro call
+   |                            |
+   |                            help: missing comma here
+
+warning: macro requires an expression as an argument
+  --> $DIR/assert-trailing-junk.rs:19:5
+   |
+LL |     assert!(true;);
+   |     ^^^^^^^^^^^^-^^
+   |                 |
+   |                 help: try removing semicolon
+   |
+   = note: this is going to be an error in the future
+
+warning: unexpected string literal
+  --> $DIR/assert-trailing-junk.rs:22:27
+   |
+LL |     assert!(false || true "error message");
+   |                          -^^^^^^^^^^^^^^^
+   |                          |
+   |                          help: try adding a comma
+   |
+   = note: this is going to be an error in the future
+
+error: aborting due to 4 previous errors