Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
321 changes: 321 additions & 0 deletions crates/ruff_linter/resources/mdtest/ruff/noqa-comment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
# `noqa-comment` (`RUF105`)

```toml
[lint]
preview = true
select = ["noqa-comment", "F401", "F402", "F403"]
```

## File-level comments

### Single code

```py
# snapshot: noqa-comment
# ruff: noqa: F401
import math
```

```snapshot
error[RUF105]: `ruff: noqa` comment used instead of `ruff:file-ignore`
--> src/mdtest_snippet.py:2:1
|
2 | # ruff: noqa: F401
| ^^^^^^^^^^^^^^^^^^
|
help: Use `ruff:file-ignore` instead
|
1 | # snapshot: noqa-comment
- # ruff: noqa: F401
2 + # ruff:file-ignore[F401]
3 | import math
|
```

### Multiple codes

```py
# snapshot: noqa-comment
# ruff: noqa: F401, F402, F403
import math
import os
from module import *
for os in []:
pass
```

```snapshot
error[RUF105]: `ruff: noqa` comment used instead of `ruff:file-ignore`
--> src/mdtest_snippet.py:2:1
|
2 | # ruff: noqa: F401, F402, F403
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Use `ruff:file-ignore` instead
|
1 | # snapshot: noqa-comment
- # ruff: noqa: F401, F402, F403
2 + # ruff:file-ignore[F401, F402, F403]
3 | import math
|
```

### Multiple codes followed by a reason

```py
# snapshot: noqa-comment
# ruff: noqa: F401, F402, F403 for some reason
import math
import os
from module import *
for os in []:
pass
```

```snapshot
error[RUF105]: `ruff: noqa` comment used instead of `ruff:file-ignore`
--> src/mdtest_snippet.py:2:1
|
2 | # ruff: noqa: F401, F402, F403 for some reason
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Use `ruff:file-ignore` instead
|
1 | # snapshot: noqa-comment
- # ruff: noqa: F401, F402, F403 for some reason
2 + # ruff:file-ignore[F401, F402, F403] for some reason
3 | import math
|
```

### Multiple codes followed by a nested (pragma) comment

```py
# snapshot: noqa-comment
# ruff: noqa: F401, F402, F403 # fmt:skip
import math
import os
from module import *
for os in []:
pass
```

```snapshot
error[RUF105]: `ruff: noqa` comment used instead of `ruff:file-ignore`
--> src/mdtest_snippet.py:2:1
|
2 | # ruff: noqa: F401, F402, F403 # fmt:skip
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Use `ruff:file-ignore` instead
|
1 | # snapshot: noqa-comment
- # ruff: noqa: F401, F402, F403 # fmt:skip
2 + # ruff:file-ignore[F401, F402, F403] # fmt:skip
3 | import math
|
```

### Unknown codes do not disable the rule

In case the unknown code is a typo rather than an intentionally external code, we emit both
`invalid-rule-code` and `noqa-comment`:

```toml
[lint]
preview = true
select = ["noqa-comment", "unused-noqa", "invalid-rule-code", "F401"]
```

```py
# error: [noqa-comment]
# snapshot: invalid-rule-code
import math # noqa: F401, UNK001
Comment thread
ntBre marked this conversation as resolved.
Outdated
```

```snapshot
error[RUF102]: Invalid rule code in `# noqa`: UNK001
--> src/mdtest_snippet.py:3:28
|
3 | import math # noqa: F401, UNK001
| ^^^^^^
|
help: Add non-Ruff rule codes to the `lint.external` configuration option
help: Remove the rule code `UNK001`
|
2 | # snapshot: invalid-rule-code
- import math # noqa: F401, UNK001
3 + import math # noqa: F401
|
```

### External codes disable the rule

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the word disable the rule a bit misleading. It's not that we disable the rule. It's more that using noqa remains allowed in combination with external codes.


However, if the code is intentionally marked as `external`, we *do* disable the rule:
Comment thread
ntBre marked this conversation as resolved.
Outdated

```toml
[lint]
preview = true
select = ["noqa-comment", "unused-noqa", "invalid-rule-code", "F401"]
external = ["EXT"]
```

```py
import math # noqa: F401, EXT001
```

### Any unmatched code disables the rule

This leaves an unused `noqa` comment to be cleaned up by `RUF100` instead, which can be especially
important in the case of a standalone `noqa` comment, which has no effect (in almost all cases), but
could become an effectful own-line `ruff:ignore` comment if `RUF105` applied.

```py
# ruff: noqa: F401, F402
import math
```

### Flake8 comments are ignored

```py
# flake8: noqa: F401
import math
```

## Inline comments

### Basic

```py
# snapshot: noqa-comment
import math # noqa: F401

