mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:25:17 +00:00
Consume the escaped Windows newline (\r\n
) for FStringMiddle
(#7722)
## Summary This PR fixes a bug where if a Windows newline (`\r\n`) character was escaped, then only the `\r` was consumed and not `\n` leading to an unterminated string error. ## Test Plan Add new test cases to check the newline escapes. fixes: #7632
This commit is contained in:
parent
e72d617f4b
commit
e91ffe3e93
4 changed files with 101 additions and 2 deletions
|
@ -584,7 +584,7 @@ impl<'source> Lexer<'source> {
|
|||
location: self.offset(),
|
||||
});
|
||||
}
|
||||
'\n' if !fstring.is_triple_quoted() => {
|
||||
'\n' | '\r' if !fstring.is_triple_quoted() => {
|
||||
return Err(LexicalError {
|
||||
error: LexicalErrorType::FStringError(FStringErrorType::UnterminatedString),
|
||||
location: self.offset(),
|
||||
|
@ -603,7 +603,11 @@ impl<'source> Lexer<'source> {
|
|||
}
|
||||
}
|
||||
// Consume the escaped character.
|
||||
self.cursor.bump();
|
||||
if self.cursor.eat_char('\r') {
|
||||
self.cursor.eat_char('\n');
|
||||
} else {
|
||||
self.cursor.bump();
|
||||
}
|
||||
}
|
||||
quote @ ('\'' | '"') if quote == fstring.quote_char() => {
|
||||
if let Some(triple_quotes) = fstring.triple_quotes() {
|
||||
|
@ -1983,6 +1987,26 @@ def f(arg=%timeit a = b):
|
|||
assert_debug_snapshot!(lex_source(source));
|
||||
}
|
||||
|
||||
fn fstring_single_quote_escape_eol(eol: &str) -> Vec<Spanned> {
|
||||
let source = format!(r"f'text \{eol} more text'");
|
||||
lex_source(&source)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_single_quote_escape_unix_eol() {
|
||||
assert_debug_snapshot!(fstring_single_quote_escape_eol(UNIX_EOL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_single_quote_escape_mac_eol() {
|
||||
assert_debug_snapshot!(fstring_single_quote_escape_eol(MAC_EOL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_single_quote_escape_windows_eol() {
|
||||
assert_debug_snapshot!(fstring_single_quote_escape_eol(WINDOWS_EOL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_escape() {
|
||||
let source = r#"f"\{x:\"\{x}} \"\"\
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/lexer.rs
|
||||
expression: fstring_single_quote_escape_eol(MAC_EOL)
|
||||
---
|
||||
[
|
||||
(
|
||||
FStringStart,
|
||||
0..2,
|
||||
),
|
||||
(
|
||||
FStringMiddle {
|
||||
value: "text \\\r more text",
|
||||
is_raw: false,
|
||||
},
|
||||
2..19,
|
||||
),
|
||||
(
|
||||
FStringEnd,
|
||||
19..20,
|
||||
),
|
||||
(
|
||||
Newline,
|
||||
20..20,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/lexer.rs
|
||||
expression: fstring_single_quote_escape_eol(UNIX_EOL)
|
||||
---
|
||||
[
|
||||
(
|
||||
FStringStart,
|
||||
0..2,
|
||||
),
|
||||
(
|
||||
FStringMiddle {
|
||||
value: "text \\\n more text",
|
||||
is_raw: false,
|
||||
},
|
||||
2..19,
|
||||
),
|
||||
(
|
||||
FStringEnd,
|
||||
19..20,
|
||||
),
|
||||
(
|
||||
Newline,
|
||||
20..20,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/lexer.rs
|
||||
expression: fstring_single_quote_escape_eol(WINDOWS_EOL)
|
||||
---
|
||||
[
|
||||
(
|
||||
FStringStart,
|
||||
0..2,
|
||||
),
|
||||
(
|
||||
FStringMiddle {
|
||||
value: "text \\\r\n more text",
|
||||
is_raw: false,
|
||||
},
|
||||
2..20,
|
||||
),
|
||||
(
|
||||
FStringEnd,
|
||||
20..21,
|
||||
),
|
||||
(
|
||||
Newline,
|
||||
21..21,
|
||||
),
|
||||
]
|
Loading…
Add table
Add a link
Reference in a new issue