diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM905.py b/crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM905.py index 1545b07ca8..a8dc8fe996 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM905.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM905.py @@ -171,3 +171,10 @@ print("<\x1c\x1d\x1e\x1f".rsplit(maxsplit=0)) " a b c d ".split(maxsplit=2) # ["a", "b", "c d "] " a b c d ".rsplit(maxsplit=2) # [" a b", "c", "d"] "a b".split(maxsplit=1) # ["a", "b"] + +# https://github.com/astral-sh/ruff/issues/19610 +r"1" "\n".split("1") # [r"", "\n"] +r"" "\"".split("1") # ['"'] +r"1" """ +""".split("1") # [r"", "\n"] +r"\n" "\n'\"".split("1") # ["\\n\n'\""] diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/split_static_string.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/split_static_string.rs index ffd4ee30c5..a38886772e 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/split_static_string.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/split_static_string.rs @@ -1,8 +1,7 @@ use ruff_macros::{ViolationMetadata, derive_message_formats}; -use ruff_python_ast::StringFlags; use ruff_python_ast::{ - Expr, ExprCall, ExprContext, ExprList, ExprUnaryOp, StringLiteral, StringLiteralFlags, - StringLiteralValue, UnaryOp, str::TripleQuotes, + Expr, ExprCall, ExprContext, ExprList, ExprUnaryOp, StringFlags, StringLiteral, + StringLiteralFlags, StringLiteralValue, UnaryOp, }; use ruff_text_size::{Ranged, TextRange}; use std::cmp::Ordering; @@ -158,21 +157,26 @@ fn replace_flags(elt: &str, flags: StringLiteralFlags) -> StringLiteralFlags { // 'single'quoted // """.split() # -> [r"itemA",r"'single'quoted'"] // ``` - if !flags.prefix().is_raw() || !elt.contains(flags.quote_style().as_char()) { - flags.with_triple_quotes(TripleQuotes::No) - } - // If we have a raw string containing a quotation mark of the same style, - // then we have to swap the style of quotation marks used - else if !elt.contains(flags.quote_style().opposite().as_char()) { - flags - .with_quote_style(flags.quote_style().opposite()) - .with_triple_quotes(TripleQuotes::No) - } else - // If both types of quotes are used in the raw, triple-quoted string, then - // we are forced to either add escapes or keep the triple quotes. We opt for - // the latter. - { - flags + if !flags.prefix().is_raw() { + flags.with_triple_quotes(ruff_python_ast::str::TripleQuotes::No) + } else if elt.contains(['\n', '\r']) { + // If the element contains newlines or carriage returns, we need to use + // default flags (no raw prefix) to avoid syntax errors + StringLiteralFlags::empty() + } else if elt.contains(flags.quote_style().as_char()) { + // If we have a raw string containing a quotation mark of the same style, + // then we have to swap the style of quotation marks used + if elt.contains(flags.quote_style().opposite().as_char()) { + // If both types of quotes are used in the raw string, then + // we are forced to use default flags to avoid syntax errors + StringLiteralFlags::empty() + } else { + flags + .with_quote_style(flags.quote_style().opposite()) + .with_triple_quotes(ruff_python_ast::str::TripleQuotes::No) + } + } else { + flags.with_triple_quotes(ruff_python_ast::str::TripleQuotes::No) } } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__SIM905_SIM905.py.snap b/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__SIM905_SIM905.py.snap index 2cadf0ceb9..961048deeb 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__SIM905_SIM905.py.snap +++ b/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__SIM905_SIM905.py.snap @@ -1302,7 +1302,7 @@ help: Replace with list literal - 'no need' to escape - "swap" quote style - "use' ugly triple quotes""".split("\n") -160 + [r"first", r"'no need' to escape", r'"swap" quote style', r""""use' ugly triple quotes"""] +160 + [r"first", r"'no need' to escape", r'"swap" quote style', '"use\' ugly triple quotes'] 161 | 162 | # https://github.com/astral-sh/ruff/issues/19845 163 | print("S\x1cP\x1dL\x1eI\x1fT".split()) @@ -1394,5 +1394,80 @@ SIM905 Consider using a list literal instead of `str.split` 172 | " a b c d ".rsplit(maxsplit=2) # [" a b", "c", "d"] 173 | "a b".split(maxsplit=1) # ["a", "b"] | ^^^^^^^^^^^^^^^^^^^^^^^^ +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 | help: Replace with list literal + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:176:1 + | +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] + | ^^^^^^^^^^^^^^^^^^^^ +177 | r"" "\"".split("1") # ['"'] +178 | r"1" """ + | +help: Replace with list literal +173 | "a b".split(maxsplit=1) # ["a", "b"] +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 + - r"1" "\n".split("1") # [r"", "\n"] +176 + [r"", '\n'] # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:177:1 + | +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] + | ^^^^^^^^^^^^^^^^^^^ +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] + | +help: Replace with list literal +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] + - r"" "\"".split("1") # ['"'] +177 + [r'"'] # ['"'] +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] +180 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:178:1 + | +176 | r"1" "\n".split("1") # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] +178 | / r"1" """ +179 | | """.split("1") # [r"", "\n"] + | |______________^ +180 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + | +help: Replace with list literal +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] + - r"1" """ + - """.split("1") # [r"", "\n"] +178 + [r"", '\n'] # [r"", "\n"] +179 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:180:1 + | +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] +180 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: Replace with list literal +177 | r"" "\"".split("1") # ['"'] +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] + - r"\n" "\n'\"".split("1") # ["\\n\n'\""] +180 + ['\\n\n\'"'] # ["\\n\n'\""] diff --git a/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__preview__SIM905_SIM905.py.snap b/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__preview__SIM905_SIM905.py.snap index d477367205..d224c4581f 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__preview__SIM905_SIM905.py.snap +++ b/crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__preview__SIM905_SIM905.py.snap @@ -1350,7 +1350,7 @@ help: Replace with list literal - 'no need' to escape - "swap" quote style - "use' ugly triple quotes""".split("\n") -160 + [r"first", r"'no need' to escape", r'"swap" quote style', r""""use' ugly triple quotes"""] +160 + [r"first", r"'no need' to escape", r'"swap" quote style', '"use\' ugly triple quotes'] 161 | 162 | # https://github.com/astral-sh/ruff/issues/19845 163 | print("S\x1cP\x1dL\x1eI\x1fT".split()) @@ -1430,6 +1430,7 @@ help: Replace with list literal 171 + ["a", "b", "c d "] # ["a", "b", "c d "] 172 | " a b c d ".rsplit(maxsplit=2) # [" a b", "c", "d"] 173 | "a b".split(maxsplit=1) # ["a", "b"] +174 | SIM905 [*] Consider using a list literal instead of `str.rsplit` --> SIM905.py:172:1 @@ -1447,6 +1448,8 @@ help: Replace with list literal - " a b c d ".rsplit(maxsplit=2) # [" a b", "c", "d"] 172 + [" a b", "c", "d"] # [" a b", "c", "d"] 173 | "a b".split(maxsplit=1) # ["a", "b"] +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 SIM905 [*] Consider using a list literal instead of `str.split` --> SIM905.py:173:1 @@ -1455,6 +1458,8 @@ SIM905 [*] Consider using a list literal instead of `str.split` 172 | " a b c d ".rsplit(maxsplit=2) # [" a b", "c", "d"] 173 | "a b".split(maxsplit=1) # ["a", "b"] | ^^^^^^^^^^^^^^^^^^^^^^^^ +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 | help: Replace with list literal 170 | # leading/trailing whitespace should not count towards maxsplit @@ -1462,3 +1467,79 @@ help: Replace with list literal 172 | " a b c d ".rsplit(maxsplit=2) # [" a b", "c", "d"] - "a b".split(maxsplit=1) # ["a", "b"] 173 + ["a", "b"] # ["a", "b"] +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:176:1 + | +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] + | ^^^^^^^^^^^^^^^^^^^^ +177 | r"" "\"".split("1") # ['"'] +178 | r"1" """ + | +help: Replace with list literal +173 | "a b".split(maxsplit=1) # ["a", "b"] +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 + - r"1" "\n".split("1") # [r"", "\n"] +176 + [r"", '\n'] # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:177:1 + | +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] + | ^^^^^^^^^^^^^^^^^^^ +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] + | +help: Replace with list literal +174 | +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] + - r"" "\"".split("1") # ['"'] +177 + [r'"'] # ['"'] +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] +180 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:178:1 + | +176 | r"1" "\n".split("1") # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] +178 | / r"1" """ +179 | | """.split("1") # [r"", "\n"] + | |______________^ +180 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + | +help: Replace with list literal +175 | # https://github.com/astral-sh/ruff/issues/19610 +176 | r"1" "\n".split("1") # [r"", "\n"] +177 | r"" "\"".split("1") # ['"'] + - r"1" """ + - """.split("1") # [r"", "\n"] +178 + [r"", '\n'] # [r"", "\n"] +179 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + +SIM905 [*] Consider using a list literal instead of `str.split` + --> SIM905.py:180:1 + | +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] +180 | r"\n" "\n'\"".split("1") # ["\\n\n'\""] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: Replace with list literal +177 | r"" "\"".split("1") # ['"'] +178 | r"1" """ +179 | """.split("1") # [r"", "\n"] + - r"\n" "\n'\"".split("1") # ["\\n\n'\""] +180 + ['\\n\n\'"'] # ["\\n\n'\""]