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
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>(
reader: &StringReader<'a>,
ch: char, ch: char,
err: &mut DiagnosticBuilder<'a>) -> bool { err: &mut DiagnosticBuilder<'a>,
UNICODE_ARRAY ) -> bool {
.iter() let (u_name, ascii_char) = match UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) {
.find(|&&(c, _, _)| c == ch) Some(&(_u_char, u_name, ascii_char)) => (u_name, ascii_char),
.map(|&(_, u_name, ascii_char)| { None => return false,
};
let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION); 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 ascii_name = match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
Some((_ascii_char, ascii_name)) => ascii_name,
None => {
let msg = format!("substitution character not found for '{}'", ch);
reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
return false
},
};
// special help suggestion for "directed" double quotes // special help suggestion for "directed" double quotes
if let Some(s) = reader.peek_delimited('“', '”') { if let Some(s) = reader.peek_delimited('“', '”') {
let msg = format!("Unicode characters '“' (Left Double Quotation Mark) and \ let msg = format!(
"Unicode characters '“' (Left Double Quotation Mark) and \
'”' (Right Double Quotation Mark) look like '{}' ({}), but are not", '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
ascii_char, ascii_name); ascii_char, ascii_name
);
err.span_suggestion( err.span_suggestion(
Span::new(reader.pos, reader.next_pos + Pos::from_usize(s.len()) + Span::new(
Pos::from_usize('”'.len_utf8()), NO_EXPANSION), reader.pos,
reader.next_pos + Pos::from_usize(s.len()) + Pos::from_usize('”'.len_utf8()),
NO_EXPANSION,
),
&msg, &msg,
format!("\"{}\"", s), format!("\"{}\"", s),
Applicability::MaybeIncorrect); Applicability::MaybeIncorrect,
);
} else { } else {
let msg = let msg = format!(
format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not", "Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
ch, u_name, ascii_char, ascii_name); ch, u_name, ascii_char, ascii_name
);
err.span_suggestion( err.span_suggestion(
span, span,
&msg, &msg,
ascii_char.to_string(), ascii_char.to_string(),
Applicability::MaybeIncorrect); Applicability::MaybeIncorrect,
);
} }
true true
}, }
None => {
let msg = format!("substitution character not found for '{}'", ch); impl StringReader<'_> {
reader.sess.span_diagnostic.span_bug_no_panic(span, &msg); /// Immutably extract string if found at current position with given delimiters
false 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();
}).unwrap_or(false) 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])
}
} }