diff --git a/crates/ruff_linter/resources/test/fixtures/pycodestyle/W291.py b/crates/ruff_linter/resources/test/fixtures/pycodestyle/W291.py index 4ccbd43194..5217672d52 100644 --- a/crates/ruff_linter/resources/test/fixtures/pycodestyle/W291.py +++ b/crates/ruff_linter/resources/test/fixtures/pycodestyle/W291.py @@ -1,2 +1,15 @@ '''trailing whitespace inside a multiline string''' + +f'''trailing whitespace +inside a multiline f-string''' + +# Trailing whitespace after `{` +f'abc { + 1 + 2 +}' + +# Trailing whitespace after `2` +f'abc { + 1 + 2 +}' diff --git a/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs b/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs index 95b9b25366..c2c7e0428d 100644 --- a/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs +++ b/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs @@ -221,6 +221,7 @@ pub(crate) fn avoidable_escaped_quote( Tok::FStringMiddle { value: string_contents, is_raw, + triple_quoted: _, } if !is_raw => { let Some(context) = fstrings.last_mut() else { continue; @@ -361,6 +362,7 @@ pub(crate) fn unnecessary_escaped_quote( Tok::FStringMiddle { value: string_contents, is_raw, + triple_quoted: _, } if !is_raw => { let Some(context) = fstrings.last_mut() else { continue; diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs index 77a3d6ba62..c227c536c7 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs @@ -67,7 +67,7 @@ pub(crate) fn invalid_escape_sequence( token_range: TextRange, ) { let (token_source_code, string_start_location) = match token { - Tok::FStringMiddle { value, is_raw } => { + Tok::FStringMiddle { value, is_raw, .. } => { if *is_raw { return; } diff --git a/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__W291_W291.py.snap b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__W291_W291.py.snap index 441da19697..44f7a2f7ae 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__W291_W291.py.snap +++ b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__W291_W291.py.snap @@ -13,5 +13,65 @@ W291.py:1:23: W291 [*] Trailing whitespace 1 |-'''trailing whitespace 1 |+'''trailing whitespace 2 2 | inside a multiline string''' +3 3 | +4 4 | f'''trailing whitespace + +W291.py:4:24: W291 [*] Trailing whitespace + | +2 | inside a multiline string''' +3 | +4 | f'''trailing whitespace + | ^ W291 +5 | inside a multiline f-string''' + | + = help: Remove trailing whitespace + +ℹ Unsafe fix +1 1 | '''trailing whitespace +2 2 | inside a multiline string''' +3 3 | +4 |-f'''trailing whitespace + 4 |+f'''trailing whitespace +5 5 | inside a multiline f-string''' +6 6 | +7 7 | # Trailing whitespace after `{` + +W291.py:8:8: W291 [*] Trailing whitespace + | + 7 | # Trailing whitespace after `{` + 8 | f'abc { + | ^ W291 + 9 | 1 + 2 +10 | }' + | + = help: Remove trailing whitespace + +ℹ Safe fix +5 5 | inside a multiline f-string''' +6 6 | +7 7 | # Trailing whitespace after `{` +8 |-f'abc { + 8 |+f'abc { +9 9 | 1 + 2 +10 10 | }' +11 11 | + +W291.py:14:10: W291 [*] Trailing whitespace + | +12 | # Trailing whitespace after `2` +13 | f'abc { +14 | 1 + 2 + | ^ W291 +15 | }' + | + = help: Remove trailing whitespace + +ℹ Safe fix +11 11 | +12 12 | # Trailing whitespace after `2` +13 13 | f'abc { +14 |- 1 + 2 + 14 |+ 1 + 2 +15 15 | }' diff --git a/crates/ruff_python_index/src/multiline_ranges.rs b/crates/ruff_python_index/src/multiline_ranges.rs index 3461211e3d..1a41a4e009 100644 --- a/crates/ruff_python_index/src/multiline_ranges.rs +++ b/crates/ruff_python_index/src/multiline_ranges.rs @@ -46,7 +46,8 @@ pub(crate) struct MultilineRangesBuilder { impl MultilineRangesBuilder { pub(crate) fn visit_token(&mut self, token: &Tok, range: TextRange) { - if let Tok::String { triple_quoted, .. } = token { + if let Tok::String { triple_quoted, .. } | Tok::FStringMiddle { triple_quoted, .. } = token + { if *triple_quoted { self.ranges.push(range); } diff --git a/crates/ruff_python_parser/src/lexer.rs b/crates/ruff_python_parser/src/lexer.rs index 517dd4b441..694d769b90 100644 --- a/crates/ruff_python_parser/src/lexer.rs +++ b/crates/ruff_python_parser/src/lexer.rs @@ -675,6 +675,7 @@ impl<'source> Lexer<'source> { Ok(Some(Tok::FStringMiddle { value, is_raw: fstring.is_raw_string(), + triple_quoted: fstring.is_triple_quoted(), })) } diff --git a/crates/ruff_python_parser/src/python.lalrpop b/crates/ruff_python_parser/src/python.lalrpop index aa87fcd72d..cc9bf71e8a 100644 --- a/crates/ruff_python_parser/src/python.lalrpop +++ b/crates/ruff_python_parser/src/python.lalrpop @@ -1622,7 +1622,7 @@ FStringExpr: StringType = { FStringMiddlePattern: ast::FStringElement = { FStringReplacementField, =>? { - let (source, is_raw) = fstring_middle; + let (source, is_raw, _) = fstring_middle; Ok(parse_fstring_literal_element(&source, is_raw, (location..end_location).into())?) } }; @@ -2067,7 +2067,8 @@ extern { }, fstring_middle => token::Tok::FStringMiddle { value: , - is_raw: + is_raw: , + triple_quoted: }, name => token::Tok::Name { name: }, ipy_escape_command => token::Tok::IpyEscapeCommand { diff --git a/crates/ruff_python_parser/src/python.rs b/crates/ruff_python_parser/src/python.rs index 5771d7099f..c409f91eee 100644 --- a/crates/ruff_python_parser/src/python.rs +++ b/crates/ruff_python_parser/src/python.rs @@ -1,5 +1,5 @@ // auto-generated: "lalrpop 0.20.0" -// sha3: 031689e389556292d9dbd8a1b1ff8ca29bac76d83f1b345630481d620b89e1c2 +// sha3: aa0540221d25f4eadfc9e043fb4fc631d537b672b8a96785dfec2407e0524b79 use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_python_ast::{self as ast, Int, IpyEscapeKind}; use crate::{ @@ -50,7 +50,7 @@ mod __parse__Top { Variant0(token::Tok), Variant1((f64, f64)), Variant2(f64), - Variant3((String, bool)), + Variant3((String, bool, bool)), Variant4(Int), Variant5((IpyEscapeKind, String)), Variant6(String), @@ -151,7 +151,7 @@ mod __parse__Top { Variant101(ast::TypeParams), Variant102(core::option::Option), Variant103(ast::UnaryOp), - Variant104(core::option::Option<(String, bool)>), + Variant104(core::option::Option<(String, bool, bool)>), } const __ACTION: &[i16] = &[ // State 0 @@ -6090,7 +6090,7 @@ mod __parse__Top { token::Tok::StartModule if true => Some(93), token::Tok::Complex { real: _, imag: _ } if true => Some(94), token::Tok::Float { value: _ } if true => Some(95), - token::Tok::FStringMiddle { value: _, is_raw: _ } if true => Some(96), + token::Tok::FStringMiddle { value: _, is_raw: _, triple_quoted: _ } if true => Some(96), token::Tok::Int { value: _ } if true => Some(97), token::Tok::IpyEscapeCommand { kind: _, value: _ } if true => Some(98), token::Tok::Name { name: _ } if true => Some(99), @@ -6116,7 +6116,7 @@ mod __parse__Top { _ => unreachable!(), }, 96 => match __token { - token::Tok::FStringMiddle { value: __tok0, is_raw: __tok1 } if true => __Symbol::Variant3((__tok0, __tok1)), + token::Tok::FStringMiddle { value: __tok0, is_raw: __tok1, triple_quoted: __tok2 } if true => __Symbol::Variant3((__tok0, __tok1, __tok2)), _ => unreachable!(), }, 97 => match __token { @@ -18386,7 +18386,7 @@ mod __parse__Top { fn __pop_Variant3< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, (String, bool), TextSize) + ) -> (TextSize, (String, bool, bool), TextSize) { match __symbols.pop() { Some((__l, __Symbol::Variant3(__v), __r)) => (__l, __v, __r), @@ -19136,7 +19136,7 @@ mod __parse__Top { fn __pop_Variant104< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option<(String, bool)>, TextSize) + ) -> (TextSize, core::option::Option<(String, bool, bool)>, TextSize) { match __symbols.pop() { Some((__l, __Symbol::Variant104(__v), __r)) => (__l, __v, __r), @@ -35910,7 +35910,7 @@ fn __action184< (_, parameters, _): (TextSize, core::option::Option, TextSize), (_, end_location_args, _): (TextSize, TextSize, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, fstring_middle, _): (TextSize, core::option::Option<(String, bool)>, TextSize), + (_, fstring_middle, _): (TextSize, core::option::Option<(String, bool, bool)>, TextSize), (_, body, _): (TextSize, crate::parser::ParenthesizedExpr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> Result> @@ -36413,12 +36413,12 @@ fn __action220< source_code: &str, mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, fstring_middle, _): (TextSize, (String, bool), TextSize), + (_, fstring_middle, _): (TextSize, (String, bool, bool), TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> Result> { { - let (source, is_raw) = fstring_middle; + let (source, is_raw, _) = fstring_middle; Ok(parse_fstring_literal_element(&source, is_raw, (location..end_location).into())?) } } @@ -37357,8 +37357,8 @@ fn __action281< >( source_code: &str, mode: Mode, - (_, __0, _): (TextSize, (String, bool), TextSize), -) -> core::option::Option<(String, bool)> + (_, __0, _): (TextSize, (String, bool, bool), TextSize), +) -> core::option::Option<(String, bool, bool)> { Some(__0) } @@ -37371,7 +37371,7 @@ fn __action282< mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option<(String, bool)> +) -> core::option::Option<(String, bool, bool)> { None } @@ -48505,7 +48505,7 @@ fn __action804< >( source_code: &str, mode: Mode, - __0: (TextSize, (String, bool), TextSize), + __0: (TextSize, (String, bool, bool), TextSize), __1: (TextSize, TextSize, TextSize), ) -> Result> { @@ -49609,7 +49609,7 @@ fn __action839< __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, TextSize, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, core::option::Option<(String, bool)>, TextSize), + __4: (TextSize, core::option::Option<(String, bool, bool)>, TextSize), __5: (TextSize, crate::parser::ParenthesizedExpr, TextSize), __6: (TextSize, TextSize, TextSize), ) -> Result> @@ -64527,7 +64527,7 @@ fn __action1315< >( source_code: &str, mode: Mode, - __0: (TextSize, (String, bool), TextSize), + __0: (TextSize, (String, bool, bool), TextSize), ) -> Result> { let __start0 = __0.2; @@ -65430,7 +65430,7 @@ fn __action1347< __0: (TextSize, token::Tok, TextSize), __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, core::option::Option<(String, bool)>, TextSize), + __3: (TextSize, core::option::Option<(String, bool, bool)>, TextSize), __4: (TextSize, crate::parser::ParenthesizedExpr, TextSize), ) -> Result> { @@ -77662,7 +77662,7 @@ fn __action1727< __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Parameters, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, core::option::Option<(String, bool)>, TextSize), + __3: (TextSize, core::option::Option<(String, bool, bool)>, TextSize), __4: (TextSize, crate::parser::ParenthesizedExpr, TextSize), ) -> Result> { @@ -77693,7 +77693,7 @@ fn __action1728< mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option<(String, bool)>, TextSize), + __2: (TextSize, core::option::Option<(String, bool, bool)>, TextSize), __3: (TextSize, crate::parser::ParenthesizedExpr, TextSize), ) -> Result> { @@ -79598,7 +79598,7 @@ fn __action1785< __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Parameters, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, (String, bool), TextSize), + __3: (TextSize, (String, bool, bool), TextSize), __4: (TextSize, crate::parser::ParenthesizedExpr, TextSize), ) -> Result> { @@ -79661,7 +79661,7 @@ fn __action1787< mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, (String, bool), TextSize), + __2: (TextSize, (String, bool, bool), TextSize), __3: (TextSize, crate::parser::ParenthesizedExpr, TextSize), ) -> Result> { diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring.snap index cc415cb5cc..1be56bef6d 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "normal ", is_raw: false, + triple_quoted: false, }, 2..9, ), @@ -32,6 +33,7 @@ expression: lex_source(source) FStringMiddle { value: " {another} ", is_raw: false, + triple_quoted: false, }, 14..27, ), @@ -53,6 +55,7 @@ expression: lex_source(source) FStringMiddle { value: " {", is_raw: false, + triple_quoted: false, }, 32..35, ), @@ -74,6 +77,7 @@ expression: lex_source(source) FStringMiddle { value: "}", is_raw: false, + triple_quoted: false, }, 42..44, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_comments.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_comments.snap index b0427ad58f..18df4c9ef4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_comments.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_comments.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\n# not a comment ", is_raw: false, + triple_quoted: true, }, 4..21, ), @@ -46,6 +47,7 @@ expression: lex_source(source) FStringMiddle { value: " # not a comment\n", is_raw: false, + triple_quoted: true, }, 42..59, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_conversion.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_conversion.snap index d52a177288..d8665e4779 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_conversion.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_conversion.snap @@ -35,6 +35,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 7..8, ), @@ -70,6 +71,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 14..15, ), @@ -91,6 +93,7 @@ expression: lex_source(source) FStringMiddle { value: ".3f!r", is_raw: false, + triple_quoted: false, }, 18..23, ), @@ -102,6 +105,7 @@ expression: lex_source(source) FStringMiddle { value: " {x!r}", is_raw: false, + triple_quoted: false, }, 24..32, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape.snap index 886c384db2..97f56a70d4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\\", is_raw: false, + triple_quoted: false, }, 2..3, ), @@ -32,6 +33,7 @@ expression: lex_source(source) FStringMiddle { value: "\\\"\\", is_raw: false, + triple_quoted: false, }, 6..9, ), @@ -57,6 +59,7 @@ expression: lex_source(source) FStringMiddle { value: " \\\"\\\"\\\n end", is_raw: false, + triple_quoted: false, }, 13..24, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_braces.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_braces.snap index d0d44618e0..97abf50916 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_braces.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_braces.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\\", is_raw: false, + triple_quoted: false, }, 2..3, ), @@ -40,6 +41,7 @@ expression: lex_source(source) FStringMiddle { value: "\\\\", is_raw: false, + triple_quoted: false, }, 12..14, ), @@ -69,6 +71,7 @@ expression: lex_source(source) FStringMiddle { value: "\\{foo}", is_raw: false, + triple_quoted: false, }, 23..31, ), @@ -84,6 +87,7 @@ expression: lex_source(source) FStringMiddle { value: "\\\\{foo}", is_raw: false, + triple_quoted: false, }, 35..44, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_raw.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_raw.snap index b5ee34faa8..9d9b88d370 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_raw.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_escape_raw.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\\", is_raw: true, + triple_quoted: false, }, 3..4, ), @@ -32,6 +33,7 @@ expression: lex_source(source) FStringMiddle { value: "\\\"\\", is_raw: true, + triple_quoted: false, }, 7..10, ), @@ -57,6 +59,7 @@ expression: lex_source(source) FStringMiddle { value: " \\\"\\\"\\\n end", is_raw: true, + triple_quoted: false, }, 14..25, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_expression_multiline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_expression_multiline.snap index e6f6703a3c..e6c8e91d6a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_expression_multiline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_expression_multiline.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "first ", is_raw: false, + triple_quoted: false, }, 2..8, ), @@ -58,6 +59,7 @@ expression: lex_source(source) FStringMiddle { value: " second", is_raw: false, + triple_quoted: false, }, 41..48, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_multiline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_multiline.snap index 0b89f0e51d..4eeb53420a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_multiline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_multiline.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\nhello\n world\n", is_raw: false, + triple_quoted: true, }, 4..21, ), @@ -26,6 +27,7 @@ expression: lex_source(source) FStringMiddle { value: "\n world\nhello\n", is_raw: false, + triple_quoted: true, }, 29..46, ), @@ -41,6 +43,7 @@ expression: lex_source(source) FStringMiddle { value: "some ", is_raw: false, + triple_quoted: false, }, 52..57, ), @@ -56,6 +59,7 @@ expression: lex_source(source) FStringMiddle { value: "multiline\nallowed ", is_raw: false, + triple_quoted: true, }, 62..80, ), @@ -85,6 +89,7 @@ expression: lex_source(source) FStringMiddle { value: " string", is_raw: false, + triple_quoted: false, }, 87..94, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode.snap index 0a9392ee7d..f089764742 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\\N{BULLET} normal \\Nope \\N", is_raw: false, + triple_quoted: false, }, 2..28, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode_raw.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode_raw.snap index f80b8761c6..de2a27e092 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode_raw.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_named_unicode_raw.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\\N", is_raw: true, + triple_quoted: false, }, 3..5, ), @@ -32,6 +33,7 @@ expression: lex_source(source) FStringMiddle { value: " normal", is_raw: true, + triple_quoted: false, }, 13..20, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_nested.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_nested.snap index 7a4191cd63..a06b6f2be9 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_nested.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_nested.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "foo ", is_raw: false, + triple_quoted: false, }, 2..6, ), @@ -26,6 +27,7 @@ expression: lex_source(source) FStringMiddle { value: "bar ", is_raw: false, + triple_quoted: false, }, 9..13, ), @@ -81,6 +83,7 @@ expression: lex_source(source) FStringMiddle { value: " baz", is_raw: false, + triple_quoted: false, }, 29..33, ), @@ -96,6 +99,7 @@ expression: lex_source(source) FStringMiddle { value: "foo ", is_raw: false, + triple_quoted: false, }, 37..41, ), @@ -111,6 +115,7 @@ expression: lex_source(source) FStringMiddle { value: "bar", is_raw: false, + triple_quoted: false, }, 44..47, ), @@ -126,6 +131,7 @@ expression: lex_source(source) FStringMiddle { value: " some ", is_raw: false, + triple_quoted: false, }, 49..55, ), @@ -141,6 +147,7 @@ expression: lex_source(source) FStringMiddle { value: "another", is_raw: false, + triple_quoted: false, }, 58..65, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_parentheses.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_parentheses.snap index 1e4b829ac9..3d88dfd7a4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_parentheses.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_parentheses.snap @@ -27,6 +27,7 @@ expression: lex_source(source) FStringMiddle { value: "{}", is_raw: false, + triple_quoted: false, }, 8..12, ), @@ -42,6 +43,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 16..17, ), @@ -65,6 +67,7 @@ expression: lex_source(source) FStringMiddle { value: "{", is_raw: false, + triple_quoted: false, }, 23..25, ), @@ -80,6 +83,7 @@ expression: lex_source(source) FStringMiddle { value: "}", is_raw: false, + triple_quoted: false, }, 27..29, ), @@ -95,6 +99,7 @@ expression: lex_source(source) FStringMiddle { value: "{{}}", is_raw: false, + triple_quoted: false, }, 33..41, ), @@ -110,6 +115,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 45..46, ), @@ -125,6 +131,7 @@ expression: lex_source(source) FStringMiddle { value: " {} {", is_raw: false, + triple_quoted: false, }, 48..56, ), @@ -140,6 +147,7 @@ expression: lex_source(source) FStringMiddle { value: "} {{}} ", is_raw: false, + triple_quoted: false, }, 58..71, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_mac_eol.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_mac_eol.snap index c955bded5f..ccd7a72187 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_mac_eol.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_mac_eol.snap @@ -11,6 +11,7 @@ expression: fstring_single_quote_escape_eol(MAC_EOL) FStringMiddle { value: "text \\\r more text", is_raw: false, + triple_quoted: false, }, 2..19, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_unix_eol.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_unix_eol.snap index 0b30f70577..a0686308bc 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_unix_eol.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_unix_eol.snap @@ -11,6 +11,7 @@ expression: fstring_single_quote_escape_eol(UNIX_EOL) FStringMiddle { value: "text \\\n more text", is_raw: false, + triple_quoted: false, }, 2..19, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_windows_eol.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_windows_eol.snap index e7b88d9f94..07ab82564a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_windows_eol.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_single_quote_escape_windows_eol.snap @@ -11,6 +11,7 @@ expression: fstring_single_quote_escape_eol(WINDOWS_EOL) FStringMiddle { value: "text \\\r\n more text", is_raw: false, + triple_quoted: false, }, 2..20, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_format_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_format_spec.snap index db324bdef0..5c0d3cc150 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_format_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_format_spec.snap @@ -29,6 +29,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 8..9, ), @@ -64,6 +65,7 @@ expression: lex_source(source) FStringMiddle { value: ".3f", is_raw: false, + triple_quoted: false, }, 15..18, ), @@ -75,6 +77,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 19..20, ), @@ -96,6 +99,7 @@ expression: lex_source(source) FStringMiddle { value: ".", is_raw: false, + triple_quoted: false, }, 23..24, ), @@ -117,6 +121,7 @@ expression: lex_source(source) FStringMiddle { value: "f", is_raw: false, + triple_quoted: false, }, 27..28, ), @@ -128,6 +133,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 29..30, ), @@ -151,6 +157,7 @@ expression: lex_source(source) FStringMiddle { value: "*^", is_raw: false, + triple_quoted: false, }, 34..36, ), @@ -194,6 +201,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 44..45, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_ipy_escape_command.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_ipy_escape_command.snap index 89911851aa..a29c962cde 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_ipy_escape_command.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_ipy_escape_command.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "foo ", is_raw: false, + triple_quoted: false, }, 2..6, ), @@ -36,6 +37,7 @@ expression: lex_source(source) FStringMiddle { value: " bar", is_raw: false, + triple_quoted: false, }, 12..16, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_multiline_format_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_multiline_format_spec.snap index 6cab3fb5a5..0b2627b52f 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_multiline_format_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_multiline_format_spec.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: true, }, 4..6, ), @@ -36,6 +37,7 @@ expression: lex_source(source) FStringMiddle { value: "d\n", is_raw: false, + triple_quoted: true, }, 14..16, ), @@ -47,6 +49,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: true, }, 17..19, ), @@ -66,6 +69,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: true, }, 27..29, ), @@ -91,6 +95,7 @@ expression: lex_source(source) FStringMiddle { value: "a\n b\n c\n", is_raw: false, + triple_quoted: true, }, 37..61, ), @@ -102,6 +107,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: true, }, 62..64, ), @@ -121,6 +127,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: false, }, 70..72, ), @@ -146,6 +153,7 @@ expression: lex_source(source) FStringMiddle { value: "d", is_raw: false, + triple_quoted: false, }, 80..81, ), @@ -161,6 +169,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: false, }, 83..85, ), @@ -180,6 +189,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: false, }, 89..91, ), @@ -205,6 +215,7 @@ expression: lex_source(source) FStringMiddle { value: "a", is_raw: false, + triple_quoted: false, }, 99..100, ), @@ -230,6 +241,7 @@ expression: lex_source(source) FStringMiddle { value: "__", is_raw: false, + triple_quoted: false, }, 112..114, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_named_expression.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_named_expression.snap index aa551e4d73..30facd70fa 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_named_expression.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_named_expression.snap @@ -25,6 +25,7 @@ expression: lex_source(source) FStringMiddle { value: "=10", is_raw: false, + triple_quoted: false, }, 5..8, ), @@ -36,6 +37,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 9..10, ), @@ -75,6 +77,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 19..20, ), @@ -124,6 +127,7 @@ expression: lex_source(source) FStringMiddle { value: " ", is_raw: false, + triple_quoted: false, }, 31..32, ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_nul_char.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_nul_char.snap index 667d1897ec..76adda27a7 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_nul_char.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__fstring_with_nul_char.snap @@ -11,6 +11,7 @@ expression: lex_source(source) FStringMiddle { value: "\\0", is_raw: false, + triple_quoted: false, }, 2..4, ), diff --git a/crates/ruff_python_parser/src/token.rs b/crates/ruff_python_parser/src/token.rs index ac441395ff..059901b7ef 100644 --- a/crates/ruff_python_parser/src/token.rs +++ b/crates/ruff_python_parser/src/token.rs @@ -54,6 +54,8 @@ pub enum Tok { value: String, /// Whether the string is raw or not. is_raw: bool, + /// Whether the string is triple quoted. + triple_quoted: bool, }, /// Token value for the end of an f-string. This includes the closing quote. FStringEnd,