Rollup merge of #62297 - matklad:peek-delimited, r=petrochenkov
refactor check_for_substitution No behavior change, just flatter and simpler code. r? @petrochenkov
This commit is contained in:
commit
c0ec567214
|
@ -83,28 +83,6 @@ impl<'a> StringReader<'a> {
|
||||||
Ok(ret_val)
|
Ok(ret_val)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Immutably extract string if found at current position with given delimiters
|
|
||||||
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<Token, ()> {
|
fn try_real_token(&mut self) -> Result<Token, ()> {
|
||||||
let mut t = self.try_next_token()?;
|
let mut t = self.try_next_token()?;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
// Characters and their corresponding confusables were collected from
|
// Characters and their corresponding confusables were collected from
|
||||||
// http://www.unicode.org/Public/security/10.0.0/confusables.txt
|
// http://www.unicode.org/Public/security/10.0.0/confusables.txt
|
||||||
|
|
||||||
use syntax_pos::{Span, Pos, NO_EXPANSION};
|
|
||||||
use errors::{Applicability, DiagnosticBuilder};
|
|
||||||
use super::StringReader;
|
use super::StringReader;
|
||||||
|
use errors::{Applicability, DiagnosticBuilder};
|
||||||
|
use syntax_pos::{Pos, Span, NO_EXPANSION};
|
||||||
|
|
||||||
|
#[rustfmt::skip] // for line breaks
|
||||||
const UNICODE_ARRAY: &[(char, &str, char)] = &[
|
const UNICODE_ARRAY: &[(char, &str, char)] = &[
|
||||||
('
', "Line Separator", ' '),
|
('
', "Line Separator", ' '),
|
||||||
('
', "Paragraph Separator", ' '),
|
('
', "Paragraph Separator", ' '),
|
||||||
|
@ -293,8 +294,8 @@ const UNICODE_ARRAY: &[(char, &str, char)] = &[
|
||||||
('〉', "Right-Pointing Angle Bracket", '>'),
|
('〉', "Right-Pointing Angle Bracket", '>'),
|
||||||
('〉', "Right Angle Bracket", '>'),
|
('〉', "Right Angle Bracket", '>'),
|
||||||
('》', "Right Double Angle Bracket", '>'),
|
('》', "Right Double Angle Bracket", '>'),
|
||||||
('>', "Fullwidth Greater-Than Sign", '>'), ];
|
('>', "Fullwidth Greater-Than Sign", '>'),
|
||||||
|
];
|
||||||
|
|
||||||
const ASCII_ARRAY: &[(char, &str)] = &[
|
const ASCII_ARRAY: &[(char, &str)] = &[
|
||||||
(' ', "Space"),
|
(' ', "Space"),
|
||||||
|
@ -321,46 +322,72 @@ const ASCII_ARRAY: &[(char, &str)] = &[
|
||||||
('+', "Plus Sign"),
|
('+', "Plus Sign"),
|
||||||
('<', "Less-Than Sign"),
|
('<', "Less-Than Sign"),
|
||||||
('=', "Equals Sign"),
|
('=', "Equals Sign"),
|
||||||
('>', "Greater-Than Sign"), ];
|
('>', "Greater-Than Sign"),
|
||||||
|
];
|
||||||
|
|
||||||
crate fn check_for_substitution<'a>(reader: &StringReader<'a>,
|
crate fn check_for_substitution<'a>(
|
||||||
ch: char,
|
reader: &StringReader<'a>,
|
||||||
err: &mut DiagnosticBuilder<'a>) -> bool {
|
ch: char,
|
||||||
UNICODE_ARRAY
|
err: &mut DiagnosticBuilder<'a>,
|
||||||
.iter()
|
) -> bool {
|
||||||
.find(|&&(c, _, _)| c == ch)
|
let (u_name, ascii_char) = match UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) {
|
||||||
.map(|&(_, u_name, ascii_char)| {
|
Some(&(_u_char, u_name, ascii_char)) => (u_name, ascii_char),
|
||||||
let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION);
|
None => return false,
|
||||||
match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
|
};
|
||||||
Some(&(ascii_char, ascii_name)) => {
|
|
||||||
// special help suggestion for "directed" double quotes
|
let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION);
|
||||||
if let Some(s) = reader.peek_delimited('“', '”') {
|
|
||||||
let msg = format!("Unicode characters '“' (Left Double Quotation Mark) and \
|
let ascii_name = match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
|
||||||
'”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
|
Some((_ascii_char, ascii_name)) => ascii_name,
|
||||||
ascii_char, ascii_name);
|
None => {
|
||||||
err.span_suggestion(
|
let msg = format!("substitution character not found for '{}'", ch);
|
||||||
Span::new(reader.pos, reader.next_pos + Pos::from_usize(s.len()) +
|
reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
|
||||||
Pos::from_usize('”'.len_utf8()), NO_EXPANSION),
|
return false
|
||||||
&msg,
|
},
|
||||||
format!("\"{}\"", s),
|
};
|
||||||
Applicability::MaybeIncorrect);
|
|
||||||
} else {
|
// special help suggestion for "directed" double quotes
|
||||||
let msg =
|
if let Some(s) = reader.peek_delimited('“', '”') {
|
||||||
format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
|
let msg = format!(
|
||||||
ch, u_name, ascii_char, ascii_name);
|
"Unicode characters '“' (Left Double Quotation Mark) and \
|
||||||
err.span_suggestion(
|
'”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
|
||||||
span,
|
ascii_char, ascii_name
|
||||||
&msg,
|
);
|
||||||
ascii_char.to_string(),
|
err.span_suggestion(
|
||||||
Applicability::MaybeIncorrect);
|
Span::new(
|
||||||
}
|
reader.pos,
|
||||||
true
|
reader.next_pos + Pos::from_usize(s.len()) + Pos::from_usize('”'.len_utf8()),
|
||||||
},
|
NO_EXPANSION,
|
||||||
None => {
|
),
|
||||||
let msg = format!("substitution character not found for '{}'", ch);
|
&msg,
|
||||||
reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
|
format!("\"{}\"", s),
|
||||||
false
|
Applicability::MaybeIncorrect,
|
||||||
}
|
);
|
||||||
}
|
} else {
|
||||||
}).unwrap_or(false)
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StringReader<'_> {
|
||||||
|
/// Immutably extract string if found at current position with given delimiters
|
||||||
|
fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<&str> {
|
||||||
|
let tail = &self.src[self.src_index(self.pos)..];
|
||||||
|
let mut chars = tail.chars();
|
||||||
|
let first_char = chars.next()?;
|
||||||
|
if first_char != from_ch {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let last_char_idx = chars.as_str().find(to_ch)?;
|
||||||
|
Some(&chars.as_str()[..last_char_idx])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue