Skip to content

Commit 5a12efd

Browse files
committed
Flag knot: ignore[] as unused
1 parent 429250c commit 5a12efd

File tree

4 files changed

+26
-7
lines changed

4 files changed

+26
-7
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ An empty codes array suppresses no-diagnostics and is always useless
148148

149149
```py
150150
# error: [division-by-zero]
151+
# error: [unused-ignore-comment] "Unused `knot: ignore` without a code"
151152
a = 4 / 0 # knot: ignore[]
152153
```
153154

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ File level suppressions must come before any non-trivia token,
153153
including module docstrings.
154154
"""
155155

156-
# error: [unused-ignore-comment] "Unused blanked `type: ignore` directive"
156+
# error: [unused-ignore-comment] "Unused blanket `type: ignore` directive"
157157
# type: ignore
158158

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

crates/red_knot_python_semantic/src/suppression.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub(crate) fn suppressions(db: &dyn Db, file: File) -> Suppressions {
5353
let parser = SuppressionParser::new(&source, token.range());
5454

5555
for comment in parser {
56-
builder.add_comment(comment, TextRange::new(line_start, token.end()));
56+
builder.add_comment(&comment, TextRange::new(line_start, token.end()));
5757
}
5858
}
5959
TokenKind::Newline | TokenKind::NonLogicalNewline => {
@@ -126,7 +126,7 @@ pub(crate) fn check_unused_suppressions(
126126

127127
let message = match suppression.target {
128128
SuppressionTarget::All => {
129-
format!("Unused blanked `{}` directive", suppression.kind)
129+
format!("Unused blanket `{}` directive", suppression.kind)
130130
}
131131
SuppressionTarget::Lint(lint) => {
132132
format!(
@@ -135,6 +135,9 @@ pub(crate) fn check_unused_suppressions(
135135
code = lint.name()
136136
)
137137
}
138+
SuppressionTarget::Empty => {
139+
format!("Unused `{}` without a code", suppression.kind)
140+
}
138141
};
139142
diagnostics.push(TypeCheckDiagnostic {
140143
id: DiagnosticId::Lint(UNUSED_IGNORE_COMMENT.name()),
@@ -261,6 +264,7 @@ impl Suppression {
261264
match self.target {
262265
SuppressionTarget::All => true,
263266
SuppressionTarget::Lint(suppressed_id) => tested_id == suppressed_id,
267+
SuppressionTarget::Empty => false,
264268
}
265269
}
266270

@@ -285,6 +289,9 @@ enum SuppressionTarget {
285289

286290
/// Suppress the lint with the given id
287291
Lint(LintId),
292+
293+
/// Suppresses no lint, e.g. `knot: ignore[]`
294+
Empty,
288295
}
289296

290297
impl SuppressionTarget {
@@ -330,7 +337,7 @@ impl<'a> SuppressionsBuilder<'a> {
330337
}
331338
}
332339

333-
fn add_comment(&mut self, comment: SuppressionComment, line_range: TextRange) {
340+
fn add_comment(&mut self, comment: &SuppressionComment, line_range: TextRange) {
334341
let (suppressions, suppressed_range) =
335342
// `type: ignore` comments at the start of the file apply to the entire range.
336343
// > A # type: ignore comment on a line by itself at the top of a file, before any docstrings,
@@ -350,7 +357,7 @@ impl<'a> SuppressionsBuilder<'a> {
350357
)
351358
};
352359

353-
match comment.codes {
360+
match comment.codes.as_deref() {
354361
// `type: ignore`
355362
None => {
356363
suppressions.push(Suppression {
@@ -375,9 +382,20 @@ impl<'a> SuppressionsBuilder<'a> {
375382
});
376383
}
377384

385+
// `knot: ignore[]`
386+
Some([]) => {
387+
suppressions.push(Suppression {
388+
target: SuppressionTarget::Empty,
389+
kind: comment.kind,
390+
range: comment.range,
391+
comment_range: comment.range,
392+
suppressed_range,
393+
});
394+
}
395+
378396
// `knot: ignore[a, b]`
379397
Some(codes) => {
380-
for code_range in &codes {
398+
for code_range in codes {
381399
let code = &self.source[*code_range];
382400
match self.lint_registry.get(code) {
383401
Ok(lint) => {

crates/ruff_benchmark/benches/red_knot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static EXPECTED_DIAGNOSTICS: &[&str] = &[
4343
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:579:12 Name `char` used when possibly not defined",
4444
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:580:63 Name `char` used when possibly not defined",
4545
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:629:38 Name `datetime_obj` used when possibly not defined",
46-
"warning[lint:unused-ignore-comment] /src/tomllib/_parser.py:682:31 Unused blanked `type: ignore` directive"
46+
"warning[lint:unused-ignore-comment] /src/tomllib/_parser.py:682:31 Unused blanket `type: ignore` directive"
4747
];
4848

4949
fn get_test_file(name: &str) -> TestFile {

0 commit comments

Comments
 (0)