Sync interpolated lexer state within `re_lex_logical_token`

This commit is contained in:
Micha Reiser 2025-12-10 17:16:28 +01:00
parent 7d47f711c1
commit c4e32ea180
No known key found for this signature in database
3 changed files with 35 additions and 27 deletions

View File

@ -841,7 +841,7 @@ impl TokenFlags {
self.intersects(TokenFlags::T_STRING.union(TokenFlags::F_STRING)) self.intersects(TokenFlags::T_STRING.union(TokenFlags::F_STRING))
} }
/// Returns `true` if the token is a triple-quoted t-string. /// Returns `true` if the token is a triple-quoted interpolated-string.
pub fn is_triple_quoted_interpolated_string(self) -> bool { pub fn is_triple_quoted_interpolated_string(self) -> bool {
self.intersects(TokenFlags::TRIPLE_QUOTED_STRING) && self.is_interpolated_string() self.intersects(TokenFlags::TRIPLE_QUOTED_STRING) && self.is_interpolated_string()
} }

View File

@ -1452,14 +1452,20 @@ impl<'src> Lexer<'src> {
return false; return false;
} }
if let Some(interpolated) = self.interpolated_strings.current_mut() {
interpolated.try_end_format_spec(self.nesting);
}
// Reduce the nesting level because the parser recovered from an error inside list parsing // Reduce the nesting level because the parser recovered from an error inside list parsing
// i.e., it recovered from an unclosed parenthesis (`(`, `[`, or `{`). // i.e., it recovered from an unclosed parenthesis (`(`, `[`, or `{`).
self.nesting -= 1; self.nesting -= 1;
// The lexer can't be moved back for a triple-quoted f/t-string because the newlines are // A nesting level that's lower than the nesting when the interpolated string was created
// part of the f/t-string itself, so there is no newline token to be emitted. // strongly suggests that we're now outside an interpolated string.
if self.current_flags.is_triple_quoted_interpolated_string() { if let Some(interpolated) = self.interpolated_strings.current()
return false; && interpolated.nesting() < self.nesting
{
self.interpolated_strings.pop();
} }
let Some(new_position) = non_logical_newline_start else { let Some(new_position) = non_logical_newline_start else {
@ -1537,6 +1543,8 @@ impl<'src> Lexer<'src> {
} }
} }
dbg!("Handle unclosed string");
if self.errors.last().is_some_and(|error| { if self.errors.last().is_some_and(|error| {
error.location() == self.current_range error.location() == self.current_range
&& matches!(error.error(), LexicalErrorType::UnclosedStringError) && matches!(error.error(), LexicalErrorType::UnclosedStringError)

View File

@ -145,6 +145,28 @@ Module(
simple: false, simple: false,
}, },
), ),
ClassDef(
StmtClassDef {
node_index: NodeIndex(None),
range: 94..111,
decorator_list: [],
name: Identifier {
id: Name("A"),
range: 100..101,
node_index: NodeIndex(None),
},
type_params: None,
arguments: None,
body: [
Pass(
StmtPass {
node_index: NodeIndex(None),
range: 107..111,
},
),
],
},
),
], ],
}, },
) )
@ -189,17 +211,6 @@ Module(
| |
|
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
2 | (c: int = 1,f"""{d=[
3 | def a(
| _______^
4 | | class A:
5 | | pass
| |_________^ Syntax Error: f-string: unterminated triple-quoted string
|
| |
2 | (c: int = 1,f"""{d=[ 2 | (c: int = 1,f"""{d=[
3 | def a( 3 | def a(
@ -209,17 +220,6 @@ Module(
| |
|
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
2 | (c: int = 1,f"""{d=[
3 | def a(
| _______^
4 | | class A:
5 | | pass
| |_________^ Syntax Error: Expected a statement
|
| |
4 | class A: 4 | class A:
5 | pass 5 | pass