diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py index fbdeb1dd7e1542..28cc06427d76bc 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py @@ -62,6 +62,16 @@ 1111111111111111111111111111111111111111111111111111111111111111111111111, ) +""" +{} +""".format(1) + +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ +{} +""".format( + 111111 +) + ### # Non-errors ### @@ -99,6 +109,21 @@ 11111111111111111111111111111111111111111111111111111111111111111111111111, ) +""" +{} +{} +{} +""".format( +1, +2, +111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, +) + +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """{} +""".format( + 111111 +) + async def c(): return "{}".format(await 3) diff --git a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs index 494274b3a3751d..9f9954719b96da 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs @@ -325,8 +325,8 @@ pub(crate) fn f_strings( return; } - // Avoid refactoring multi-line strings. - if checker.locator.contains_line_break(template.range()) { + // Avoid refactoring strings that are implicitly concatenated. + if is_implicit_concatenation(checker.locator.slice(template.range())) { return; } @@ -338,7 +338,17 @@ pub(crate) fn f_strings( // Avoid refactors that exceed the line length limit. let col_offset = template.start() - checker.locator.line_start(template.start()); - if col_offset.to_usize() + contents.len() > line_length.get() { + if contents.lines().enumerate().any(|(idx, line)| { + // If `template` is a multiline string, `col_offset` should only be applied to the first + // line: + // ``` + // a = """{} -> offset = col_offset (= 4) + // {} -> offset = 0 + // """.format(0, 1) -> offset = 0 + // ``` + let offset = if idx == 0 { col_offset.to_usize() } else { 0 }; + offset + line.chars().count() > line_length.get() + }) { return; } diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap index 2a1340df50b060..2ae81f60bae340 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap @@ -581,7 +581,7 @@ UP032_0.py:61:1: UP032 [*] Use f-string instead of `format` call 63 | | ) | |_^ UP032 64 | -65 | ### +65 | """ | = help: Convert to f-string @@ -594,57 +594,115 @@ UP032_0.py:61:1: UP032 [*] Use f-string instead of `format` call 63 |-) 61 |+f"123456789 {1111111111111111111111111111111111111111111111111111111111111111111111111}" 64 62 | -65 63 | ### -66 64 | # Non-errors +65 63 | """ +66 64 | {} -UP032_0.py:111:11: UP032 [*] Use f-string instead of `format` call +UP032_0.py:65:1: UP032 [*] Use f-string instead of `format` call + | +63 | ) +64 | +65 | / """ +66 | | {} +67 | | """.format(1) + | |_____________^ UP032 +68 | +69 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ + | + = help: Convert to f-string + +ℹ Suggested fix +62 62 | 1111111111111111111111111111111111111111111111111111111111111111111111111, +63 63 | ) +64 64 | + 65 |+f""" + 66 |+{1} +65 67 | """ +66 |-{} +67 |-""".format(1) +68 68 | +69 69 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ +70 70 | {} + +UP032_0.py:69:85: UP032 [*] Use f-string instead of `format` call + | +67 | """.format(1) +68 | +69 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ + | _____________________________________________________________________________________^ +70 | | {} +71 | | """.format( +72 | | 111111 +73 | | ) + | |_^ UP032 +74 | +75 | ### + | + = help: Convert to f-string + +ℹ Suggested fix +66 66 | {} +67 67 | """.format(1) +68 68 | +69 |-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ +70 |-{} +71 |-""".format( +72 |- 111111 +73 |-) + 69 |+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = f""" + 70 |+{111111} + 71 |+""" +74 72 | +75 73 | ### +76 74 | # Non-errors + +UP032_0.py:136:11: UP032 [*] Use f-string instead of `format` call | -110 | def d(osname, version, release): -111 | return"{}-{}.{}".format(osname, version, release) +135 | def d(osname, version, release): +136 | return"{}-{}.{}".format(osname, version, release) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 | = help: Convert to f-string ℹ Suggested fix -108 108 | -109 109 | -110 110 | def d(osname, version, release): -111 |- return"{}-{}.{}".format(osname, version, release) - 111 |+ return f"{osname}-{version}.{release}" -112 112 | -113 113 | -114 114 | def e(): - -UP032_0.py:115:10: UP032 [*] Use f-string instead of `format` call +133 133 | +134 134 | +135 135 | def d(osname, version, release): +136 |- return"{}-{}.{}".format(osname, version, release) + 136 |+ return f"{osname}-{version}.{release}" +137 137 | +138 138 | +139 139 | def e(): + +UP032_0.py:140:10: UP032 [*] Use f-string instead of `format` call | -114 | def e(): -115 | yield"{}".format(1) +139 | def e(): +140 | yield"{}".format(1) | ^^^^^^^^^^^^^^ UP032 | = help: Convert to f-string ℹ Suggested fix -112 112 | -113 113 | -114 114 | def e(): -115 |- yield"{}".format(1) - 115 |+ yield f"{1}" -116 116 | -117 117 | -118 118 | assert"{}".format(1) - -UP032_0.py:118:7: UP032 [*] Use f-string instead of `format` call +137 137 | +138 138 | +139 139 | def e(): +140 |- yield"{}".format(1) + 140 |+ yield f"{1}" +141 141 | +142 142 | +143 143 | assert"{}".format(1) + +UP032_0.py:143:7: UP032 [*] Use f-string instead of `format` call | -118 | assert"{}".format(1) +143 | assert"{}".format(1) | ^^^^^^^^^^^^^^ UP032 | = help: Convert to f-string ℹ Suggested fix -115 115 | yield"{}".format(1) -116 116 | -117 117 | -118 |-assert"{}".format(1) - 118 |+assert f"{1}" +140 140 | yield"{}".format(1) +141 141 | +142 142 | +143 |-assert"{}".format(1) + 143 |+assert f"{1}"