Skip to content

Commit 6ea4bfa

Browse files
committed
Add unused-ignore-comment rule
1 parent 357825e commit 6ea4bfa

File tree

7 files changed

+257
-55
lines changed

7 files changed

+257
-55
lines changed

crates/red_knot_python_semantic/resources/mdtest/suppressions/knot-ignore.md

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,55 @@ a = 4 + test # knot: ignore
1414
a = 4 + test # knot: ignore[unresolved-reference]
1515
```
1616

17-
## Useless suppression
18-
19-
TODO: Red Knot should emit an `unused-suppression` diagnostic for the
20-
`possibly-unresolved-reference` suppression.
17+
## Unused suppression
2118

2219
```py
2320
test = 10
21+
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'possibly-unresolved-reference'"
2422
a = test + 3 # knot: ignore[possibly-unresolved-reference]
2523
```
2624

27-
## Useless suppression if the error codes don't match
28-
29-
TODO: Red Knot should emit a `unused-suppression` diagnostic for the `possibly-unresolved-reference`
30-
suppression because it doesn't match the actual `unresolved-reference` diagnostic.
25+
## Unused suppression if the error codes don't match
3126

3227
```py
3328
# error: [unresolved-reference]
29+
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'possibly-unresolved-reference'"
3430
a = test + 3 # knot: ignore[possibly-unresolved-reference]
3531
```
3632

33+
## Suppressed unused comment
34+
35+
```py
36+
# error: [unused-ignore-comment]
37+
a = 10 / 2 # knot: ignore[division-by-zero]
38+
a = 10 / 2 # knot: ignore[division-by-zero, unused-ignore-comment]
39+
a = 10 / 2 # knot: ignore[unused-ignore-comment, division-by-zero]
40+
a = 10 / 2 # knot: ignore[unused-ignore-comment] # type: ignore
41+
a = 10 / 2 # type: ignore # knot: ignore[unused-ignore-comment]
42+
```
43+
44+
## Unused ignore comment
45+
46+
```py
47+
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unused-ignore-comment'"
48+
a = 10 / 0 # knot: ignore[division-by-zero, unused-ignore-comment]
49+
```
50+
51+
## Multiple unused comments
52+
53+
Today, Red Knot emits a diagnostic for every unused code.
54+
We might want to group the codes by comment at some point in the future.
55+
56+
```py
57+
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'division-by-zero'"
58+
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unresolved-reference'"
59+
a = 10 / 2 # knot: ignore[division-by-zero, unresolved-reference]
60+
61+
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'invalid-assignment'"
62+
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unresolved-reference'"
63+
a = 10 / 0 # knot: ignore[invalid-assignment, division-by-zero, unresolved-reference]
64+
```
65+
3766
## Multiple suppressions
3867

3968
```py
@@ -47,17 +76,20 @@ def test(a: f"f-string type annotation", b: b"byte-string-type-annotation"): ...
4776

4877
```py
4978
# error: [invalid-syntax]
79+
# error: [unused-ignore-comment]
5080
def test( # knot: ignore
5181
```
5282

5383
<!-- blacken-docs:on -->
5484

5585
## Can't suppress `revealed-type` diagnostics
5686

87+
TODO: Emit an error that the rule code is unknown: `unknown-rule`
88+
5789
```py
5890
a = 10
5991
# revealed: Literal[10]
60-
reveal_type(a) # knot: ignore
92+
reveal_type(a) # knot: ignore[revealed-type]
6193
```
6294

6395
## Extra whitespace in type ignore comments is allowed
@@ -126,6 +158,7 @@ if they should use a different syntax that also supports enabling rules or chang
126158
severity: `knot: possibly-undefined-reference=error`
127159

128160
```py
161+
# error: [unused-ignore-comment]
129162
# knot: ignore[division-by-zero]
130163

131164
a = 4 / 0 # error: [division-by-zero]

crates/red_knot_python_semantic/resources/mdtest/suppressions/type-ignore.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ from typing import cast
4343

4444
y = (
4545
cast(int, "test" +
46+
# TODO: Remove the expected error after implementing `invalid-operator` for binary expressions
47+
# error: [unused-ignore-comment]
4648
2 # type: ignore
4749
)
4850
+ "other" # TODO: expected-error[invalid-operator]
@@ -118,6 +120,7 @@ in Pyright. Neither Ruff, nor mypy support this and neither does Red Knot.
118120

119121
```py
120122
# fmt: off
123+
# error: [unused-ignore-comment]
121124
a = ( # type: ignore
122125
test + 4 # error: [unresolved-reference]
123126
)
@@ -149,7 +152,7 @@ b = a / 0
149152
File level suppressions must come before any non-trivia token,
150153
including module docstrings.
151154
"""
152-
155+
# error: [unused-ignore-comment] "Unused blanked `type: ignore` directive"
153156
# type: ignore
154157

155158
a = 10 / 0 # error: [division-by-zero]

crates/red_knot_python_semantic/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::hash::BuildHasherDefault;
33
use rustc_hash::FxHasher;
44

55
use crate::lint::{LintRegistry, LintRegistryBuilder};
6+
use crate::suppression::UNUSED_IGNORE_COMMENT;
67
pub use db::Db;
78
pub use module_name::ModuleName;
89
pub use module_resolver::{resolve_module, system_module_search_paths, KnownModule, Module};
@@ -44,4 +45,5 @@ pub fn default_lint_registry() -> &'static LintRegistry {
4445
/// Register all known semantic lints.
4546
pub fn register_lints(registry: &mut LintRegistryBuilder) {
4647
types::register_lints(registry);
48+
registry.register_lint(&UNUSED_IGNORE_COMMENT);
4749
}

0 commit comments

Comments
 (0)