Collect occurrences of for mismatched braces diagnostic

Change-Id: I20ba0b62308370ee961141fa1aefc4b9c9f0cb3a
This commit is contained in:
wangxiangqing 2019-10-13 12:59:23 +08:00
parent 80b861bed1
commit e6ce3ef80a
4 changed files with 31 additions and 3 deletions

View file

@ -1,3 +1,4 @@
use rustc_data_structures::fx::FxHashMap;
use syntax_pos::Span;
use crate::print::pprust::token_to_string;
@ -16,6 +17,7 @@ impl<'a> StringReader<'a> {
unmatched_braces: Vec::new(),
matching_delim_spans: Vec::new(),
last_unclosed_found_span: None,
last_delim_empty_block_spans: FxHashMap::default()
};
let res = tt_reader.parse_all_token_trees();
(res, tt_reader.unmatched_braces)
@ -34,6 +36,7 @@ struct TokenTreesReader<'a> {
/// Used only for error recovery when arriving to EOF with mismatched braces.
matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
last_unclosed_found_span: Option<Span>,
last_delim_empty_block_spans: FxHashMap<token::DelimToken, Span>
}
impl<'a> TokenTreesReader<'a> {
@ -121,13 +124,20 @@ impl<'a> TokenTreesReader<'a> {
// Correct delimiter.
token::CloseDelim(d) if d == delim => {
let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
let close_brace_span = self.token.span;
if close_brace_span.lo() == open_brace_span.hi() {
let empty_block_span = open_brace_span.to(close_brace_span);
self.last_delim_empty_block_spans.insert(delim, empty_block_span);
}
if self.open_braces.len() == 0 {
// Clear up these spans to avoid suggesting them as we've found
// properly matched delimiters so far for an entire block.
self.matching_delim_spans.clear();
} else {
self.matching_delim_spans.push(
(open_brace, open_brace_span, self.token.span),
(open_brace, open_brace_span, close_brace_span),
);
}
// Parse the close delimiter.
@ -193,13 +203,17 @@ impl<'a> TokenTreesReader<'a> {
tts.into()
).into())
},
token::CloseDelim(_) => {
token::CloseDelim(delim) => {
// An unexpected closing delimiter (i.e., there is no
// matching opening delimiter).
let token_str = token_to_string(&self.token);
let msg = format!("unexpected close delimiter: `{}`", token_str);
let mut err = self.string_reader.sess.span_diagnostic
.struct_span_err(self.token.span, &msg);
if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
err.span_label(span, "this block is empty, you might have not meant to close it");
}
err.span_label(self.token.span, "unexpected close delimiter");
Err(err)
},

View file

@ -36,7 +36,7 @@ pub enum BinOpToken {
}
/// A delimiter token.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum DelimToken {
/// A round parenthesis (i.e., `(` or `)`).
Paren,

View file

@ -0,0 +1,3 @@
fn main() {}
let _ = ();
} //~ ERROR unexpected close delimiter

View file

@ -0,0 +1,11 @@
error: unexpected close delimiter: `}`
--> $DIR/mismatched-delim-brace-empty-block.rs:3:1
|
LL | fn main() {}
| -- this block is empty, you might have not meant to close it
LL | let _ = ();
LL | }
| ^ unexpected close delimiter
error: aborting due to previous error