Skip to content

Commit 667dc62

Browse files
lubaskinc0dentBre
andauthored
[ruff] Fix syntax error introduced for an empty string followed by a u-prefixed string (UP025) (#18899)
## Summary /closes #18895 ## Test Plan --------- Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
1 parent dac4e35 commit 667dc62

File tree

3 files changed

+111
-5
lines changed

3 files changed

+111
-5
lines changed

crates/ruff_linter/resources/test/fixtures/pyupgrade/UP025.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,9 @@ def hello():
2626

2727
f"foo"u"bar" # OK
2828
f"foo" u"bar" # OK
29+
30+
# https://github.com/astral-sh/ruff/issues/18895
31+
""u""
32+
""u"hi"
33+
""""""""""""""""""""u"hi"
34+
""U"helloooo"

crates/ruff_linter/src/rules/pyupgrade/rules/unicode_kind_prefix.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,28 @@ impl AlwaysFixableViolation for UnicodeKindPrefix {
4242
pub(crate) fn unicode_kind_prefix(checker: &Checker, string: &StringLiteral) {
4343
if string.flags.prefix().is_unicode() {
4444
let mut diagnostic = checker.report_diagnostic(UnicodeKindPrefix, string.range);
45-
diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(TextRange::at(
46-
string.start(),
47-
TextSize::from(1),
48-
))));
45+
46+
let prefix_range = TextRange::at(string.start(), TextSize::new(1));
47+
let locator = checker.locator();
48+
let content = locator
49+
.slice(TextRange::new(prefix_range.end(), string.end()))
50+
.to_owned();
51+
52+
// If the preceding character is equivalent to the quote character, insert a space to avoid a
53+
// syntax error. For example, when removing the `u` prefix in `""u""`, rewrite to `"" ""`
54+
// instead of `""""`.
55+
// see https://github.com/astral-sh/ruff/issues/18895
56+
let edit = if locator
57+
.slice(TextRange::up_to(prefix_range.start()))
58+
.chars()
59+
.last()
60+
.is_some_and(|char| content.starts_with(char))
61+
{
62+
Edit::range_replacement(" ".to_string(), prefix_range)
63+
} else {
64+
Edit::range_deletion(prefix_range)
65+
};
66+
67+
diagnostic.set_fix(Fix::safe_edit(edit));
4968
}
5069
}

crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP025.py.snap

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,14 +281,18 @@ UP025.py:27:7: UP025 [*] Remove unicode literals from strings
281281
25 25 | return"Hello" # OK
282282
26 26 |
283283
27 |-f"foo"u"bar" # OK
284-
27 |+f"foo""bar" # OK
284+
27 |+f"foo" "bar" # OK
285285
28 28 | f"foo" u"bar" # OK
286+
29 29 |
287+
30 30 | # https://github.com/astral-sh/ruff/issues/18895
286288

287289
UP025.py:28:8: UP025 [*] Remove unicode literals from strings
288290
|
289291
27 | f"foo"u"bar" # OK
290292
28 | f"foo" u"bar" # OK
291293
| ^^^^^^ UP025
294+
29 |
295+
30 | # https://github.com/astral-sh/ruff/issues/18895
292296
|
293297
= help: Remove unicode prefix
294298

@@ -298,3 +302,80 @@ UP025.py:28:8: UP025 [*] Remove unicode literals from strings
298302
27 27 | f"foo"u"bar" # OK
299303
28 |-f"foo" u"bar" # OK
300304
28 |+f"foo" "bar" # OK
305+
29 29 |
306+
30 30 | # https://github.com/astral-sh/ruff/issues/18895
307+
31 31 | ""u""
308+
309+
UP025.py:31:3: UP025 [*] Remove unicode literals from strings
310+
|
311+
30 | # https://github.com/astral-sh/ruff/issues/18895
312+
31 | ""u""
313+
| ^^^ UP025
314+
32 | ""u"hi"
315+
33 | """"""""""""""""""""u"hi"
316+
|
317+
= help: Remove unicode prefix
318+
319+
Safe fix
320+
28 28 | f"foo" u"bar" # OK
321+
29 29 |
322+
30 30 | # https://github.com/astral-sh/ruff/issues/18895
323+
31 |-""u""
324+
31 |+"" ""
325+
32 32 | ""u"hi"
326+
33 33 | """"""""""""""""""""u"hi"
327+
34 34 | ""U"helloooo"
328+
329+
UP025.py:32:3: UP025 [*] Remove unicode literals from strings
330+
|
331+
30 | # https://github.com/astral-sh/ruff/issues/18895
332+
31 | ""u""
333+
32 | ""u"hi"
334+
| ^^^^^ UP025
335+
33 | """"""""""""""""""""u"hi"
336+
34 | ""U"helloooo"
337+
|
338+
= help: Remove unicode prefix
339+
340+
Safe fix
341+
29 29 |
342+
30 30 | # https://github.com/astral-sh/ruff/issues/18895
343+
31 31 | ""u""
344+
32 |-""u"hi"
345+
32 |+"" "hi"
346+
33 33 | """"""""""""""""""""u"hi"
347+
34 34 | ""U"helloooo"
348+
349+
UP025.py:33:21: UP025 [*] Remove unicode literals from strings
350+
|
351+
31 | ""u""
352+
32 | ""u"hi"
353+
33 | """"""""""""""""""""u"hi"
354+
| ^^^^^ UP025
355+
34 | ""U"helloooo"
356+
|
357+
= help: Remove unicode prefix
358+
359+
Safe fix
360+
30 30 | # https://github.com/astral-sh/ruff/issues/18895
361+
31 31 | ""u""
362+
32 32 | ""u"hi"
363+
33 |-""""""""""""""""""""u"hi"
364+
33 |+"""""""""""""""""""" "hi"
365+
34 34 | ""U"helloooo"
366+
367+
UP025.py:34:3: UP025 [*] Remove unicode literals from strings
368+
|
369+
32 | ""u"hi"
370+
33 | """"""""""""""""""""u"hi"
371+
34 | ""U"helloooo"
372+
| ^^^^^^^^^^^ UP025
373+
|
374+
= help: Remove unicode prefix
375+
376+
Safe fix
377+
31 31 | ""u""
378+
32 32 | ""u"hi"
379+
33 33 | """"""""""""""""""""u"hi"
380+
34 |-""U"helloooo"
381+
34 |+"" "helloooo"

0 commit comments

Comments
 (0)