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:
Mazdak Farrokhzad 2019-07-04 01:38:55 +02:00 committed by GitHub
commit c0ec567214
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 67 deletions

View File

@ -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 {

View File

@ -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])
}
} }