import os # noqa: F401, F402
```

```snapshot
error[RUF105]: `noqa` comment used instead of `ruff:ignore`
--> src/mdtest_snippet.py:2:14
|
2 | import math # noqa: F401
| ^^^^^^^^^^^^
|
help: Use `ruff:ignore` instead
|
1 | # snapshot: noqa-comment
- import math # noqa: F401
2 + import math # ruff:ignore[F401]
3 |
|
```

### Nested pragma comment before the directive

```py
# snapshot: noqa-comment
import math # fmt:skip # noqa: F401
```

```snapshot
error[RUF105]: `noqa` comment used instead of `ruff:ignore`
--> src/mdtest_snippet.py:2:25
|
2 | import math # fmt:skip # noqa: F401
| ^^^^^^^^^^^^
|
help: Use `ruff:ignore` instead
|
1 | # snapshot: noqa-comment
- import math # fmt:skip # noqa: F401
2 + import math # fmt:skip # ruff:ignore[F401]
|
```

## Blanket comments

RUF105 flags blanket comments but does not offer a fix because `ruff:ignore` requires at least one
rule selector.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and I think the complexity is that we don't track which rules were suppressed by a noqa comment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that we actually do track this in matches:

pub(crate) struct NoqaDirectiveLine<'a> {
/// The range of the text line for which the noqa directive applies.
pub(crate) range: TextRange,
/// The noqa directive.
pub(crate) directive: Directive<'a>,
/// The codes that are ignored by the directive.
pub(crate) matches: Vec<Rule>,

I wonder why we don't use this in PGH004.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to revert this if I went too far, but I got this working with matches without too much code. My only hesitation is whether this logic belongs exclusively in PGH004 or if it's okay to use it here too.


### Inline

```py
# snapshot: noqa-comment
import math # noqa
```

```snapshot
error[RUF105]: `noqa` comment used instead of `ruff:ignore`
--> src/mdtest_snippet.py:2:14
|
2 | import math # noqa
| ^^^^^^
|
```

### File-level

```py
# snapshot: noqa-comment
# ruff: noqa
import math
```

```snapshot
error[RUF105]: `ruff: noqa` comment used instead of `ruff:file-ignore`
--> src/mdtest_snippet.py:2:1
|
2 | # ruff: noqa
| ^^^^^^^^^^^^
|
```

## Inline self-suppression

```toml
[lint]
preview = true
select = ["noqa-comment", "unused-noqa", "F401"]
```

It should be possible to suppress `RUF105` with a `noqa` comment:

```py
value = 1 # noqa: RUF105
```

But a suppression for `RUF100` should not prevent the rule from firing:

```py
# error: [noqa-comment]
import math # noqa: RUF100, F401
```

## Suppression with `ruff:ignore`

```toml
[lint]
preview = true
select = ["noqa-comment", "unused-noqa", "F401"]
```

### Inline suppression

```py
import math # noqa: F401 # ruff:ignore[RUF105]
```

### Standalone suppression

```py
# ruff:ignore[RUF105]
# ruff: noqa: F401
import math
```

### File-level suppression

```py
# ruff:file-ignore[RUF105]
# ruff: noqa: F401
import math
```
2 changes: 1 addition & 1 deletion crates/ruff_linter/resources/mdtest/suppression/ignore.md
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ import foo
```toml
[lint]
preview = true
select = ["F401", "RUF10", "FIX002"]
select = ["F401", "RUF100", "FIX002"]
```

Nested suppression comments on a comment-only line are treated as trailing on the comment itself and
Expand Down
Loading
Loading