Auto merge of #52397 - estebank:println-comma, r=oli-obk
Suggest comma when writing `println!("{}" a);` Fix #49370.
This commit is contained in:
commit
3f4f18f098
6 changed files with 92 additions and 10 deletions
|
@ -174,7 +174,32 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
|
|||
}
|
||||
|
||||
let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers"));
|
||||
cx.span_err(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
|
||||
let mut err = cx.struct_span_err(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
|
||||
|
||||
// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
|
||||
if let Some((arg, comma_span)) = arg.add_comma() {
|
||||
for lhs in lhses { // try each arm's matchers
|
||||
let lhs_tt = match *lhs {
|
||||
quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
|
||||
_ => cx.span_bug(sp, "malformed macro lhs")
|
||||
};
|
||||
match TokenTree::parse(cx, lhs_tt, arg.clone()) {
|
||||
Success(_) => {
|
||||
if comma_span == DUMMY_SP {
|
||||
err.note("you might be missing a comma");
|
||||
} else {
|
||||
err.span_suggestion_short(
|
||||
comma_span,
|
||||
"missing comma here",
|
||||
",".to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
cx.trace_macros_diag();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
|
|
@ -182,6 +182,31 @@ pub struct TokenStream {
|
|||
kind: TokenStreamKind,
|
||||
}
|
||||
|
||||
impl TokenStream {
|
||||
/// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
|
||||
/// separating the two arguments with a comma for diagnostic suggestions.
|
||||
pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
|
||||
// Used to suggest if a user writes `println!("{}" a);`
|
||||
if let TokenStreamKind::Stream(ref slice) = self.kind {
|
||||
if slice.len() == 2 {
|
||||
let comma_span = match slice[0] {
|
||||
TokenStream { kind: TokenStreamKind::Tree(TokenTree::Token(sp, _)) } |
|
||||
TokenStream { kind: TokenStreamKind::Tree(TokenTree::Delimited(sp, _)) } => {
|
||||
sp.shrink_to_hi()
|
||||
}
|
||||
_ => DUMMY_SP,
|
||||
};
|
||||
let comma = TokenStream {
|
||||
kind: TokenStreamKind::Tree(TokenTree::Token(comma_span, token::Comma)),
|
||||
};
|
||||
let slice = RcSlice::new(vec![slice[0].clone(), comma, slice[1].clone()]);
|
||||
return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, comma_span));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum TokenStreamKind {
|
||||
Empty,
|
||||
|
|
|
@ -147,7 +147,7 @@ fn parse_args(ecx: &mut ExtCtxt,
|
|||
let mut named = false;
|
||||
while p.token != token::Eof {
|
||||
if !p.eat(&token::Comma) {
|
||||
ecx.span_err(sp, "expected token: `,`");
|
||||
ecx.span_err(p.span, "expected token: `,`");
|
||||
return None;
|
||||
}
|
||||
if p.token == token::Eof {
|
||||
|
|
|
@ -7,20 +7,16 @@ LL | format!(); //~ ERROR requires at least a format string argument
|
|||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
error: expected token: `,`
|
||||
--> $DIR/bad-format-args.rs:13:5
|
||||
--> $DIR/bad-format-args.rs:13:16
|
||||
|
|
||||
LL | format!("" 1); //~ ERROR expected token: `,`
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
| ^
|
||||
|
||||
error: expected token: `,`
|
||||
--> $DIR/bad-format-args.rs:14:5
|
||||
--> $DIR/bad-format-args.rs:14:19
|
||||
|
|
||||
LL | format!("", 1 1); //~ ERROR expected token: `,`
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
20
src/test/ui/macros/missing-comma.rs
Normal file
20
src/test/ui/macros/missing-comma.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
macro_rules! foo {
|
||||
($a:ident, $b:ident) => ()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}" a);
|
||||
//~^ ERROR expected token: `,`
|
||||
foo!(a b);
|
||||
//~^ ERROR no rules expected the token `b`
|
||||
}
|
16
src/test/ui/macros/missing-comma.stderr
Normal file
16
src/test/ui/macros/missing-comma.stderr
Normal file
|
@ -0,0 +1,16 @@
|
|||
error: expected token: `,`
|
||||
--> $DIR/missing-comma.rs:16:19
|
||||
|
|
||||
LL | println!("{}" a);
|
||||
| ^
|
||||
|
||||
error: no rules expected the token `b`
|
||||
--> $DIR/missing-comma.rs:18:12
|
||||
|
|
||||
LL | foo!(a b);
|
||||
| -^
|
||||
| |
|
||||
| help: missing comma here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Add table
Reference in a new issue