Rollup merge of #87671 - jesyspa:issue-87319-multiple-newlines, r=estebank
Warn when an escaped newline skips multiple lines Resolves #87319
This commit is contained in:
commit
53a66acbd3
@ -60,6 +60,9 @@ pub enum EscapeError {
|
||||
/// After a line ending with '\', the next line contains whitespace
|
||||
/// characters that are not skipped.
|
||||
UnskippedWhitespaceWarning,
|
||||
|
||||
/// After a line ending with '\', multiple lines are skipped.
|
||||
MultipleSkippedLinesWarning,
|
||||
}
|
||||
|
||||
impl EscapeError {
|
||||
@ -67,6 +70,7 @@ impl EscapeError {
|
||||
pub fn is_fatal(&self) -> bool {
|
||||
match self {
|
||||
EscapeError::UnskippedWhitespaceWarning => false,
|
||||
EscapeError::MultipleSkippedLinesWarning => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
@ -315,12 +319,17 @@ where
|
||||
where
|
||||
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
||||
{
|
||||
let str = chars.as_str();
|
||||
let first_non_space = str
|
||||
let tail = chars.as_str();
|
||||
let first_non_space = tail
|
||||
.bytes()
|
||||
.position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r')
|
||||
.unwrap_or(str.len());
|
||||
let tail = &str[first_non_space..];
|
||||
.unwrap_or(tail.len());
|
||||
if tail[1..first_non_space].contains('\n') {
|
||||
// The +1 accounts for the escaping slash.
|
||||
let end = start + first_non_space + 1;
|
||||
callback(start..end, Err(EscapeError::MultipleSkippedLinesWarning));
|
||||
}
|
||||
let tail = &tail[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.
|
||||
|
@ -106,6 +106,10 @@ fn test_unescape_str_warn() {
|
||||
assert_eq!(unescaped, expected);
|
||||
}
|
||||
|
||||
// Check we can handle escaped newlines at the end of a file.
|
||||
check("\\\n", &[]);
|
||||
check("\\\n ", &[]);
|
||||
|
||||
check(
|
||||
"\\\n \u{a0} x",
|
||||
&[
|
||||
@ -115,6 +119,7 @@ fn test_unescape_str_warn() {
|
||||
(6..7, Ok('x')),
|
||||
],
|
||||
);
|
||||
check("\\\n \n x", &[(0..7, Err(EscapeError::MultipleSkippedLinesWarning)), (7..8, Ok('x'))]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -280,6 +280,11 @@ pub(crate) fn emit_unescape_error(
|
||||
format!("non-ASCII whitespace symbol '{}' is not skipped", c.escape_unicode());
|
||||
handler.struct_span_warn(span, &msg).span_label(char_span, &msg).emit();
|
||||
}
|
||||
EscapeError::MultipleSkippedLinesWarning => {
|
||||
let msg = "multiple lines skipped by escaped newline";
|
||||
let bottom_msg = "skipping everything up to and including this point";
|
||||
handler.struct_span_warn(span, msg).span_label(span, bottom_msg).emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ fn main() {
|
||||
a");
|
||||
//~^ ERROR invalid format string
|
||||
format!("{ \
|
||||
|
||||
\
|
||||
b");
|
||||
//~^ ERROR invalid format string
|
||||
format!(r#"{ \
|
||||
@ -38,12 +38,12 @@ fn main() {
|
||||
{ \
|
||||
\
|
||||
b \
|
||||
|
||||
\
|
||||
");
|
||||
//~^^^ ERROR invalid format string
|
||||
format!(r#"
|
||||
raw { \
|
||||
|
||||
\
|
||||
c"#);
|
||||
//~^^^ ERROR invalid format string
|
||||
format!(r#"
|
||||
|
@ -19,7 +19,7 @@ error: invalid format string: expected `'}'`, found `'b'`
|
||||
|
|
||||
LL | format!("{ \
|
||||
| - because of this opening brace
|
||||
LL |
|
||||
LL | \
|
||||
LL | b");
|
||||
| ^ expected `}` in format string
|
||||
|
|
||||
|
11
src/test/ui/str/str-escape.rs
Normal file
11
src/test/ui/str/str-escape.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// check-pass
|
||||
fn main() {
|
||||
let s = "\
|
||||
|
||||
";
|
||||
//~^^^ WARNING multiple lines skipped by escaped newline
|
||||
let s = "foo\
|
||||
bar
|
||||
";
|
||||
//~^^^ WARNING non-ASCII whitespace symbol '\u{a0}' is not skipped
|
||||
}
|
21
src/test/ui/str/str-escape.stderr
Normal file
21
src/test/ui/str/str-escape.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
warning: multiple lines skipped by escaped newline
|
||||
--> $DIR/str-escape.rs:3:14
|
||||
|
|
||||
LL | let s = "\
|
||||
| ______________^
|
||||
LL | |
|
||||
LL | | ";
|
||||
| |_____________^ skipping everything up to and including this point
|
||||
|
||||
warning: non-ASCII whitespace symbol '\u{a0}' is not skipped
|
||||
--> $DIR/str-escape.rs:7:17
|
||||
|
|
||||
LL | let s = "foo\
|
||||
| _________________^
|
||||
LL | | bar
|
||||
| | ^ non-ASCII whitespace symbol '\u{a0}' is not skipped
|
||||
| |___|
|
||||
|
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
Loading…
x
Reference in New Issue
Block a user