diff options
| author | Patrick McCarter <p.mccarter@gmail.com> | 2019-02-16 19:56:30 -0500 |
|---|---|---|
| committer | Patrick McCarter <p.mccarter@gmail.com> | 2019-02-16 19:56:30 -0500 |
| commit | c34aac7b1703edc9ef4ebaa17c16b96a18ca1443 (patch) | |
| tree | f346a3ef97e724a87f8def9bc26594788d037280 /src/libsyntax/parse | |
| parent | eac09088e1a8fc8a293028764e4e84da29469205 (diff) | |
| download | rust-c34aac7b1703edc9ef4ebaa17c16b96a18ca1443.tar.gz rust-c34aac7b1703edc9ef4ebaa17c16b96a18ca1443.zip | |
help suggestion when trying to delimit string literals with directed unicode quotes #58436
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/unicode_chars.rs | 31 |
2 files changed, 44 insertions, 9 deletions
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index babe0eef20f..a7cde5fbb92 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -125,6 +125,28 @@ impl<'a> StringReader<'a> { Ok(ret_val) } + /// Immutably extract string if found at current position with given delimiters + pub fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<String> { + let mut pos = self.pos; + let mut idx = self.src_index(pos); + let mut ch = char_at(&self.src, idx); + if ch != from_ch { + return None; + } + pos = pos + Pos::from_usize(ch.len_utf8()); + let start_pos = pos; + idx = self.src_index(pos); + while idx < self.end_src_index { + ch = char_at(&self.src, idx); + if ch == to_ch { + return Some(self.src[self.src_index(start_pos)..self.src_index(pos)].to_string()); + } + pos = pos + Pos::from_usize(ch.len_utf8()); + idx = self.src_index(pos); + } + return None; + } + fn try_real_token(&mut self) -> Result<TokenAndSpan, ()> { let mut t = self.try_next_token()?; loop { diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 7da4284c0e4..94ce6297fbe 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -1,7 +1,7 @@ // Characters and their corresponding confusables were collected from // http://www.unicode.org/Public/security/10.0.0/confusables.txt -use syntax_pos::{Span, NO_EXPANSION}; +use syntax_pos::{Span, Pos, NO_EXPANSION}; use errors::{Applicability, DiagnosticBuilder}; use super::StringReader; @@ -333,14 +333,27 @@ crate fn check_for_substitution<'a>(reader: &StringReader<'a>, let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION); match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) { Some(&(ascii_char, ascii_name)) => { - let msg = - format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not", - ch, u_name, ascii_char, ascii_name); - err.span_suggestion( - span, - &msg, - ascii_char.to_string(), - Applicability::MaybeIncorrect); + // special help suggestion for "directed" double quotes + if let Some(s) = reader.peek_delimited('“', '”') { + let msg = format!("Unicode characters '“' (Left Double Quotation Mark) and \ + '”' (Right Double Quotation Mark) look like '{}' ({}), but are not", + ascii_char, ascii_name); + err.span_suggestion( + Span::new(reader.pos, reader.next_pos + Pos::from_usize(s.len()) + + Pos::from_usize('”'.len_utf8()), NO_EXPANSION), + &msg, + format!("\"{}\"", s), + Applicability::MaybeIncorrect); + } else { + let msg = + format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not", + ch, u_name, ascii_char, ascii_name); + err.span_suggestion( + span, + &msg, + ascii_char.to_string(), + Applicability::MaybeIncorrect); + } true }, None => { |
