diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_implicit_str_concat/ISC_syntax_error.py b/crates/ruff_linter/resources/test/fixtures/flake8_implicit_str_concat/ISC_syntax_error.py index 997c86968d..dae709face 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_implicit_str_concat/ISC_syntax_error.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_implicit_str_concat/ISC_syntax_error.py @@ -1,10 +1,10 @@ -# The lexer doesn't emit a string token if it's unterminated +# The lexer emits a string token if it's unterminated "a" "b "a" "b" "c "a" """b c""" "d -# For f-strings, the `FStringRanges` won't contain the range for +# This is also true for # unterminated f-strings. f"a" f"b f"a" f"b" f"c diff --git a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC001_ISC_syntax_error.py.snap b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC001_ISC_syntax_error.py.snap index 0b61838958..ac74361ae5 100644 --- a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC001_ISC_syntax_error.py.snap +++ b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC001_ISC_syntax_error.py.snap @@ -1,22 +1,23 @@ --- source: crates/ruff_linter/src/rules/flake8_implicit_str_concat/mod.rs --- -invalid-syntax: missing closing quote in string literal - --> ISC_syntax_error.py:2:5 +ISC001 Implicitly concatenated string literals on one line + --> ISC_syntax_error.py:2:1 | -1 | # The lexer doesn't emit a string token if it's unterminated +1 | # The lexer emits a string token if it's unterminated 2 | "a" "b - | ^^ + | ^^^^^^ 3 | "a" "b" "c 4 | "a" """b | +help: Combine string literals -invalid-syntax: Expected a statement - --> ISC_syntax_error.py:2:7 +invalid-syntax: missing closing quote in string literal + --> ISC_syntax_error.py:2:5 | -1 | # The lexer doesn't emit a string token if it's unterminated +1 | # The lexer emits a string token if it's unterminated 2 | "a" "b - | ^ + | ^^ 3 | "a" "b" "c 4 | "a" """b | @@ -24,7 +25,7 @@ invalid-syntax: Expected a statement ISC001 Implicitly concatenated string literals on one line --> ISC_syntax_error.py:3:1 | -1 | # The lexer doesn't emit a string token if it's unterminated +1 | # The lexer emits a string token if it's unterminated 2 | "a" "b 3 | "a" "b" "c | ^^^^^^^ @@ -33,24 +34,25 @@ ISC001 Implicitly concatenated string literals on one line | help: Combine string literals -invalid-syntax: missing closing quote in string literal - --> ISC_syntax_error.py:3:9 +ISC001 Implicitly concatenated string literals on one line + --> ISC_syntax_error.py:3:5 | -1 | # The lexer doesn't emit a string token if it's unterminated +1 | # The lexer emits a string token if it's unterminated 2 | "a" "b 3 | "a" "b" "c - | ^^ + | ^^^^^^ 4 | "a" """b 5 | c""" "d | +help: Combine string literals -invalid-syntax: Expected a statement - --> ISC_syntax_error.py:3:11 +invalid-syntax: missing closing quote in string literal + --> ISC_syntax_error.py:3:9 | -1 | # The lexer doesn't emit a string token if it's unterminated +1 | # The lexer emits a string token if it's unterminated 2 | "a" "b 3 | "a" "b" "c - | ^ + | ^^ 4 | "a" """b 5 | c""" "d | @@ -64,7 +66,21 @@ ISC001 Implicitly concatenated string literals on one line 5 | | c""" "d | |____^ 6 | -7 | # For f-strings, the `FStringRanges` won't contain the range for +7 | # This is also true for + | +help: Combine string literals + +ISC001 Implicitly concatenated string literals on one line + --> ISC_syntax_error.py:4:5 + | +2 | "a" "b +3 | "a" "b" "c +4 | "a" """b + | _____^ +5 | | c""" "d + | |_______^ +6 | +7 | # This is also true for | help: Combine string literals @@ -76,24 +92,13 @@ invalid-syntax: missing closing quote in string literal 5 | c""" "d | ^^ 6 | -7 | # For f-strings, the `FStringRanges` won't contain the range for - | - -invalid-syntax: Expected a statement - --> ISC_syntax_error.py:5:8 - | -3 | "a" "b" "c -4 | "a" """b -5 | c""" "d - | ^ -6 | -7 | # For f-strings, the `FStringRanges` won't contain the range for +7 | # This is also true for | invalid-syntax: f-string: unterminated string --> ISC_syntax_error.py:9:8 | - 7 | # For f-strings, the `FStringRanges` won't contain the range for + 7 | # This is also true for 8 | # unterminated f-strings. 9 | f"a" f"b | ^ @@ -104,7 +109,7 @@ invalid-syntax: f-string: unterminated string invalid-syntax: Expected FStringEnd, found newline --> ISC_syntax_error.py:9:9 | - 7 | # For f-strings, the `FStringRanges` won't contain the range for + 7 | # This is also true for 8 | # unterminated f-strings. 9 | f"a" f"b | ^ @@ -183,14 +188,6 @@ invalid-syntax: f-string: unterminated triple-quoted string | |__^ | -invalid-syntax: unexpected EOF while parsing - --> ISC_syntax_error.py:30:1 - | -28 | "i" "j" -29 | ) - | ^ - | - invalid-syntax: f-string: unterminated string --> ISC_syntax_error.py:30:1 | diff --git a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC002_ISC_syntax_error.py.snap b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC002_ISC_syntax_error.py.snap index 1cbcf596b3..6c645ec5d1 100644 --- a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC002_ISC_syntax_error.py.snap +++ b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/snapshots/ruff_linter__rules__flake8_implicit_str_concat__tests__ISC002_ISC_syntax_error.py.snap @@ -4,27 +4,17 @@ source: crates/ruff_linter/src/rules/flake8_implicit_str_concat/mod.rs invalid-syntax: missing closing quote in string literal --> ISC_syntax_error.py:2:5 | -1 | # The lexer doesn't emit a string token if it's unterminated +1 | # The lexer emits a string token if it's unterminated 2 | "a" "b | ^^ 3 | "a" "b" "c 4 | "a" """b | -invalid-syntax: Expected a statement - --> ISC_syntax_error.py:2:7 - | -1 | # The lexer doesn't emit a string token if it's unterminated -2 | "a" "b - | ^ -3 | "a" "b" "c -4 | "a" """b - | - invalid-syntax: missing closing quote in string literal --> ISC_syntax_error.py:3:9 | -1 | # The lexer doesn't emit a string token if it's unterminated +1 | # The lexer emits a string token if it's unterminated 2 | "a" "b 3 | "a" "b" "c | ^^ @@ -32,17 +22,6 @@ invalid-syntax: missing closing quote in string literal 5 | c""" "d | -invalid-syntax: Expected a statement - --> ISC_syntax_error.py:3:11 - | -1 | # The lexer doesn't emit a string token if it's unterminated -2 | "a" "b -3 | "a" "b" "c - | ^ -4 | "a" """b -5 | c""" "d - | - invalid-syntax: missing closing quote in string literal --> ISC_syntax_error.py:5:6 | @@ -51,24 +30,13 @@ invalid-syntax: missing closing quote in string literal 5 | c""" "d | ^^ 6 | -7 | # For f-strings, the `FStringRanges` won't contain the range for - | - -invalid-syntax: Expected a statement - --> ISC_syntax_error.py:5:8 - | -3 | "a" "b" "c -4 | "a" """b -5 | c""" "d - | ^ -6 | -7 | # For f-strings, the `FStringRanges` won't contain the range for +7 | # This is also true for | invalid-syntax: f-string: unterminated string --> ISC_syntax_error.py:9:8 | - 7 | # For f-strings, the `FStringRanges` won't contain the range for + 7 | # This is also true for 8 | # unterminated f-strings. 9 | f"a" f"b | ^ @@ -79,7 +47,7 @@ invalid-syntax: f-string: unterminated string invalid-syntax: Expected FStringEnd, found newline --> ISC_syntax_error.py:9:9 | - 7 | # For f-strings, the `FStringRanges` won't contain the range for + 7 | # This is also true for 8 | # unterminated f-strings. 9 | f"a" f"b | ^ @@ -133,14 +101,6 @@ invalid-syntax: f-string: unterminated triple-quoted string | |__^ | -invalid-syntax: unexpected EOF while parsing - --> ISC_syntax_error.py:30:1 - | -28 | "i" "j" -29 | ) - | ^ - | - invalid-syntax: f-string: unterminated string --> ISC_syntax_error.py:30:1 | diff --git a/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLE2510_invalid_characters_syntax_error.py.snap b/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLE2510_invalid_characters_syntax_error.py.snap index 10839c42b0..4ae66b4a4a 100644 --- a/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLE2510_invalid_characters_syntax_error.py.snap +++ b/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLE2510_invalid_characters_syntax_error.py.snap @@ -23,16 +23,17 @@ invalid-syntax: missing closing quote in string literal 9 | # Unterminated f-string | -invalid-syntax: Expected a statement - --> invalid_characters_syntax_error.py:7:7 +PLE2510 Invalid unescaped character backspace, use "\b" instead + --> invalid_characters_syntax_error.py:7:6 | 5 | b = '␈' 6 | # Unterminated string 7 | b = '␈ - | ^ + | ^ 8 | b = '␈' 9 | # Unterminated f-string | +help: Replace with escape sequence PLE2510 Invalid unescaped character backspace, use "\b" instead --> invalid_characters_syntax_error.py:8:6 @@ -46,6 +47,18 @@ PLE2510 Invalid unescaped character backspace, use "\b" instead | help: Replace with escape sequence +PLE2510 Invalid unescaped character backspace, use "\b" instead + --> invalid_characters_syntax_error.py:10:7 + | + 8 | b = '␈' + 9 | # Unterminated f-string +10 | b = f'␈ + | ^ +11 | b = f'␈' +12 | # Implicitly concatenated + | +help: Replace with escape sequence + invalid-syntax: f-string: unterminated string --> invalid_characters_syntax_error.py:10:7 | @@ -109,11 +122,12 @@ invalid-syntax: missing closing quote in string literal | ^^ | -invalid-syntax: Expected a statement - --> invalid_characters_syntax_error.py:13:16 +PLE2510 Invalid unescaped character backspace, use "\b" instead + --> invalid_characters_syntax_error.py:13:15 | 11 | b = f'␈' 12 | # Implicitly concatenated 13 | b = '␈' f'␈' '␈ - | ^ + | ^ | +help: Replace with escape sequence diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs index f34751ce93..938ff1aadb 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs @@ -6,7 +6,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_python_ast::helpers::any_over_expr; use ruff_python_ast::str::{leading_quote, trailing_quote}; -use ruff_python_ast::{self as ast, Expr, Keyword}; +use ruff_python_ast::{self as ast, Expr, Keyword, StringFlags}; use ruff_python_literal::format::{ FieldName, FieldNamePart, FieldType, FormatPart, FormatString, FromTemplate, }; @@ -430,7 +430,7 @@ pub(crate) fn f_strings(checker: &Checker, call: &ast::ExprCall, summary: &Forma // dot is the start of an attribute access. break token.start(); } - TokenKind::String => { + TokenKind::String if !token.unwrap_string_flags().is_unclosed() => { match FStringConversion::try_convert(token.range(), &mut summary, checker.locator()) { // If the format string contains side effects that would need to be repeated, diff --git a/crates/ruff_python_ast/src/nodes.rs b/crates/ruff_python_ast/src/nodes.rs index b53582218f..55c055e5bb 100644 --- a/crates/ruff_python_ast/src/nodes.rs +++ b/crates/ruff_python_ast/src/nodes.rs @@ -735,6 +735,8 @@ pub trait StringFlags: Copy { fn prefix(self) -> AnyStringPrefix; + fn is_unclosed(self) -> bool; + /// Is the string triple-quoted, i.e., /// does it begin and end with three consecutive quote characters? fn is_triple_quoted(self) -> bool { @@ -779,6 +781,7 @@ pub trait StringFlags: Copy { fn as_any_string_flags(self) -> AnyStringFlags { AnyStringFlags::new(self.prefix(), self.quote_style(), self.triple_quotes()) + .with_unclosed(self.is_unclosed()) } fn display_contents(self, contents: &str) -> DisplayFlags<'_> { @@ -829,6 +832,10 @@ bitflags! { /// for why we track the casing of the `r` prefix, /// but not for any other prefix const R_PREFIX_UPPER = 1 << 3; + + /// The f-string is unclosed, meaning it is missing a closing quote. + /// For example: `f"{bar` + const UNCLOSED = 1 << 4; } } @@ -887,6 +894,12 @@ impl FStringFlags { self } + #[must_use] + pub fn with_unclosed(mut self, unclosed: bool) -> Self { + self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed); + self + } + #[must_use] pub fn with_prefix(mut self, prefix: FStringPrefix) -> Self { match prefix { @@ -984,6 +997,12 @@ impl TStringFlags { self } + #[must_use] + pub fn with_unclosed(mut self, unclosed: bool) -> Self { + self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed); + self + } + #[must_use] pub fn with_prefix(mut self, prefix: TStringPrefix) -> Self { match prefix { @@ -1051,6 +1070,10 @@ impl StringFlags for FStringFlags { fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Format(self.prefix()) } + + fn is_unclosed(self) -> bool { + self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED) + } } impl fmt::Debug for FStringFlags { @@ -1059,6 +1082,7 @@ impl fmt::Debug for FStringFlags { .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) + .field("unclosed", &self.is_unclosed()) .finish() } } @@ -1090,6 +1114,10 @@ impl StringFlags for TStringFlags { fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Template(self.prefix()) } + + fn is_unclosed(self) -> bool { + self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED) + } } impl fmt::Debug for TStringFlags { @@ -1098,6 +1126,7 @@ impl fmt::Debug for TStringFlags { .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) + .field("unclosed", &self.is_unclosed()) .finish() } } @@ -1427,6 +1456,9 @@ bitflags! { /// The string was deemed invalid by the parser. const INVALID = 1 << 5; + + /// The string literal misses the matching closing quote(s). + const UNCLOSED = 1 << 6; } } @@ -1479,6 +1511,12 @@ impl StringLiteralFlags { self } + #[must_use] + pub fn with_unclosed(mut self, unclosed: bool) -> Self { + self.0.set(StringLiteralFlagsInner::UNCLOSED, unclosed); + self + } + #[must_use] pub fn with_prefix(self, prefix: StringLiteralPrefix) -> Self { let StringLiteralFlags(flags) = self; @@ -1560,6 +1598,10 @@ impl StringFlags for StringLiteralFlags { fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Regular(self.prefix()) } + + fn is_unclosed(self) -> bool { + self.0.intersects(StringLiteralFlagsInner::UNCLOSED) + } } impl fmt::Debug for StringLiteralFlags { @@ -1568,6 +1610,7 @@ impl fmt::Debug for StringLiteralFlags { .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) + .field("unclosed", &self.is_unclosed()) .finish() } } @@ -1846,6 +1889,9 @@ bitflags! { /// The bytestring was deemed invalid by the parser. const INVALID = 1 << 4; + + /// The byte string misses the matching closing quote(s). + const UNCLOSED = 1 << 5; } } @@ -1897,6 +1943,12 @@ impl BytesLiteralFlags { self } + #[must_use] + pub fn with_unclosed(mut self, unclosed: bool) -> Self { + self.0.set(BytesLiteralFlagsInner::UNCLOSED, unclosed); + self + } + #[must_use] pub fn with_prefix(mut self, prefix: ByteStringPrefix) -> Self { match prefix { @@ -1959,6 +2011,10 @@ impl StringFlags for BytesLiteralFlags { fn prefix(self) -> AnyStringPrefix { AnyStringPrefix::Bytes(self.prefix()) } + + fn is_unclosed(self) -> bool { + self.0.intersects(BytesLiteralFlagsInner::UNCLOSED) + } } impl fmt::Debug for BytesLiteralFlags { @@ -1967,6 +2023,7 @@ impl fmt::Debug for BytesLiteralFlags { .field("quote_style", &self.quote_style()) .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) + .field("unclosed", &self.is_unclosed()) .finish() } } @@ -2028,7 +2085,7 @@ bitflags! { /// prefix flags is by calling the `as_flags()` method on the /// `StringPrefix` enum. #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] - struct AnyStringFlagsInner: u8 { + struct AnyStringFlagsInner: u16 { /// The string uses double quotes (`"`). /// If this flag is not set, the string uses single quotes (`'`). const DOUBLE = 1 << 0; @@ -2071,6 +2128,9 @@ bitflags! { /// for why we track the casing of the `r` prefix, /// but not for any other prefix const R_PREFIX_UPPER = 1 << 7; + + /// String without matching closing quote(s). + const UNCLOSED = 1 << 8; } } @@ -2166,6 +2226,12 @@ impl AnyStringFlags { .set(AnyStringFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes()); self } + + #[must_use] + pub fn with_unclosed(mut self, unclosed: bool) -> Self { + self.0.set(AnyStringFlagsInner::UNCLOSED, unclosed); + self + } } impl StringFlags for AnyStringFlags { @@ -2234,6 +2300,10 @@ impl StringFlags for AnyStringFlags { } AnyStringPrefix::Regular(StringLiteralPrefix::Empty) } + + fn is_unclosed(self) -> bool { + self.0.intersects(AnyStringFlagsInner::UNCLOSED) + } } impl fmt::Debug for AnyStringFlags { @@ -2242,6 +2312,7 @@ impl fmt::Debug for AnyStringFlags { .field("prefix", &self.prefix()) .field("triple_quoted", &self.is_triple_quoted()) .field("quote_style", &self.quote_style()) + .field("unclosed", &self.is_unclosed()) .finish() } } @@ -2258,6 +2329,7 @@ impl From for StringLiteralFlags { .with_quote_style(value.quote_style()) .with_prefix(prefix) .with_triple_quotes(value.triple_quotes()) + .with_unclosed(value.is_unclosed()) } } @@ -2279,6 +2351,7 @@ impl From for BytesLiteralFlags { .with_quote_style(value.quote_style()) .with_prefix(bytestring_prefix) .with_triple_quotes(value.triple_quotes()) + .with_unclosed(value.is_unclosed()) } } @@ -2300,6 +2373,7 @@ impl From for FStringFlags { .with_quote_style(value.quote_style()) .with_prefix(prefix) .with_triple_quotes(value.triple_quotes()) + .with_unclosed(value.is_unclosed()) } } @@ -2321,6 +2395,7 @@ impl From for TStringFlags { .with_quote_style(value.quote_style()) .with_prefix(prefix) .with_triple_quotes(value.triple_quotes()) + .with_unclosed(value.is_unclosed()) } } diff --git a/crates/ruff_python_parser/src/lexer.rs b/crates/ruff_python_parser/src/lexer.rs index ca58e72bec..dc864d71b6 100644 --- a/crates/ruff_python_parser/src/lexer.rs +++ b/crates/ruff_python_parser/src/lexer.rs @@ -13,6 +13,7 @@ use unicode_ident::{is_xid_continue, is_xid_start}; use unicode_normalization::UnicodeNormalization; use ruff_python_ast::name::Name; +use ruff_python_ast::str_prefix::{AnyStringPrefix, StringLiteralPrefix}; use ruff_python_ast::{Int, IpyEscapeKind, StringFlags}; use ruff_python_trivia::is_python_whitespace; use ruff_text_size::{TextLen, TextRange, TextSize}; @@ -24,6 +25,7 @@ use crate::lexer::indentation::{Indentation, Indentations, IndentationsCheckpoin use crate::lexer::interpolated_string::{ InterpolatedStringContext, InterpolatedStrings, InterpolatedStringsCheckpoint, }; +use crate::string::InterpolatedStringKind; use crate::token::{TokenFlags, TokenKind, TokenValue}; mod cursor; @@ -782,6 +784,7 @@ impl<'src> Lexer<'src> { // SAFETY: Safe because the function is only called when `self.fstrings` is not empty. let interpolated_string = self.interpolated_strings.current().unwrap(); let string_kind = interpolated_string.kind(); + let interpolated_flags = interpolated_string.flags(); // Check if we're at the end of the f-string. if interpolated_string.is_triple_quoted() { @@ -819,15 +822,19 @@ impl<'src> Lexer<'src> { } else { InterpolatedStringErrorType::UnterminatedString }; + + self.nesting = interpolated_string.nesting(); self.interpolated_strings.pop(); - return Some(self.push_error(LexicalError::new( + self.current_flags |= TokenFlags::UNCLOSED_STRING; + self.push_error(LexicalError::new( LexicalErrorType::from_interpolated_string_error(error, string_kind), self.token_range(), - ))); + )); + + break; } '\n' | '\r' if !interpolated_string.is_triple_quoted() => { // https://github.com/astral-sh/ruff/issues/18632 - self.interpolated_strings.pop(); let error_type = if in_format_spec { InterpolatedStringErrorType::NewlineInFormatSpec @@ -835,10 +842,16 @@ impl<'src> Lexer<'src> { InterpolatedStringErrorType::UnterminatedString }; - return Some(self.push_error(LexicalError::new( + self.nesting = interpolated_string.nesting(); + self.interpolated_strings.pop(); + self.current_flags |= TokenFlags::UNCLOSED_STRING; + + self.push_error(LexicalError::new( LexicalErrorType::from_interpolated_string_error(error_type, string_kind), self.token_range(), - ))); + )); + + break; } '\\' => { self.cursor.bump(); // '\' @@ -913,7 +926,7 @@ impl<'src> Lexer<'src> { self.current_value = TokenValue::InterpolatedStringMiddle(value.into_boxed_str()); - self.current_flags = interpolated_string.flags(); + self.current_flags = interpolated_flags; Some(string_kind.middle_token()) } @@ -942,10 +955,12 @@ impl<'src> Lexer<'src> { let Some(index) = memchr::memchr(quote_byte, self.cursor.rest().as_bytes()) else { self.cursor.skip_to_end(); - return self.push_error(LexicalError::new( + self.current_flags |= TokenFlags::UNCLOSED_STRING; + self.push_error(LexicalError::new( LexicalErrorType::UnclosedStringError, self.token_range(), )); + break self.offset(); }; // Rare case: if there are an odd number of backslashes before the quote, then @@ -977,11 +992,14 @@ impl<'src> Lexer<'src> { memchr::memchr3(quote_byte, b'\r', b'\n', self.cursor.rest().as_bytes()) else { self.cursor.skip_to_end(); + self.current_flags |= TokenFlags::UNCLOSED_STRING; - return self.push_error(LexicalError::new( - LexicalErrorType::StringError, + self.push_error(LexicalError::new( + LexicalErrorType::UnclosedStringError, self.token_range(), )); + + break self.offset(); }; // Rare case: if there are an odd number of backslashes before the quote, then @@ -1009,10 +1027,12 @@ impl<'src> Lexer<'src> { match quote_or_newline { '\r' | '\n' => { - return self.push_error(LexicalError::new( + self.current_flags |= TokenFlags::UNCLOSED_STRING; + self.push_error(LexicalError::new( LexicalErrorType::UnclosedStringError, self.token_range(), )); + break self.offset(); } ch if ch == quote => { let value_end = self.offset(); @@ -1331,7 +1351,20 @@ impl<'src> Lexer<'src> { fn consume_end(&mut self) -> TokenKind { // We reached end of file. - // First of all, we need all nestings to be finished. + + // First, finish any unterminated interpolated-strings. + while let Some(interpolated_string) = self.interpolated_strings.pop() { + self.nesting = interpolated_string.nesting(); + self.push_error(LexicalError::new( + LexicalErrorType::from_interpolated_string_error( + InterpolatedStringErrorType::UnterminatedString, + interpolated_string.kind(), + ), + self.token_range(), + )); + } + + // Second, finish all nestings. // For Mode::ParenthesizedExpression we start with nesting level 1. // So we check if we end with that level. let init_nesting = u32::from(self.mode == Mode::ParenthesizedExpression); @@ -1459,6 +1492,107 @@ impl<'src> Lexer<'src> { true } + /// Re-lexes an unclosed string token in the context of an interpolated string element. + /// + /// ```py + /// f'{a' + /// ``` + /// + /// This method re-lexes the trailing `'` as the end of the f-string rather than the + /// start of a new string token for better error recovery. + pub(crate) fn re_lex_string_token_in_interpolation_element( + &mut self, + kind: InterpolatedStringKind, + ) { + let Some(interpolated_string) = self.interpolated_strings.current() else { + return; + }; + + let current_string_flags = self.current_flags().as_any_string_flags(); + + // Only unclosed strings, that have the same quote character + if !matches!(self.current_kind, TokenKind::String) + || !self.current_flags.is_unclosed() + || current_string_flags.prefix() != AnyStringPrefix::Regular(StringLiteralPrefix::Empty) + || current_string_flags.quote_style().as_char() != interpolated_string.quote_char() + || current_string_flags.is_triple_quoted() != interpolated_string.is_triple_quoted() + { + return; + } + + // Only if the string's first line only contains whitespace, + // or ends in a comment (not `f"{"abc`) + let first_line = &self.source + [(self.current_range.start() + current_string_flags.quote_len()).to_usize()..]; + + for c in first_line.chars() { + if matches!(c, '\n' | '\r' | '#') { + break; + } + + // `f'{'ab`, we want to parse `ab` as a normal string and not the closing element of the f-string + if !is_python_whitespace(c) { + return; + } + } + + if self.errors.last().is_some_and(|error| { + error.location() == self.current_range + && matches!(error.error(), LexicalErrorType::UnclosedStringError) + }) { + self.errors.pop(); + } + + self.current_range = + TextRange::at(self.current_range.start(), self.current_flags.quote_len()); + self.current_kind = kind.end_token(); + self.current_value = TokenValue::None; + self.current_flags = TokenFlags::empty(); + + self.nesting = interpolated_string.nesting(); + self.interpolated_strings.pop(); + + self.cursor = Cursor::new(self.source); + self.cursor.skip_bytes(self.current_range.end().to_usize()); + } + + /// Re-lex `r"` in a format specifier position. + /// + /// `r"` in a format specifier position is unlikely to be the start of a raw string. + /// Instead, it's the format specifier `!r` followed by the closing quote of the f-string, + /// when the `}` is missing. + /// + /// ```py + /// f"{test!r" + /// ``` + /// + /// This function re-lexes the `r"` as `r` (a name token). The next `next_token` call will + /// return a unclosed string token for `"`, which [`Self::re_lex_string_token_in_interpolation_element`] + /// can then re-lex as the end of the f-string. + pub(crate) fn re_lex_raw_string_in_format_spec(&mut self) { + // Re-lex `r"` as `NAME r` followed by an unclosed string + // `f"{test!r"` -> `f"{test!`, `r`, `"` + if matches!(self.current_kind, TokenKind::String) + && self.current_flags.is_unclosed() + && self.current_flags.prefix() + == AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false }) + { + if self.errors.last().is_some_and(|error| { + error.location() == self.current_range + && matches!(error.error(), LexicalErrorType::UnclosedStringError) + }) { + self.errors.pop(); + } + + self.current_range = TextRange::at(self.current_range.start(), 'r'.text_len()); + self.current_kind = TokenKind::Name; + self.current_value = TokenValue::Name(Name::new_static("r")); + self.current_flags = TokenFlags::empty(); + self.cursor = Cursor::new(self.source); + self.cursor.skip_bytes(self.current_range.end().to_usize()); + } + } + #[inline] fn token_range(&self) -> TextRange { let end = self.offset(); @@ -2739,6 +2873,164 @@ t"{(lambda x:{x})}" } } + #[test] + fn lex_fstring_unclosed() { + let source = r#"f"hello"#; + + assert_snapshot!(lex_invalid(source, Mode::Module), @r#" + ## Tokens + ``` + [ + ( + FStringStart, + 0..2, + TokenFlags( + DOUBLE_QUOTES | F_STRING, + ), + ), + ( + InterpolatedStringMiddle( + "hello", + ), + 2..7, + TokenFlags( + DOUBLE_QUOTES | F_STRING, + ), + ), + ( + Newline, + 7..7, + ), + ] + ``` + ## Errors + ``` + [ + LexicalError { + error: FStringError( + UnterminatedString, + ), + location: 2..7, + }, + ] + ``` + "#); + } + + #[test] + fn lex_fstring_missing_brace() { + let source = "f'{'"; + + assert_snapshot!(lex_invalid(source, Mode::Module), @r#" + ## Tokens + ``` + [ + ( + FStringStart, + 0..2, + TokenFlags( + F_STRING, + ), + ), + ( + Lbrace, + 2..3, + ), + ( + String( + "", + ), + 3..4, + TokenFlags( + UNCLOSED_STRING, + ), + ), + ( + Newline, + 4..4, + ), + ] + ``` + ## Errors + ``` + [ + LexicalError { + error: UnclosedStringError, + location: 3..4, + }, + LexicalError { + error: FStringError( + UnterminatedString, + ), + location: 4..4, + }, + ] + ``` + "#); + } + + #[test] + fn lex_fstring_missing_brace_after_format_spec() { + let source = r#"f"{foo!r""#; + + assert_snapshot!(lex_invalid(source, Mode::Module), @r#" + ## Tokens + ``` + [ + ( + FStringStart, + 0..2, + TokenFlags( + DOUBLE_QUOTES | F_STRING, + ), + ), + ( + Lbrace, + 2..3, + ), + ( + Name( + Name("foo"), + ), + 3..6, + ), + ( + Exclamation, + 6..7, + ), + ( + String( + "", + ), + 7..9, + TokenFlags( + DOUBLE_QUOTES | RAW_STRING_LOWERCASE | UNCLOSED_STRING, + ), + ), + ( + Newline, + 9..9, + ), + ] + ``` + ## Errors + ``` + [ + LexicalError { + error: UnclosedStringError, + location: 7..9, + }, + LexicalError { + error: FStringError( + UnterminatedString, + ), + location: 9..9, + }, + ] + ``` + "#); + } + #[test] fn test_tstring_error() { use InterpolatedStringErrorType::{ diff --git a/crates/ruff_python_parser/src/parser/expression.rs b/crates/ruff_python_parser/src/parser/expression.rs index d198441895..043de1772c 100644 --- a/crates/ruff_python_parser/src/parser/expression.rs +++ b/crates/ruff_python_parser/src/parser/expression.rs @@ -1526,7 +1526,7 @@ impl<'src> Parser<'src> { kind: InterpolatedStringKind, ) -> InterpolatedStringData { let start = self.node_start(); - let flags = self.tokens.current_flags().as_any_string_flags(); + let mut flags = self.tokens.current_flags().as_any_string_flags(); self.bump(kind.start_token()); let elements = self.parse_interpolated_string_elements( @@ -1535,7 +1535,9 @@ impl<'src> Parser<'src> { kind, ); - self.expect(kind.end_token()); + if !self.expect(kind.end_token()) { + flags = flags.with_unclosed(true); + } // test_ok pep701_f_string_py312 // # parse_options: {"target-version": "3.12"} @@ -1719,6 +1721,9 @@ impl<'src> Parser<'src> { let start = self.node_start(); self.bump(TokenKind::Lbrace); + self.tokens + .re_lex_string_token_in_interpolation_element(string_kind); + // test_err f_string_empty_expression // f"{}" // f"{ }" @@ -1740,6 +1745,7 @@ impl<'src> Parser<'src> { // t"{*}" // t"{*x and y}" // t"{*yield x}" + let value = self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or()); if !value.is_parenthesized && value.expr.is_lambda_expr() { @@ -1773,6 +1779,10 @@ impl<'src> Parser<'src> { }; let conversion = if self.eat(TokenKind::Exclamation) { + // Ensure that the `r` is lexed as a `r` name token instead of a raw string + // in `f{abc!r"` (note the missing `}`). + self.tokens.re_lex_raw_string_in_format_spec(); + let conversion_flag_range = self.current_token_range(); if self.at(TokenKind::Name) { // test_err f_string_conversion_follows_exclamation @@ -1852,6 +1862,9 @@ impl<'src> Parser<'src> { None }; + self.tokens + .re_lex_string_token_in_interpolation_element(string_kind); + // We're using `eat` here instead of `expect` to use the f-string specific error type. if !self.eat(TokenKind::Rbrace) { // TODO(dhruvmanila): This requires some changes in the lexer. One of them diff --git a/crates/ruff_python_parser/src/parser/snapshots/ruff_python_parser__parser__tests__unicode_aliases.snap b/crates/ruff_python_parser/src/parser/snapshots/ruff_python_parser__parser__tests__unicode_aliases.snap index 2e77ece943..08e3e1b4f3 100644 --- a/crates/ruff_python_parser/src/parser/snapshots/ruff_python_parser__parser__tests__unicode_aliases.snap +++ b/crates/ruff_python_parser/src/parser/snapshots/ruff_python_parser__parser__tests__unicode_aliases.snap @@ -31,6 +31,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_newline_format_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_newline_format_spec.snap index 868a705a31..4f6fb2e8cc 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_newline_format_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_newline_format_spec.snap @@ -44,11 +44,16 @@ expression: "lex_invalid(source, Mode::Module)" 12..13, ), ( - Unknown, + InterpolatedStringMiddle( + "d", + ), 13..14, + TokenFlags( + F_STRING, + ), ), ( - NonLogicalNewline, + Newline, 14..15, ), ( @@ -62,8 +67,13 @@ expression: "lex_invalid(source, Mode::Module)" 16..18, ), ( - Unknown, + String( + "", + ), 18..19, + TokenFlags( + UNCLOSED_STRING, + ), ), ( Newline, @@ -104,13 +114,22 @@ expression: "lex_invalid(source, Mode::Module)" 31..32, ), ( - Unknown, + InterpolatedStringMiddle( + "a", + ), 32..33, + TokenFlags( + F_STRING, + ), ), ( - NonLogicalNewline, + Newline, 33..34, ), + ( + Indent, + 34..42, + ), ( Name( Name("b"), @@ -118,9 +137,13 @@ expression: "lex_invalid(source, Mode::Module)" 42..43, ), ( - NonLogicalNewline, + Newline, 43..44, ), + ( + Dedent, + 44..44, + ), ( Rbrace, 44..45, @@ -132,8 +155,13 @@ expression: "lex_invalid(source, Mode::Module)" 45..47, ), ( - Unknown, + String( + "", + ), 47..48, + TokenFlags( + UNCLOSED_STRING, + ), ), ( Newline, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__tstring_newline_format_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__tstring_newline_format_spec.snap index c4db37da4c..810ce6592e 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__tstring_newline_format_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__tstring_newline_format_spec.snap @@ -44,11 +44,16 @@ expression: "lex_invalid(source, Mode::Module)" 12..13, ), ( - Unknown, + InterpolatedStringMiddle( + "d", + ), 13..14, + TokenFlags( + T_STRING, + ), ), ( - NonLogicalNewline, + Newline, 14..15, ), ( @@ -62,8 +67,13 @@ expression: "lex_invalid(source, Mode::Module)" 16..18, ), ( - Unknown, + String( + "", + ), 18..19, + TokenFlags( + UNCLOSED_STRING, + ), ), ( Newline, @@ -104,13 +114,22 @@ expression: "lex_invalid(source, Mode::Module)" 31..32, ), ( - Unknown, + InterpolatedStringMiddle( + "a", + ), 32..33, + TokenFlags( + T_STRING, + ), ), ( - NonLogicalNewline, + Newline, 33..34, ), + ( + Indent, + 34..42, + ), ( Name( Name("b"), @@ -118,9 +137,13 @@ expression: "lex_invalid(source, Mode::Module)" 42..43, ), ( - NonLogicalNewline, + Newline, 43..44, ), + ( + Dedent, + 44..44, + ), ( Rbrace, 44..45, @@ -132,8 +155,13 @@ expression: "lex_invalid(source, Mode::Module)" 45..47, ), ( - Unknown, + String( + "", + ), 47..48, + TokenFlags( + UNCLOSED_STRING, + ), ), ( Newline, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap index 9a734b8be4..c6c8e9cf85 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap index 72fcda7d2a..5c6fd12129 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap index 3f04c6f2d7..56bda12a56 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap index 791588d794..783e8c736e 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap index 2d53ec0f3d..68c017dfc7 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__dont_panic_on_8_in_octal_escape.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__dont_panic_on_8_in_octal_escape.snap index 546f94b9d9..5e04b08423 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__dont_panic_on_8_in_octal_escape.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__dont_panic_on_8_in_octal_escape.snap @@ -31,6 +31,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap index 687ce16e1d..0b61a51378 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap @@ -278,6 +278,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap index 2cec840d0a..e271519126 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap index e0ad6cff1b..36ed21596e 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap @@ -32,6 +32,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap index 80aad9289c..f4f90563ab 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap @@ -27,6 +27,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap index 2067566074..a2121c46f8 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap index ed6a838d4e..a04a2f4118 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap @@ -78,6 +78,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap index 990c1d9dad..c356bd1c08 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap @@ -47,6 +47,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap index 7fbfd50e8e..998a2269ed 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap @@ -47,6 +47,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap index d950371db1..44540b29c3 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap @@ -49,6 +49,7 @@ expression: suite uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap index 2955122167..e1a4f80cca 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap @@ -45,6 +45,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap index dc882a8c57..a6617dd01c 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap @@ -81,6 +81,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap index da86391550..861fc69c1c 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap @@ -59,6 +59,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap index 42fcd75676..0e871901fc 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap @@ -47,6 +47,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap index cdf45c0397..392be7a93c 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_fstring.snap index f865593fb2..db0275af32 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_fstring.snap @@ -22,6 +22,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_tstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_tstring.snap index 98b1fa3461..bfb2d6218a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_tstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_tstring.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap index d539cb8deb..b5a212b25b 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -43,6 +44,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap index d539cb8deb..b5a212b25b 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -43,6 +44,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap index 1193adb2e4..c0997152c4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -56,6 +57,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -72,6 +74,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_4.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_4.snap index 02419e8a00..e9634e20e3 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_4.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_4.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -56,6 +57,7 @@ expression: suite quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -72,6 +74,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -84,6 +87,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap index db72a345e0..7123b8431c 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap @@ -64,6 +64,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_equals.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_equals.snap index 07654a0e22..7a9edf207f 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_equals.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_equals.snap @@ -61,6 +61,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap index 1d80035515..7bfb2a5b22 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap @@ -57,6 +57,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -67,6 +68,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], @@ -91,6 +93,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap index 3ed5dbd04b..f938542df6 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap @@ -64,6 +64,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap index 68960eab25..66f2aecbec 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap @@ -55,6 +55,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -76,6 +77,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_equals.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_equals.snap index f3fa222a17..3ab964282e 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_equals.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_equals.snap @@ -61,6 +61,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap index 2f9be02104..b9a2229626 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap @@ -54,6 +54,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap index e53098fdec..43ce4660a4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap @@ -45,6 +45,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap index 7de32a7c0c..766de86c5f 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap @@ -45,6 +45,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_yield_expr.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_yield_expr.snap index 3154dbeff5..1f59b2a5ba 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_yield_expr.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_yield_expr.snap @@ -39,6 +39,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap index 20b0be9eab..8b7e266d6d 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -33,6 +34,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap index e37ba3eaf0..bbacfc3e4a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Single, prefix: Unicode, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring.snap index 64cb321009..67b4c41365 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring.snap @@ -63,6 +63,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_equals.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_equals.snap index af2754bea4..c7baa8a513 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_equals.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_equals.snap @@ -60,6 +60,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_concatenation_string_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_concatenation_string_spec.snap index bfef44ca1a..93cfa48dd1 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_concatenation_string_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_concatenation_string_spec.snap @@ -56,6 +56,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -66,6 +67,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], @@ -90,6 +92,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_spec.snap index 2432a03fea..70f42c3139 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_spec.snap @@ -63,6 +63,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_string_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_string_spec.snap index 4d167f6391..38b4e902ba 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_string_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_nested_string_spec.snap @@ -54,6 +54,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -75,6 +76,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_equals.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_equals.snap index cda9ac6385..bf1180fe07 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_equals.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_equals.snap @@ -60,6 +60,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_nested_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_nested_spec.snap index 607db4621e..32d1997a5a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_nested_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_not_nested_spec.snap @@ -53,6 +53,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_prec_space.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_prec_space.snap index 82a3532343..102f40910a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_prec_space.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_prec_space.snap @@ -44,6 +44,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_trailing_space.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_trailing_space.snap index 5b44cbb07e..24b1b36cd8 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_trailing_space.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_self_doc_trailing_space.snap @@ -44,6 +44,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_yield_expr.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_yield_expr.snap index 745e1afdf4..b16d33cefb 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_yield_expr.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_tstring_yield_expr.snap @@ -38,6 +38,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap index bfadf93148..ac951c2811 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ), @@ -43,6 +44,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap index 31dcb6c17d..21f69ed5ed 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ), @@ -43,6 +44,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -55,6 +57,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap index 8a8b31c488..6c75165710 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -33,6 +34,7 @@ expression: suite quote_style: Single, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap index 6dd96bc445..aca2fefc21 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap @@ -23,6 +23,7 @@ expression: suite quote_style: Single, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -33,6 +34,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap index d90d77f669..68e5a30fee 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap @@ -28,6 +28,7 @@ expression: suite uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap index 9dc2e32ae2..76ddf8520d 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap @@ -26,6 +26,7 @@ expression: suite uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap index 2454031212..eb8b1a3e6d 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap @@ -42,6 +42,7 @@ expression: suite uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_tstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_tstring.snap index 41f1bac3ab..b97792d742 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_tstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_tstring.snap @@ -41,6 +41,7 @@ expression: suite uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap index b156356ac7..b919928dc5 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap @@ -278,6 +278,7 @@ expression: suite quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_mac_eol.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_mac_eol.snap index c2521fd8ac..4352fb34d4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_mac_eol.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_mac_eol.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_unix_eol.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_unix_eol.snap index c2521fd8ac..4352fb34d4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_unix_eol.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_unix_eol.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_windows_eol.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_windows_eol.snap index b66b5c3738..58ff7730d8 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_windows_eol.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__string_parser_escaped_windows_eol.snap @@ -21,6 +21,7 @@ expression: suite quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap index 3ec5fbae97..8877e5956f 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap @@ -42,6 +42,7 @@ expression: suite uppercase_r: false, }, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_tstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_tstring.snap index bdf91f88e5..4cf02baf48 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_tstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_tstring.snap @@ -41,6 +41,7 @@ expression: suite uppercase_r: false, }, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_constant_range.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_constant_range.snap index 7460cec091..f8825a1412 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_constant_range.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_constant_range.snap @@ -77,6 +77,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_character.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_character.snap index 44d783177f..a10e0fc996 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_character.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_character.snap @@ -46,6 +46,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_newline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_newline.snap index d17834c3b1..071d5af2c4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_newline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_escaped_newline.snap @@ -46,6 +46,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_line_continuation.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_line_continuation.snap index 7a142da726..ae7da0c069 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_line_continuation.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_line_continuation.snap @@ -48,6 +48,7 @@ expression: suite uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base.snap index 81b079ca5e..5169493e0a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base.snap @@ -44,6 +44,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base_more.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base_more.snap index 4af3383006..e9b8a959fc 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base_more.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_base_more.snap @@ -80,6 +80,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_format.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_format.snap index d8970fbf3a..18ce2cfc63 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_format.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_parse_self_documenting_format.snap @@ -58,6 +58,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_unescaped_newline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_unescaped_newline.snap index 19db8fe2e7..2c5a1b47c4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_unescaped_newline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__tstring_unescaped_newline.snap @@ -46,6 +46,7 @@ expression: suite quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/src/token.rs b/crates/ruff_python_parser/src/token.rs index 240e015a3b..1d9461a722 100644 --- a/crates/ruff_python_parser/src/token.rs +++ b/crates/ruff_python_parser/src/token.rs @@ -729,7 +729,7 @@ impl fmt::Display for TokenKind { bitflags! { #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub(crate) struct TokenFlags: u8 { + pub(crate) struct TokenFlags: u16 { /// The token is a string with double quotes (`"`). const DOUBLE_QUOTES = 1 << 0; /// The token is a triple-quoted string i.e., it starts and ends with three consecutive @@ -748,9 +748,12 @@ bitflags! { const RAW_STRING_LOWERCASE = 1 << 6; /// The token is a raw string and the prefix character is in uppercase. const RAW_STRING_UPPERCASE = 1 << 7; + /// String without matching closing quote(s) + const UNCLOSED_STRING = 1 << 8; /// The token is a raw string i.e., prefixed with `r` or `R` const RAW_STRING = Self::RAW_STRING_LOWERCASE.bits() | Self::RAW_STRING_UPPERCASE.bits(); + } } @@ -808,6 +811,10 @@ impl StringFlags for TokenFlags { AnyStringPrefix::Regular(StringLiteralPrefix::Empty) } } + + fn is_unclosed(self) -> bool { + self.intersects(TokenFlags::UNCLOSED_STRING) + } } impl TokenFlags { diff --git a/crates/ruff_python_parser/src/token_source.rs b/crates/ruff_python_parser/src/token_source.rs index 26088c7a12..f24fb4771f 100644 --- a/crates/ruff_python_parser/src/token_source.rs +++ b/crates/ruff_python_parser/src/token_source.rs @@ -3,6 +3,7 @@ use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::Mode; use crate::error::LexicalError; use crate::lexer::{Lexer, LexerCheckpoint}; +use crate::string::InterpolatedStringKind; use crate::token::{Token, TokenFlags, TokenKind, TokenValue}; /// Token source for the parser that skips over any trivia tokens. @@ -88,6 +89,18 @@ impl<'src> TokenSource<'src> { } } + pub(crate) fn re_lex_string_token_in_interpolation_element( + &mut self, + kind: InterpolatedStringKind, + ) { + self.lexer + .re_lex_string_token_in_interpolation_element(kind); + } + + pub(crate) fn re_lex_raw_string_in_format_spec(&mut self) { + self.lexer.re_lex_raw_string_in_format_spec(); + } + /// Returns the next non-trivia token without consuming it. /// /// Use [`peek2`] to get the next two tokens. diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@ann_assign_stmt_invalid_target.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@ann_assign_stmt_invalid_target.py.snap index 74e36dcbca..1e58991d17 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@ann_assign_stmt_invalid_target.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@ann_assign_stmt_invalid_target.py.snap @@ -28,6 +28,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -57,6 +58,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -114,6 +116,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_target.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_target.py.snap index 1085de726c..7516e2d842 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_target.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_target.py.snap @@ -144,6 +144,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -164,6 +165,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -194,6 +196,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -214,6 +217,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@aug_assign_stmt_invalid_target.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@aug_assign_stmt_invalid_target.py.snap index 731d9a3996..0d1311ca25 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@aug_assign_stmt_invalid_target.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@aug_assign_stmt_invalid_target.py.snap @@ -53,6 +53,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -74,6 +75,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@debug_shadow_with.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@debug_shadow_with.py.snap index 0f9a6c4b23..12c0003499 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@debug_shadow_with.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@debug_shadow_with.py.snap @@ -49,6 +49,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_class_attr.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_class_attr.py.snap index 4a2eefcbc8..63067a4b3c 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_class_attr.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_class_attr.py.snap @@ -229,6 +229,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -249,6 +250,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -396,6 +398,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -416,6 +419,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -601,6 +605,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -621,6 +626,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_key.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_key.py.snap index 34974c55b0..aec92ae959 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_key.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@duplicate_match_key.py.snap @@ -45,6 +45,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -65,6 +66,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -147,6 +149,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -169,6 +172,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -663,6 +667,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: true, + unclosed: false, }, }, ), @@ -683,6 +688,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: true, + unclosed: false, }, }, ), @@ -763,6 +769,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -783,6 +790,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -803,6 +811,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -907,6 +916,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -936,6 +946,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1051,6 +1062,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1071,6 +1083,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1203,6 +1216,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1223,6 +1237,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1407,6 +1422,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1427,6 +1443,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__dict__comprehension.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__dict__comprehension.py.snap index 6c72721b03..6b8ee79f05 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__dict__comprehension.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__dict__comprehension.py.snap @@ -105,6 +105,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__list__comprehension.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__list__comprehension.py.snap index 80f0ed10de..480b1586fb 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__list__comprehension.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__list__comprehension.py.snap @@ -140,6 +140,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__set__comprehension.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__set__comprehension.py.snap index 08cad0598c..1ccec2050b 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__set__comprehension.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@expressions__set__comprehension.py.snap @@ -140,6 +140,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_conversion_follows_exclamation.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_conversion_follows_exclamation.py.snap index 0deb7be86a..63c3670334 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_conversion_follows_exclamation.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_conversion_follows_exclamation.py.snap @@ -47,6 +47,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -92,6 +93,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -137,6 +139,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_empty_expression.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_empty_expression.py.snap index b336a9531b..f18251146b 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_empty_expression.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_empty_expression.py.snap @@ -47,6 +47,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -93,6 +94,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_name_tok.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_name_tok.py.snap index acb9c88e02..a5603a2dd3 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_name_tok.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_name_tok.py.snap @@ -47,6 +47,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_other_tok.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_other_tok.py.snap index 28624a678e..f69dee9e5c 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_other_tok.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_conversion_flag_other_tok.py.snap @@ -47,6 +47,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -93,6 +94,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_starred_expr.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_starred_expr.py.snap index a6920bde70..20091bbe02 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_starred_expr.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_invalid_starred_expr.py.snap @@ -54,6 +54,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -124,6 +125,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -185,6 +187,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_lambda_without_parentheses.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_lambda_without_parentheses.py.snap index 2c4c6ee355..b7da154352 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_lambda_without_parentheses.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_lambda_without_parentheses.py.snap @@ -87,6 +87,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace.py.snap index 9f85f5551d..c8b75ce3f9 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace.py.snap @@ -47,6 +47,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -73,7 +74,7 @@ Module( elements: [ Interpolation( InterpolatedElement { - range: 7..14, + range: 7..13, node_index: NodeIndex(None), expression: Name( ExprName { @@ -84,7 +85,7 @@ Module( }, ), debug_text: None, - conversion: None, + conversion: Repr, format_spec: None, }, ), @@ -93,6 +94,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -144,6 +146,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -156,75 +159,91 @@ Module( Expr( StmtExpr { node_index: NodeIndex(None), - range: 24..37, + range: 24..28, value: FString( ExprFString { node_index: NodeIndex(None), - range: 24..37, + range: 24..28, value: FStringValue { - inner: Concatenated( - [ - FString( - FString { - range: 24..28, - node_index: NodeIndex(None), - elements: [ - Interpolation( - InterpolatedElement { - range: 26..27, - node_index: NodeIndex(None), - expression: Name( - ExprName { - node_index: NodeIndex(None), - range: 27..27, - id: Name(""), - ctx: Invalid, - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - flags: FStringFlags { - quote_style: Double, - prefix: Regular, - triple_quoted: false, - }, + inner: Single( + FString( + FString { + range: 24..28, + node_index: NodeIndex(None), + elements: [ + Interpolation( + InterpolatedElement { + range: 26..27, + node_index: NodeIndex(None), + expression: Name( + ExprName { + node_index: NodeIndex(None), + range: 27..27, + id: Name(""), + ctx: Invalid, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + flags: FStringFlags { + quote_style: Double, + prefix: Regular, + triple_quoted: false, + unclosed: false, }, - ), - FString( - FString { - range: 29..37, - node_index: NodeIndex(None), - elements: [ - Interpolation( - InterpolatedElement { - range: 33..34, - node_index: NodeIndex(None), - expression: Name( - ExprName { - node_index: NodeIndex(None), - range: 34..34, - id: Name(""), - ctx: Invalid, - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - flags: FStringFlags { - quote_style: Double, - prefix: Regular, - triple_quoted: true, - }, + }, + ), + ), + }, + }, + ), + }, + ), + Expr( + StmtExpr { + node_index: NodeIndex(None), + range: 29..37, + value: FString( + ExprFString { + node_index: NodeIndex(None), + range: 29..37, + value: FStringValue { + inner: Single( + FString( + FString { + range: 29..37, + node_index: NodeIndex(None), + elements: [ + Interpolation( + InterpolatedElement { + range: 33..34, + node_index: NodeIndex(None), + expression: Name( + ExprName { + node_index: NodeIndex(None), + range: 34..34, + id: Name(""), + ctx: Invalid, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + flags: FStringFlags { + quote_style: Double, + prefix: Regular, + triple_quoted: true, + unclosed: false, }, - ), - ], + }, + ), ), }, }, @@ -239,23 +258,7 @@ Module( | 1 | f"{" - | ^ Syntax Error: missing closing quote in string literal -2 | f"{foo!r" -3 | f"{foo=" - | - - - | -1 | f"{" - | ^ Syntax Error: f-string: unterminated string -2 | f"{foo!r" -3 | f"{foo=" - | - - - | -1 | f"{" - | ^ Syntax Error: f-string: unterminated string + | ^ Syntax Error: Expected an expression 2 | f"{foo!r" 3 | f"{foo=" | @@ -264,25 +267,7 @@ Module( | 1 | f"{" 2 | f"{foo!r" - | ^^ Syntax Error: missing closing quote in string literal -3 | f"{foo=" -4 | f"{" - | - - - | -1 | f"{" -2 | f"{foo!r" - | ^ Syntax Error: f-string: unterminated string -3 | f"{foo=" -4 | f"{" - | - - - | -1 | f"{" -2 | f"{foo!r" - | ^ Syntax Error: f-string: unterminated string + | ^ Syntax Error: f-string: expecting '}' 3 | f"{foo=" 4 | f"{" | @@ -292,46 +277,7 @@ Module( 1 | f"{" 2 | f"{foo!r" 3 | f"{foo=" - | ^^ Syntax Error: f-string: expecting '}' -4 | f"{" -5 | f"""{""" - | - - - | -1 | f"{" -2 | f"{foo!r" - | ^ Syntax Error: Expected FStringEnd, found Unknown -3 | f"{foo=" -4 | f"{" - | - - - | -1 | f"{" -2 | f"{foo!r" -3 | f"{foo=" - | ^ Syntax Error: missing closing quote in string literal -4 | f"{" -5 | f"""{""" - | - - - | -1 | f"{" -2 | f"{foo!r" -3 | f"{foo=" - | ^ Syntax Error: f-string: unterminated string -4 | f"{" -5 | f"""{""" - | - - - | -1 | f"{" -2 | f"{foo!r" -3 | f"{foo=" - | ^ Syntax Error: f-string: unterminated string + | ^ Syntax Error: f-string: expecting '}' 4 | f"{" 5 | f"""{""" | @@ -341,36 +287,14 @@ Module( 2 | f"{foo!r" 3 | f"{foo=" 4 | f"{" - | ^ Syntax Error: missing closing quote in string literal + | ^ Syntax Error: Expected an expression 5 | f"""{""" | - | -3 | f"{foo=" -4 | f"{" -5 | f"""{""" - | ^^^^ Syntax Error: Expected FStringEnd, found FStringStart - | - - | 3 | f"{foo=" 4 | f"{" 5 | f"""{""" | ^^^ Syntax Error: Expected an expression | - - - | -4 | f"{" -5 | f"""{""" - | ^ Syntax Error: unexpected EOF while parsing - | - - - | -4 | f"{" -5 | f"""{""" - | ^ Syntax Error: f-string: unterminated string - | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace_in_format_spec.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace_in_format_spec.py.snap index 796a9745ea..cf843119c2 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace_in_format_spec.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@f_string_unclosed_lbrace_in_format_spec.py.snap @@ -60,6 +60,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -127,6 +128,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@for_stmt_invalid_target.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@for_stmt_invalid_target.py.snap index 2ee9ae9293..04caa94916 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@for_stmt_invalid_target.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@for_stmt_invalid_target.py.snap @@ -68,6 +68,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -388,6 +389,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string.py.snap index a883b9e411..7dd649dafd 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string.py.snap @@ -13,22 +13,39 @@ Module( Expr( StmtExpr { node_index: NodeIndex(None), - range: 0..7, + range: 0..14, value: StringLiteral( ExprStringLiteral { node_index: NodeIndex(None), - range: 0..7, + range: 0..14, value: StringLiteralValue { - inner: Single( - StringLiteral { - range: 0..7, - node_index: NodeIndex(None), - value: "hello", - flags: StringLiteralFlags { - quote_style: Single, - prefix: Empty, - triple_quoted: false, - }, + inner: Concatenated( + ConcatenatedStringLiteral { + strings: [ + StringLiteral { + range: 0..7, + node_index: NodeIndex(None), + value: "hello", + flags: StringLiteralFlags { + quote_style: Single, + prefix: Empty, + triple_quoted: false, + unclosed: false, + }, + }, + StringLiteral { + range: 8..14, + node_index: NodeIndex(None), + value: "world", + flags: StringLiteralFlags { + quote_style: Single, + prefix: Empty, + triple_quoted: false, + unclosed: true, + }, + }, + ], + value: "helloworld", }, ), }, @@ -87,6 +104,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -124,6 +142,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -179,15 +198,6 @@ Module( | - | -1 | 'hello' 'world - | ^ Syntax Error: Expected a statement -2 | 1 + 1 -3 | 'hello' f'world {x} -4 | 2 + 2 - | - - | 1 | 'hello' 'world 2 | 1 + 1 diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string_multiline.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string_multiline.py.snap index 58734d3b8f..6d6ae6f83c 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string_multiline.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@implicitly_concatenated_unterminated_string_multiline.py.snap @@ -30,6 +30,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -67,6 +68,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -111,59 +113,62 @@ Module( Expr( StmtExpr { node_index: NodeIndex(None), - range: 38..51, - value: StringLiteral( - ExprStringLiteral { - node_index: NodeIndex(None), - range: 44..51, - value: StringLiteralValue { - inner: Single( - StringLiteral { - range: 44..51, - node_index: NodeIndex(None), - value: "first", - flags: StringLiteralFlags { - quote_style: Single, - prefix: Empty, - triple_quoted: false, - }, - }, - ), - }, - }, - ), - }, - ), - Expr( - StmtExpr { - node_index: NodeIndex(None), - range: 68..76, + range: 38..78, value: FString( ExprFString { node_index: NodeIndex(None), - range: 68..76, + range: 44..76, value: FStringValue { - inner: Single( - FString( - FString { - range: 68..76, - node_index: NodeIndex(None), - elements: [ - Literal( - InterpolatedStringLiteralElement { - range: 70..75, - node_index: NodeIndex(None), - value: "third", - }, - ), - ], - flags: FStringFlags { - quote_style: Single, - prefix: Regular, - triple_quoted: false, + inner: Concatenated( + [ + Literal( + StringLiteral { + range: 44..51, + node_index: NodeIndex(None), + value: "first", + flags: StringLiteralFlags { + quote_style: Single, + prefix: Empty, + triple_quoted: false, + unclosed: false, + }, }, - }, - ), + ), + Literal( + StringLiteral { + range: 56..63, + node_index: NodeIndex(None), + value: "second", + flags: StringLiteralFlags { + quote_style: Single, + prefix: Empty, + triple_quoted: false, + unclosed: true, + }, + }, + ), + FString( + FString { + range: 68..76, + node_index: NodeIndex(None), + elements: [ + Literal( + InterpolatedStringLiteralElement { + range: 70..75, + node_index: NodeIndex(None), + value: "third", + }, + ), + ], + flags: FStringFlags { + quote_style: Single, + prefix: Regular, + triple_quoted: false, + unclosed: false, + }, + }, + ), + ], ), }, }, @@ -246,21 +251,3 @@ Module( 9 | f'third' 10 | ) | - - - | - 8 | 'second - 9 | f'third' -10 | ) - | ^ Syntax Error: Expected a statement -11 | 2 + 2 - | - - - | - 8 | 'second - 9 | f'third' -10 | ) - | ^ Syntax Error: Expected a statement -11 | 2 + 2 - | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_byte_literal.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_byte_literal.py.snap index 635e860d01..a330b1ce96 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_byte_literal.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_byte_literal.py.snap @@ -28,6 +28,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -56,6 +57,7 @@ Module( uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), @@ -82,6 +84,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_del_target.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_del_target.py.snap index f214888ea3..5834d7311a 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_del_target.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_del_target.py.snap @@ -68,6 +68,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -115,6 +116,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -135,6 +137,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -204,6 +207,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_fstring_literal_element.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_fstring_literal_element.py.snap index 88875b56f9..0d2f651c21 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_fstring_literal_element.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_fstring_literal_element.py.snap @@ -37,6 +37,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -73,6 +74,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_string_literal.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_string_literal.py.snap index 0dbe2ee507..72cdf3cf6a 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_string_literal.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_string_literal.py.snap @@ -28,6 +28,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -54,6 +55,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@mixed_bytes_and_non_bytes_literals.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@mixed_bytes_and_non_bytes_literals.py.snap index f79a6c0478..6ac75db9d5 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@mixed_bytes_and_non_bytes_literals.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@mixed_bytes_and_non_bytes_literals.py.snap @@ -30,6 +30,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -40,6 +41,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], @@ -79,6 +81,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -91,6 +94,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -121,6 +125,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -141,6 +146,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -153,6 +159,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@params_var_keyword_with_default.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@params_var_keyword_with_default.py.snap index 85f48fc80f..3a8644b3a8 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@params_var_keyword_with_default.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@params_var_keyword_with_default.py.snap @@ -85,6 +85,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -118,6 +119,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@pep701_f_string_py311.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@pep701_f_string_py311.py.snap index 0361caff9b..0551f2e991 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@pep701_f_string_py311.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@pep701_f_string_py311.py.snap @@ -62,6 +62,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -81,6 +82,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -131,6 +133,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -172,6 +175,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -233,6 +237,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -252,6 +257,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -390,6 +396,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -407,6 +414,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -424,6 +432,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -441,6 +450,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -458,6 +468,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -475,6 +486,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -532,6 +544,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -555,6 +568,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -579,6 +593,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -639,6 +654,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -700,6 +716,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -717,6 +734,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -767,6 +785,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -804,6 +823,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -824,6 +844,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -844,6 +865,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -869,6 +891,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lex_logical_token.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lex_logical_token.py.snap index 5864cb2b05..45a5b27c78 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lex_logical_token.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lex_logical_token.py.snap @@ -581,7 +581,7 @@ Module( test: Call( ExprCall { node_index: NodeIndex(None), - range: 890..905, + range: 890..906, func: Name( ExprName { node_index: NodeIndex(None), @@ -591,7 +591,7 @@ Module( }, ), arguments: Arguments { - range: 894..905, + range: 894..906, node_index: NodeIndex(None), args: [ FString( @@ -634,6 +634,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -713,11 +714,20 @@ Module( FString { range: 944..951, node_index: NodeIndex(None), - elements: [], + elements: [ + Literal( + InterpolatedStringLiteralElement { + range: 946..951, + node_index: NodeIndex(None), + value: "hello", + }, + ), + ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -888,7 +898,7 @@ Module( | 49 | # F-strings uses normal list parsing, so test those as well 50 | if call(f"hello {x - | ^ Syntax Error: Expected FStringEnd, found Unknown + | ^ Syntax Error: Expected FStringEnd, found NonLogicalNewline 51 | def bar(): 52 | pass | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__fstring_format_spec_1.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__fstring_format_spec_1.py.snap index b14f005e9c..1e2ad65fcf 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__fstring_format_spec_1.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__fstring_format_spec_1.py.snap @@ -50,6 +50,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -80,6 +81,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -117,6 +119,33 @@ Module( ), }, ), + Expr( + StmtExpr { + node_index: NodeIndex(None), + range: 203..205, + value: StringLiteral( + ExprStringLiteral { + node_index: NodeIndex(None), + range: 203..205, + value: StringLiteralValue { + inner: Single( + StringLiteral { + range: 203..205, + node_index: NodeIndex(None), + value: "}", + flags: StringLiteralFlags { + quote_style: Single, + prefix: Empty, + triple_quoted: false, + unclosed: true, + }, + }, + ), + }, + }, + ), + }, + ), Expr( StmtExpr { node_index: NodeIndex(None), @@ -157,6 +186,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -169,7 +199,15 @@ Module( InterpolatedStringFormatSpec { range: 226..228, node_index: NodeIndex(None), - elements: [], + elements: [ + Literal( + InterpolatedStringLiteralElement { + range: 226..228, + node_index: NodeIndex(None), + value: "\\", + }, + ), + ], }, ), }, @@ -179,6 +217,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -206,6 +245,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -254,6 +294,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -284,6 +325,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -321,6 +363,33 @@ Module( ), }, ), + Expr( + StmtExpr { + node_index: NodeIndex(None), + range: 296..298, + value: StringLiteral( + ExprStringLiteral { + node_index: NodeIndex(None), + range: 296..298, + value: StringLiteralValue { + inner: Single( + StringLiteral { + range: 296..298, + node_index: NodeIndex(None), + value: "}", + flags: StringLiteralFlags { + quote_style: Single, + prefix: Empty, + triple_quoted: false, + unclosed: true, + }, + }, + ), + }, + }, + ), + }, + ), ], }, ) @@ -363,16 +432,6 @@ Module( | - | -5 | f'middle {'string':\ -6 | 'format spec'} - | ^ Syntax Error: Expected a statement -7 | -8 | f'middle {'string':\\ -9 | 'format spec'} - | - - | 6 | 'format spec'} 7 | @@ -454,12 +513,5 @@ Module( | 11 | f'middle {'string':\\\ 12 | 'format spec'} - | ^^ Syntax Error: Got unexpected string - | - - - | -11 | f'middle {'string':\\\ -12 | 'format spec'} - | ^ Syntax Error: Expected a statement + | ^^ Syntax Error: missing closing quote in string literal | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_1.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_1.py.snap index 81e700a1d2..1a9af6dacc 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_1.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_1.py.snap @@ -54,6 +54,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: true, }, }, ), @@ -92,7 +93,7 @@ Module( 5 | f"""hello {x # comment | ___________________________^ 6 | | y = 1 - | |_____^ Syntax Error: Expected FStringEnd, found Unknown + | |_____^ Syntax Error: Expected FStringEnd, found FStringMiddle | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_2.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_2.py.snap index 599be8b78d..50bb114c7e 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_2.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_2.py.snap @@ -61,6 +61,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_3.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_3.py.snap index ce80ab0705..174ebceee4 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_3.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@re_lexing__triple_quoted_fstring_3.py.snap @@ -77,6 +77,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_assignment_targets.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_assignment_targets.py.snap index 6920a94c53..cdf7785101 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_assignment_targets.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_assignment_targets.py.snap @@ -382,6 +382,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -915,6 +916,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -996,6 +998,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1034,6 +1037,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1075,6 +1079,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_augmented_assignment_target.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_augmented_assignment_target.py.snap index 1ac04383c5..66bb515f10 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_augmented_assignment_target.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@statements__invalid_augmented_assignment_target.py.snap @@ -289,6 +289,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -811,6 +812,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -891,6 +893,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -928,6 +931,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -968,6 +972,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_empty_expression.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_empty_expression.py.snap index e1c3d47bda..de21eac870 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_empty_expression.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_empty_expression.py.snap @@ -46,6 +46,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -90,6 +91,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_name_tok.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_name_tok.py.snap index 6b648bae65..b1b3890a11 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_name_tok.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_name_tok.py.snap @@ -46,6 +46,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_other_tok.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_other_tok.py.snap index 9c937acac3..ef9242f4f8 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_other_tok.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_conversion_flag_other_tok.py.snap @@ -46,6 +46,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -90,6 +91,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_starred_expr.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_starred_expr.py.snap index 592c6eedce..d906c8c837 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_starred_expr.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_invalid_starred_expr.py.snap @@ -53,6 +53,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -121,6 +122,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -180,6 +182,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_lambda_without_parentheses.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_lambda_without_parentheses.py.snap index d0d8abdfd3..0d23f0c0d2 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_lambda_without_parentheses.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_lambda_without_parentheses.py.snap @@ -86,6 +86,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace.py.snap index 4218d6845d..4ff0a7d78f 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace.py.snap @@ -46,6 +46,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -70,7 +71,7 @@ Module( elements: [ Interpolation( InterpolatedElement { - range: 51..58, + range: 51..57, node_index: NodeIndex(None), expression: Name( ExprName { @@ -81,7 +82,7 @@ Module( }, ), debug_text: None, - conversion: None, + conversion: Repr, format_spec: None, }, ), @@ -90,6 +91,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -139,6 +141,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -150,71 +153,87 @@ Module( Expr( StmtExpr { node_index: NodeIndex(None), - range: 68..81, + range: 68..72, value: TString( ExprTString { node_index: NodeIndex(None), - range: 68..81, + range: 68..72, value: TStringValue { - inner: Concatenated( - [ - TString { - range: 68..72, - node_index: NodeIndex(None), - elements: [ - Interpolation( - InterpolatedElement { - range: 70..71, - node_index: NodeIndex(None), - expression: Name( - ExprName { - node_index: NodeIndex(None), - range: 71..71, - id: Name(""), - ctx: Invalid, - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - flags: TStringFlags { - quote_style: Double, - prefix: Regular, - triple_quoted: false, - }, + inner: Single( + TString { + range: 68..72, + node_index: NodeIndex(None), + elements: [ + Interpolation( + InterpolatedElement { + range: 70..71, + node_index: NodeIndex(None), + expression: Name( + ExprName { + node_index: NodeIndex(None), + range: 71..71, + id: Name(""), + ctx: Invalid, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + flags: TStringFlags { + quote_style: Double, + prefix: Regular, + triple_quoted: false, + unclosed: false, }, - TString { - range: 73..81, - node_index: NodeIndex(None), - elements: [ - Interpolation( - InterpolatedElement { - range: 77..78, - node_index: NodeIndex(None), - expression: Name( - ExprName { - node_index: NodeIndex(None), - range: 78..78, - id: Name(""), - ctx: Invalid, - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - flags: TStringFlags { - quote_style: Double, - prefix: Regular, - triple_quoted: true, - }, + }, + ), + }, + }, + ), + }, + ), + Expr( + StmtExpr { + node_index: NodeIndex(None), + range: 73..81, + value: TString( + ExprTString { + node_index: NodeIndex(None), + range: 73..81, + value: TStringValue { + inner: Single( + TString { + range: 73..81, + node_index: NodeIndex(None), + elements: [ + Interpolation( + InterpolatedElement { + range: 77..78, + node_index: NodeIndex(None), + expression: Name( + ExprName { + node_index: NodeIndex(None), + range: 78..78, + id: Name(""), + ctx: Invalid, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + flags: TStringFlags { + quote_style: Double, + prefix: Regular, + triple_quoted: true, + unclosed: false, }, - ], + }, ), }, }, @@ -230,25 +249,7 @@ Module( | 1 | # parse_options: {"target-version": "3.14"} 2 | t"{" - | ^ Syntax Error: missing closing quote in string literal -3 | t"{foo!r" -4 | t"{foo=" - | - - - | -1 | # parse_options: {"target-version": "3.14"} -2 | t"{" - | ^ Syntax Error: t-string: unterminated string -3 | t"{foo!r" -4 | t"{foo=" - | - - - | -1 | # parse_options: {"target-version": "3.14"} -2 | t"{" - | ^ Syntax Error: t-string: unterminated string + | ^ Syntax Error: Expected an expression 3 | t"{foo!r" 4 | t"{foo=" | @@ -258,27 +259,7 @@ Module( 1 | # parse_options: {"target-version": "3.14"} 2 | t"{" 3 | t"{foo!r" - | ^^ Syntax Error: missing closing quote in string literal -4 | t"{foo=" -5 | t"{" - | - - - | -1 | # parse_options: {"target-version": "3.14"} -2 | t"{" -3 | t"{foo!r" - | ^ Syntax Error: t-string: unterminated string -4 | t"{foo=" -5 | t"{" - | - - - | -1 | # parse_options: {"target-version": "3.14"} -2 | t"{" -3 | t"{foo!r" - | ^ Syntax Error: t-string: unterminated string + | ^ Syntax Error: t-string: expecting '}' 4 | t"{foo=" 5 | t"{" | @@ -288,47 +269,7 @@ Module( 2 | t"{" 3 | t"{foo!r" 4 | t"{foo=" - | ^^ Syntax Error: t-string: expecting '}' -5 | t"{" -6 | t"""{""" - | - - - | -1 | # parse_options: {"target-version": "3.14"} -2 | t"{" -3 | t"{foo!r" - | ^ Syntax Error: Expected TStringEnd, found Unknown -4 | t"{foo=" -5 | t"{" - | - - - | -2 | t"{" -3 | t"{foo!r" -4 | t"{foo=" - | ^ Syntax Error: missing closing quote in string literal -5 | t"{" -6 | t"""{""" - | - - - | -2 | t"{" -3 | t"{foo!r" -4 | t"{foo=" - | ^ Syntax Error: t-string: unterminated string -5 | t"{" -6 | t"""{""" - | - - - | -2 | t"{" -3 | t"{foo!r" -4 | t"{foo=" - | ^ Syntax Error: t-string: unterminated string + | ^ Syntax Error: t-string: expecting '}' 5 | t"{" 6 | t"""{""" | @@ -338,36 +279,14 @@ Module( 3 | t"{foo!r" 4 | t"{foo=" 5 | t"{" - | ^ Syntax Error: missing closing quote in string literal + | ^ Syntax Error: Expected an expression 6 | t"""{""" | - | -4 | t"{foo=" -5 | t"{" -6 | t"""{""" - | ^^^^ Syntax Error: Expected TStringEnd, found TStringStart - | - - | 4 | t"{foo=" 5 | t"{" 6 | t"""{""" | ^^^ Syntax Error: Expected an expression | - - - | -5 | t"{" -6 | t"""{""" - | ^ Syntax Error: unexpected EOF while parsing - | - - - | -5 | t"{" -6 | t"""{""" - | ^ Syntax Error: t-string: unterminated string - | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace_in_format_spec.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace_in_format_spec.py.snap index 3a002658cc..bc20f6172c 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace_in_format_spec.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@t_string_unclosed_lbrace_in_format_spec.py.snap @@ -59,6 +59,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -124,6 +125,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@template_strings_py313.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@template_strings_py313.py.snap index b631879119..1eed668827 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@template_strings_py313.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@template_strings_py313.py.snap @@ -46,6 +46,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -90,6 +91,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -124,6 +126,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@unterminated_fstring_newline_recovery.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@unterminated_fstring_newline_recovery.py.snap index 096671b850..0595f124f2 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@unterminated_fstring_newline_recovery.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@unterminated_fstring_newline_recovery.py.snap @@ -24,11 +24,20 @@ Module( FString { range: 0..7, node_index: NodeIndex(None), - elements: [], + elements: [ + Literal( + InterpolatedStringLiteralElement { + range: 2..7, + node_index: NodeIndex(None), + value: "hello", + }, + ), + ], flags: FStringFlags { quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -113,6 +122,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -203,6 +213,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -287,6 +298,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: true, }, }, ), @@ -374,9 +386,10 @@ Module( 1 | f"hello 2 | 1 + 1 3 | f"hello {x - | ^ Syntax Error: Expected FStringEnd, found Unknown + | ^ Syntax Error: Expected FStringEnd, found newline 4 | 2 + 2 5 | f"hello {x: +6 | 3 + 3 | diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@decorator_expression_eval_hack_py38.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@decorator_expression_eval_hack_py38.py.snap index d6d40d9536..fb3322b7a7 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@decorator_expression_eval_hack_py38.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@decorator_expression_eval_hack_py38.py.snap @@ -49,6 +49,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__call.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__call.py.snap index 452c617b2e..5f931e1947 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__call.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__call.py.snap @@ -606,6 +606,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary.py.snap index 8ff7bb7782..1eef98686d 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary.py.snap @@ -136,6 +136,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -411,6 +412,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -474,6 +476,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -739,6 +742,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -760,6 +764,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -794,6 +799,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -815,6 +821,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -881,6 +888,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -902,6 +910,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary_comprehension.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary_comprehension.py.snap index cf7709bd98..5046336486 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary_comprehension.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary_comprehension.py.snap @@ -181,6 +181,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__f_string.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__f_string.py.snap index adc0020609..e696d1c34a 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__f_string.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__f_string.py.snap @@ -29,6 +29,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -57,6 +58,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -85,6 +87,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -113,6 +116,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -141,6 +145,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -183,6 +188,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -199,6 +205,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -245,6 +252,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -302,6 +310,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -375,6 +384,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -437,6 +447,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -465,6 +476,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -527,6 +539,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -555,6 +568,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -606,6 +620,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -671,6 +686,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -722,6 +738,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -793,6 +810,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -874,6 +892,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -905,6 +924,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -941,6 +961,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1000,6 +1021,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1012,6 +1034,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1070,6 +1093,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1111,6 +1135,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -1121,6 +1146,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], @@ -1227,6 +1253,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1263,6 +1290,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1323,6 +1351,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -1374,6 +1403,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1482,6 +1512,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1607,6 +1638,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1674,6 +1706,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1777,6 +1810,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1864,6 +1898,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1915,6 +1950,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1966,6 +2002,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2017,6 +2054,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2077,6 +2115,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2142,6 +2181,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2202,6 +2242,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2231,6 +2272,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2261,6 +2303,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2309,6 +2352,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2339,6 +2383,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2387,6 +2432,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2399,6 +2445,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2478,6 +2525,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2507,6 +2555,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2537,6 +2586,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2549,6 +2599,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2587,6 +2638,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2607,6 +2659,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2619,6 +2672,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2641,6 +2695,7 @@ Module( uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), @@ -2663,6 +2718,7 @@ Module( uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ), @@ -2693,6 +2749,7 @@ Module( quote_style: Double, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ), @@ -2723,6 +2780,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2735,6 +2793,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2747,6 +2806,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2777,6 +2837,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2807,6 +2868,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2819,6 +2881,7 @@ Module( quote_style: Double, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ), @@ -2831,6 +2894,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2861,6 +2925,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2891,6 +2956,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2903,6 +2969,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2915,6 +2982,7 @@ Module( quote_style: Double, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ), @@ -2945,6 +3013,7 @@ Module( quote_style: Double, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ), @@ -2989,6 +3058,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -3001,6 +3071,7 @@ Module( quote_style: Double, prefix: Unicode, triple_quoted: false, + unclosed: false, }, }, ), @@ -3013,6 +3084,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__generator.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__generator.py.snap index 6dcaa77c6b..da4fe251d0 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__generator.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__generator.py.snap @@ -616,6 +616,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -693,6 +694,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -748,6 +750,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__string.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__string.py.snap index e03b149d1a..0f376fd490 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__string.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__string.py.snap @@ -28,6 +28,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -54,6 +55,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -82,6 +84,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -92,6 +95,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], @@ -123,6 +127,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -133,6 +138,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -143,6 +149,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], @@ -172,6 +179,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: true, + unclosed: false, }, }, ), @@ -198,6 +206,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: true, + unclosed: false, }, }, ), @@ -226,6 +235,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: true, + unclosed: false, }, }, StringLiteral { @@ -236,6 +246,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: true, + unclosed: false, }, }, ], @@ -277,6 +288,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -310,6 +322,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, BytesLiteral { @@ -333,6 +346,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ], diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__t_string.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__t_string.py.snap index 2233e19dc5..0896a3ae47 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__t_string.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__t_string.py.snap @@ -28,6 +28,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -54,6 +55,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -80,6 +82,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -106,6 +109,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -132,6 +136,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -172,6 +177,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -188,6 +194,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -232,6 +239,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -287,6 +295,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -358,6 +367,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -418,6 +428,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -446,6 +457,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -506,6 +518,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -534,6 +547,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -583,6 +597,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -646,6 +661,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -695,6 +711,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -764,6 +781,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -842,6 +860,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -872,6 +891,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -914,6 +934,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -971,6 +992,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -989,6 +1011,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ], @@ -1046,6 +1069,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1087,6 +1111,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, StringLiteral { @@ -1097,6 +1122,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ], @@ -1202,6 +1228,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1236,6 +1263,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1294,6 +1322,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -1343,6 +1372,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1449,6 +1479,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1572,6 +1603,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1637,6 +1669,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1738,6 +1771,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1823,6 +1857,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1872,6 +1907,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1921,6 +1957,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1970,6 +2007,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2028,6 +2066,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2091,6 +2130,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2149,6 +2189,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2184,6 +2225,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2212,6 +2254,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ], @@ -2258,6 +2301,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2286,6 +2330,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ], @@ -2332,6 +2377,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2350,6 +2396,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ], @@ -2427,6 +2474,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2462,6 +2510,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2490,6 +2539,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2508,6 +2558,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ], @@ -2544,6 +2595,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2562,6 +2614,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2580,6 +2633,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2600,6 +2654,7 @@ Module( uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, TString { @@ -2620,6 +2675,7 @@ Module( uppercase_r: false, }, triple_quoted: false, + unclosed: false, }, }, ], @@ -2694,6 +2750,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2710,6 +2767,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2727,6 +2785,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@fstring_format_spec_terminator.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@fstring_format_spec_terminator.py.snap index 331e7ba86f..d3a6103ce0 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@fstring_format_spec_terminator.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@fstring_format_spec_terminator.py.snap @@ -67,6 +67,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -141,6 +142,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@match_classify_as_keyword_1.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@match_classify_as_keyword_1.py.snap index 7c83386b60..e7e54f42bb 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@match_classify_as_keyword_1.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@match_classify_as_keyword_1.py.snap @@ -204,6 +204,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -285,6 +286,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@param_with_star_annotation_py310.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@param_with_star_annotation_py310.py.snap index d411155da7..3213ff7743 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@param_with_star_annotation_py310.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@param_with_star_annotation_py310.py.snap @@ -157,6 +157,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -255,6 +256,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py311.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py311.py.snap index 581693aa41..4b294d49ea 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py311.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py311.py.snap @@ -50,6 +50,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -66,6 +67,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -134,6 +136,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -162,6 +165,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -234,6 +238,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -250,6 +255,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -267,6 +273,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -284,6 +291,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -420,6 +428,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -444,6 +453,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -461,6 +471,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -485,6 +496,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -545,6 +557,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -581,6 +594,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py312.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py312.py.snap index 6fb97c216e..91ec761efa 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py312.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep701_f_string_py312.py.snap @@ -62,6 +62,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -81,6 +82,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -131,6 +133,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -172,6 +175,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -233,6 +237,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -252,6 +257,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -390,6 +396,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -407,6 +414,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -424,6 +432,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -441,6 +450,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -458,6 +468,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -475,6 +486,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -532,6 +544,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -555,6 +568,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -579,6 +593,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -639,6 +654,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep750_t_string_py314.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep750_t_string_py314.py.snap index 6c656364a8..0d5db2d14d 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep750_t_string_py314.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@pep750_t_string_py314.py.snap @@ -61,6 +61,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -80,6 +81,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -128,6 +130,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -169,6 +172,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -228,6 +232,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -247,6 +252,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -378,6 +384,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -394,6 +401,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -410,6 +418,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -426,6 +435,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -442,6 +452,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -458,6 +469,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -512,6 +524,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -535,6 +548,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ), @@ -558,6 +572,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -616,6 +631,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@single_parenthesized_item_context_manager_py38.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@single_parenthesized_item_context_manager_py38.py.snap index f2ab2b6c7b..09e2f6d782 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@single_parenthesized_item_context_manager_py38.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@single_parenthesized_item_context_manager_py38.py.snap @@ -49,6 +49,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -127,6 +128,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__ambiguous_lpar_with_items.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__ambiguous_lpar_with_items.py.snap index 8e048cdfb7..5e948486b8 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__ambiguous_lpar_with_items.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__ambiguous_lpar_with_items.py.snap @@ -1131,6 +1131,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1214,6 +1215,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -2720,6 +2722,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2766,6 +2769,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assert.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assert.py.snap index b3cb2bc013..ae3131d0c1 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assert.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assert.py.snap @@ -237,6 +237,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap index 852bb10a83..7239c8b530 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap @@ -855,6 +855,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__class.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__class.py.snap index 981e0fe0de..29935b6485 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__class.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__class.py.snap @@ -423,6 +423,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__function.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__function.py.snap index e715f81366..0ecafb822d 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__function.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__function.py.snap @@ -3642,6 +3642,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__match.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__match.py.snap index f98896f399..e10babe037 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__match.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__match.py.snap @@ -593,6 +593,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -637,6 +638,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -980,6 +982,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1826,6 +1829,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2893,6 +2897,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -2954,6 +2959,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -3672,6 +3678,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -4333,6 +4340,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -4380,6 +4388,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -4486,6 +4495,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -4507,6 +4517,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -4540,6 +4551,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -5292,6 +5304,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -5337,6 +5350,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -5771,6 +5785,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -7745,6 +7760,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__try.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__try.py.snap index 962d435263..6aae2f4228 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__try.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__try.py.snap @@ -715,6 +715,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -835,6 +836,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -898,6 +900,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -1183,6 +1186,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1339,6 +1343,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -1394,6 +1399,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__type.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__type.py.snap index d12ea97256..608679f328 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__type.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__type.py.snap @@ -111,6 +111,7 @@ Module( quote_style: Double, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__while.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__while.py.snap index ca6b03c547..211ddf7e05 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__while.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__while.py.snap @@ -188,6 +188,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), @@ -237,6 +238,7 @@ Module( quote_style: Single, prefix: Empty, triple_quoted: false, + unclosed: false, }, }, ), diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@template_strings_py314.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@template_strings_py314.py.snap index dda530ea46..e714e59451 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@template_strings_py314.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@template_strings_py314.py.snap @@ -46,6 +46,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -90,6 +91,7 @@ Module( quote_style: Single, prefix: Regular, triple_quoted: false, + unclosed: false, }, }, ), @@ -124,6 +126,7 @@ Module( quote_style: Double, prefix: Regular, triple_quoted: true, + unclosed: false, }, }, ),