Add warning when whitespace is not skipped after an escaped newline.
This commit is contained in:
@@ -7,7 +7,7 @@ use std::str::Chars;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Errors that can occur during string unescaping.
|
||||
/// Errors and warnings that can occur during string unescaping.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum EscapeError {
|
||||
/// Expected 1 char, but 0 were found.
|
||||
@@ -56,6 +56,20 @@ pub enum EscapeError {
|
||||
NonAsciiCharInByte,
|
||||
/// Non-ascii character in byte string literal.
|
||||
NonAsciiCharInByteString,
|
||||
|
||||
/// After a line ending with '\', the next line contains whitespace
|
||||
/// characters that are not skipped.
|
||||
UnskippedWhitespaceWarning,
|
||||
}
|
||||
|
||||
impl EscapeError {
|
||||
/// Returns true for actual errors, as opposed to warnings.
|
||||
pub fn is_fatal(&self) -> bool {
|
||||
match self {
|
||||
EscapeError::UnskippedWhitespaceWarning => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a contents of a literal (without quotes) and produces a
|
||||
@@ -283,7 +297,7 @@ where
|
||||
// if unescaped '\' character is followed by '\n'.
|
||||
// For details see [Rust language reference]
|
||||
// (https://doc.rust-lang.org/reference/tokens.html#string-literals).
|
||||
skip_ascii_whitespace(&mut chars);
|
||||
skip_ascii_whitespace(&mut chars, start, callback);
|
||||
continue;
|
||||
}
|
||||
_ => scan_escape(first_char, &mut chars, mode),
|
||||
@@ -297,13 +311,25 @@ where
|
||||
callback(start..end, unescaped_char);
|
||||
}
|
||||
|
||||
fn skip_ascii_whitespace(chars: &mut Chars<'_>) {
|
||||
fn skip_ascii_whitespace<F>(chars: &mut Chars<'_>, start: usize, callback: &mut F)
|
||||
where
|
||||
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
||||
{
|
||||
let str = chars.as_str();
|
||||
let first_non_space = str
|
||||
.bytes()
|
||||
.position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r')
|
||||
.unwrap_or(str.len());
|
||||
*chars = str[first_non_space..].chars()
|
||||
let tail = &str[first_non_space..];
|
||||
if let Some(c) = tail.chars().nth(0) {
|
||||
// For error reporting, we would like the span to contain the character that was not
|
||||
// skipped. The +1 is necessary to account for the leading \ that started the escape.
|
||||
let end = start + first_non_space + c.len_utf8() + 1;
|
||||
if c.is_whitespace() {
|
||||
callback(start..end, Err(EscapeError::UnskippedWhitespaceWarning));
|
||||
}
|
||||
}
|
||||
*chars = tail.chars();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user