Skip to content

Commit

Permalink
[ruff] Fix panic in unused # noqa removal with multi-byte space (…
Browse files Browse the repository at this point in the history
…`RUF100`) (#10682)

## Summary

Currently, [this
line](https://github.com/astral-sh/ruff/blob/716688d44ecda5d4648b7a31556bb77afe6cbbc6/crates/ruff_linter/src/fix/edits.rs#L101)
assumes that the `noqa` comment begins with an octothorpe followed by a
space. (`# `) With anyone's random code, this of course is not always
true.

When there's a multi-byte character after the leading octothorpe, such
as
[`\u0085`](https://www.fileformat.info/info/unicode/char/85/index.htm),
we try slicing from within the character, causing a panic.

To fix this, the logic has been changed to remove unused `noqa`
directives and keep any trailing comments, or removing the whole comment
if the comment is just the unused `noqa`

Fixes #10097.

## Test Plan

`cargo test`
  • Loading branch information
diceroll123 committed Apr 1, 2024
1 parent 9f2127b commit f6b6f0d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 3 deletions.
6 changes: 6 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/ruff/RUF100_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,9 @@ def f():
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
""" # noqa


def f():
# Invalid - nonexistant error code with multibyte character
d = 1 #…noqa: F841, E50
e = 1 #…noqa: E50
9 changes: 6 additions & 3 deletions crates/ruff_linter/src/fix/edits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub(crate) fn delete_comment(range: TextRange, locator: &Locator) -> Edit {
}
// Ex) `x = 1 # noqa`
else if range.end() + trailing_space_len == line_range.end() {
// Replace `x = 1 # noqa` with `x = 1`.
Edit::deletion(range.start() - leading_space_len, line_range.end())
}
// Ex) `x = 1 # noqa # type: ignore`
Expand All @@ -93,13 +94,15 @@ pub(crate) fn delete_comment(range: TextRange, locator: &Locator) -> Edit {
))
.starts_with('#')
{
// Replace `# noqa # type: ignore` with `# type: ignore`.
Edit::deletion(range.start(), range.end() + trailing_space_len)
}
// Ex) `x = 1 # noqa here`
else {
Edit::deletion(
range.start() + "# ".text_len(),
range.end() + trailing_space_len,
// Replace `# noqa here` with `# here`.
Edit::range_replacement(
"# ".to_string(),
TextRange::new(range.start(), range.end() + trailing_space_len),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,4 +284,51 @@ RUF100_0.py:93:92: RUF100 [*] Unused `noqa` directive (unused: `F401`)
95 95 |
96 96 | def f():

RUF100_0.py:107:12: RUF100 [*] Unused `noqa` directive (unknown: `E50`)
|
105 | def f():
106 | # Invalid - nonexistant error code with multibyte character
107 | d = 1noqa: F841, E50
| ^^^^^^^^^^^^^^^^ RUF100
108 | e = 1noqa: E50
|
= help: Remove unused `noqa` directive

Safe fix
104 104 |
105 105 | def f():
106 106 | # Invalid - nonexistant error code with multibyte character
107 |- d = 1noqa: F841, E50
107 |+ d = 1 # noqa: F841
108 108 | e = 1noqa: E50

RUF100_0.py:108:5: F841 [*] Local variable `e` is assigned to but never used
|
106 | # Invalid - nonexistant error code with multibyte character
107 | d = 1noqa: F841, E50
108 | e = 1noqa: E50
| ^ F841
|
= help: Remove assignment to unused variable `e`

Unsafe fix
105 105 | def f():
106 106 | # Invalid - nonexistant error code with multibyte character
107 107 | d = 1noqa: F841, E50
108 |- e = 1noqa: E50

RUF100_0.py:108:12: RUF100 [*] Unused `noqa` directive (unknown: `E50`)
|
106 | # Invalid - nonexistant error code with multibyte character
107 | d = 1noqa: F841, E50
108 | e = 1noqa: E50
| ^^^^^^^^^^ RUF100
|
= help: Remove unused `noqa` directive

Safe fix
105 105 | def f():
106 106 | # Invalid - nonexistant error code with multibyte character
107 107 | d = 1noqa: F841, E50
108 |- e = 1noqa: E50
108 |+ e = 1
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,51 @@ RUF100_0.py:93:92: RUF100 [*] Unused `noqa` directive (unused: `F401`)
95 95 |
96 96 | def f():

RUF100_0.py:107:12: RUF100 [*] Unused `noqa` directive (unknown: `E50`)
|
105 | def f():
106 | # Invalid - nonexistant error code with multibyte character
107 | d = 1noqa: F841, E50
| ^^^^^^^^^^^^^^^^ RUF100
108 | e = 1noqa: E50
|
= help: Remove unused `noqa` directive

Safe fix
104 104 |
105 105 | def f():
106 106 | # Invalid - nonexistant error code with multibyte character
107 |- d = 1noqa: F841, E50
107 |+ d = 1 # noqa: F841
108 108 | e = 1noqa: E50

RUF100_0.py:108:5: F841 [*] Local variable `e` is assigned to but never used
|
106 | # Invalid - nonexistant error code with multibyte character
107 | d = 1noqa: F841, E50
108 | e = 1noqa: E50
| ^ F841
|
= help: Remove assignment to unused variable `e`

Unsafe fix
105 105 | def f():
106 106 | # Invalid - nonexistant error code with multibyte character
107 107 | d = 1noqa: F841, E50
108 |- e = 1noqa: E50

RUF100_0.py:108:12: RUF100 [*] Unused `noqa` directive (unknown: `E50`)
|
106 | # Invalid - nonexistant error code with multibyte character
107 | d = 1noqa: F841, E50
108 | e = 1noqa: E50
| ^^^^^^^^^^ RUF100
|
= help: Remove unused `noqa` directive

Safe fix
105 105 | def f():
106 106 | # Invalid - nonexistant error code with multibyte character
107 107 | d = 1noqa: F841, E50
108 |- e = 1noqa: E50
108 |+ e = 1

0 comments on commit f6b6f0d

Please sign in to comment.