Handle common assert! misuses
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
use errors::DiagnosticBuilder;
|
use errors::{Applicability, DiagnosticBuilder};
|
||||||
|
|
||||||
use syntax::ast::{self, *};
|
use syntax::ast::{self, *};
|
||||||
use syntax::source_map::Spanned;
|
use syntax::source_map::Spanned;
|
||||||
use syntax::ext::base::*;
|
use syntax::ext::base::*;
|
||||||
use syntax::ext::build::AstBuilder;
|
use syntax::ext::build::AstBuilder;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
use syntax::parse::parser::Parser;
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
@@ -74,18 +75,54 @@ fn parse_assert<'a>(
|
|||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let assert = Assert {
|
let cond_expr = parser.parse_expr()?;
|
||||||
cond_expr: parser.parse_expr()?,
|
|
||||||
custom_message: if parser.eat(&token::Comma) {
|
// Some crates use the `assert!` macro in the following form (note extra semicolon):
|
||||||
let ts = parser.parse_tokens();
|
//
|
||||||
if !ts.is_empty() {
|
// assert!(
|
||||||
Some(ts)
|
// my_function();
|
||||||
} else {
|
// );
|
||||||
None
|
//
|
||||||
}
|
// Warn about semicolon and suggest removing it. Eventually, this should be turned into an
|
||||||
} else {
|
// error.
|
||||||
None
|
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 {
|
if parser.token != token::Eof {
|
||||||
@@ -93,5 +130,14 @@ fn parse_assert<'a>(
|
|||||||
unreachable!();
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,4 +11,14 @@ fn main() {
|
|||||||
|
|
||||||
assert!(true, "whatever" blah);
|
assert!(true, "whatever" blah);
|
||||||
//~^ ERROR no rules expected
|
//~^ 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,5 +18,43 @@ LL | assert!(true, "whatever" blah);
|
|||||||
| |
|
| |
|
||||||
| help: missing comma here
|
| 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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user