Skip to content

Commit c34aac7

Browse files
committed
help suggestion when trying to delimit string literals with directed unicode quotes #58436
1 parent eac0908 commit c34aac7

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

src/libsyntax/parse/lexer/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ impl<'a> StringReader<'a> {
125125
Ok(ret_val)
126126
}
127127

128+
/// Immutably extract string if found at current position with given delimiters
129+
pub fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<String> {
130+
let mut pos = self.pos;
131+
let mut idx = self.src_index(pos);
132+
let mut ch = char_at(&self.src, idx);
133+
if ch != from_ch {
134+
return None;
135+
}
136+
pos = pos + Pos::from_usize(ch.len_utf8());
137+
let start_pos = pos;
138+
idx = self.src_index(pos);
139+
while idx < self.end_src_index {
140+
ch = char_at(&self.src, idx);
141+
if ch == to_ch {
142+
return Some(self.src[self.src_index(start_pos)..self.src_index(pos)].to_string());
143+
}
144+
pos = pos + Pos::from_usize(ch.len_utf8());
145+
idx = self.src_index(pos);
146+
}
147+
return None;
148+
}
149+
128150
fn try_real_token(&mut self) -> Result<TokenAndSpan, ()> {
129151
let mut t = self.try_next_token()?;
130152
loop {

src/libsyntax/parse/lexer/unicode_chars.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Characters and their corresponding confusables were collected from
22
// http://www.unicode.org/Public/security/10.0.0/confusables.txt
33

4-
use syntax_pos::{Span, NO_EXPANSION};
4+
use syntax_pos::{Span, Pos, NO_EXPANSION};
55
use errors::{Applicability, DiagnosticBuilder};
66
use super::StringReader;
77

@@ -333,14 +333,27 @@ crate fn check_for_substitution<'a>(reader: &StringReader<'a>,
333333
let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION);
334334
match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
335335
Some(&(ascii_char, ascii_name)) => {
336-
let msg =
337-
format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
338-
ch, u_name, ascii_char, ascii_name);
339-
err.span_suggestion(
340-
span,
341-
&msg,
342-
ascii_char.to_string(),
343-
Applicability::MaybeIncorrect);
336+
// special help suggestion for "directed" double quotes
337+
if let Some(s) = reader.peek_delimited('“', '”') {
338+
let msg = format!("Unicode characters '“' (Left Double Quotation Mark) and \
339+
'”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
340+
ascii_char, ascii_name);
341+
err.span_suggestion(
342+
Span::new(reader.pos, reader.next_pos + Pos::from_usize(s.len()) +
343+
Pos::from_usize('”'.len_utf8()), NO_EXPANSION),
344+
&msg,
345+
format!("\"{}\"", s),
346+
Applicability::MaybeIncorrect);
347+
} else {
348+
let msg =
349+
format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
350+
ch, u_name, ascii_char, ascii_name);
351+
err.span_suggestion(
352+
span,
353+
&msg,
354+
ascii_char.to_string(),
355+
Applicability::MaybeIncorrect);
356+
}
344357
true
345358
},
346359
None => {

0 commit comments

Comments
 (0)