Skip to content

Commit

Permalink
Suggest comma when writing println!("{}" a);
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Aug 7, 2018
1 parent 73c7873 commit 4862eee
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 1 deletion.
27 changes: 26 additions & 1 deletion src/libsyntax/ext/tt/macro_rules.rs
Expand Up @@ -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)
}
Expand Down
25 changes: 25 additions & 0 deletions src/libsyntax/tokenstream.rs
Expand Up @@ -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 ot 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,
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/macros/missing-comma.rs
@@ -0,0 +1,14 @@
// 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.

fn main() {
println!("{}" a);
//~^ ERROR no rules expected the token `a`
}
10 changes: 10 additions & 0 deletions src/test/ui/macros/missing-comma.stderr
@@ -0,0 +1,10 @@
error: no rules expected the token `a`
--> $DIR/missing-comma.rs:12:19
|
LL | println!("{}" a);
| -^
| |
| help: missing comma here

error: aborting due to previous error

0 comments on commit 4862eee

Please sign in to comment.