diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2018-09-04 08:09:49 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2018-09-05 03:43:24 -0700 |
| commit | 008aa5a24e152691d852bd9f0a2990b6e4377397 (patch) | |
| tree | 13847227aed9aaca1f822f60180704fc72576e3a /src/libsyntax/parse | |
| parent | 5238b523c3959e33add469af77b2ffa5a60b4cf6 (diff) | |
| download | rust-008aa5a24e152691d852bd9f0a2990b6e4377397.tar.gz rust-008aa5a24e152691d852bd9f0a2990b6e4377397.zip | |
Provide more context for unenclosed delimiters
* When encountering EOF, point at the last opening brace that does not have the same indentation level as its close delimiter. * When encountering the wrong type of close delimiter, point at the likely correct open delimiter to give a better idea of what went wrong.
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/tokentrees.rs | 40 |
2 files changed, 43 insertions, 2 deletions
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 96584a580f1..b7e8a880e7e 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -66,6 +66,10 @@ pub struct StringReader<'a> { /// The raw source span which *does not* take `override_span` into account span_src_raw: Span, open_braces: Vec<(token::DelimToken, Span)>, + /// The type and spans for all braces that have different indentation. + /// + /// Used only for error recovery when arriving to EOF with mismatched braces. + suspicious_open_spans: Vec<(token::DelimToken, Span, Span)>, crate override_span: Option<Span>, last_unclosed_found_span: Option<Span>, } @@ -216,6 +220,7 @@ impl<'a> StringReader<'a> { span: syntax_pos::DUMMY_SP, span_src_raw: syntax_pos::DUMMY_SP, open_braces: Vec::new(), + suspicious_open_spans: Vec::new(), override_span, last_unclosed_found_span: None, } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index e8404adec0f..2999e65ae4a 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -52,6 +52,20 @@ impl<'a> StringReader<'a> { err.span_label(sp, "un-closed delimiter"); } + if let Some((delim, _)) = self.open_braces.last() { + if let Some((d, open_sp, close_sp)) = self.suspicious_open_spans.iter() + .filter(|(d, _, _)| delim == d) + .next() // these are in reverse order as they get inserted on close, but + { // we want the last open/first close + if d == delim { + err.span_label(*open_sp, "this might be the culprit..."); + err.span_label( + *close_sp, + "...as it matches this but it has different indentation", + ); + } + } + } Err(err) }, token::OpenDelim(delim) => { @@ -70,11 +84,20 @@ impl<'a> StringReader<'a> { // Expand to cover the entire delimited token tree let span = pre_span.with_hi(self.span.hi()); + let sm = self.sess.source_map(); match self.token { // Correct delimiter. token::CloseDelim(d) if d == delim => { - self.open_braces.pop().unwrap(); - + let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); + if let Some(current_padding) = sm.span_to_margin(self.span) { + if let Some(padding) = sm.span_to_margin(open_brace_span) { + if current_padding != padding { + self.suspicious_open_spans.push( + (open_brace, open_brace_span, self.span), + ); + } + } + } // Parse the close delimiter. self.real_token(); } @@ -96,6 +119,19 @@ impl<'a> StringReader<'a> { if let Some(&(_, sp)) = self.open_braces.last() { err.span_label(sp, "un-closed delimiter"); }; + if let Some(current_padding) = sm.span_to_margin(self.span) { + for (brace, brace_span) in &self.open_braces { + if let Some(padding) = sm.span_to_margin(*brace_span) { + // high likelihood of these two corresponding + if current_padding == padding && brace == &other { + err.span_label( + *brace_span, + "close delimiter possibly meant for this", + ); + } + } + } + } err.emit(); } self.open_braces.pop().unwrap(); |
