Generate invalid rule code diagnostics

This commit is contained in:
Amethyst Reese 2025-12-11 16:59:18 -08:00
parent f48d4a437b
commit 2517430738
3 changed files with 147 additions and 16 deletions

View File

@ -86,3 +86,12 @@ def f():
# Multiple codes but none are used # Multiple codes but none are used
# ruff: disable[E741, F401, F841] # ruff: disable[E741, F401, F841]
print("hello") print("hello")
def f():
# Unknown rule codes
# ruff: disable[YF829]
# ruff: disable[F841, RQW320]
value = 0
# ruff: enable[F841, RQW320]
# ruff: enable[YF829]

View File

@ -6,8 +6,8 @@ source: crates/ruff_linter/src/rules/ruff/mod.rs
+linter.preview = enabled +linter.preview = enabled
--- Summary --- --- Summary ---
Removed: 14 Removed: 15
Added: 19 Added: 23
--- Removed --- --- Removed ---
E741 Ambiguous variable name: `I` E741 Ambiguous variable name: `I`
@ -238,6 +238,27 @@ help: Remove assignment to unused variable `I`
note: This is an unsafe fix and may change runtime behavior note: This is an unsafe fix and may change runtime behavior
F841 [*] Local variable `value` is assigned to but never used
--> suppressions.py:95:5
|
93 | # ruff: disable[YF829]
94 | # ruff: disable[F841, RQW320]
95 | value = 0
| ^^^^^
96 | # ruff: enable[F841, RQW320]
97 | # ruff: enable[YF829]
|
help: Remove assignment to unused variable `value`
92 | # Unknown rule codes
93 | # ruff: disable[YF829]
94 | # ruff: disable[F841, RQW320]
- value = 0
95 + pass
96 | # ruff: enable[F841, RQW320]
97 | # ruff: enable[YF829]
note: This is an unsafe fix and may change runtime behavior
--- Added --- --- Added ---
RUF104 Unmatched suppression comment RUF104 Unmatched suppression comment
@ -370,6 +391,17 @@ RUF104 Unmatched suppression comment
| |
RUF104 Unmatched suppression comment
--> suppressions.py:69:5
|
67 | # and the other should trigger an unused suppression diagnostic
68 | # ruff: disable[F841]
69 | # ruff: disable[F841]
| ^^^^^^^^^^^^^^^^^^^^^
70 | foo = 0
|
RUF100 [*] Unused suppression (unused: `F841`) RUF100 [*] Unused suppression (unused: `F841`)
--> suppressions.py:69:5 --> suppressions.py:69:5
| |
@ -389,17 +421,6 @@ help: Remove unused suppression
71 | 71 |
RUF104 Unmatched suppression comment
--> suppressions.py:69:5
|
67 | # and the other should trigger an unused suppression diagnostic
68 | # ruff: disable[F841]
69 | # ruff: disable[F841]
| ^^^^^^^^^^^^^^^^^^^^^
70 | foo = 0
|
RUF104 Unmatched suppression comment RUF104 Unmatched suppression comment
--> suppressions.py:75:5 --> suppressions.py:75:5
| |
@ -509,6 +530,8 @@ help: Remove unused suppression
- # ruff: disable[E741, F401, F841] - # ruff: disable[E741, F401, F841]
87 + # ruff: disable[F401, F841] 87 + # ruff: disable[F401, F841]
88 | print("hello") 88 | print("hello")
89 |
90 |
RUF100 [*] Unused suppression (non-enabled: `F401`) RUF100 [*] Unused suppression (non-enabled: `F401`)
@ -527,6 +550,8 @@ help: Remove unused suppression
- # ruff: disable[E741, F401, F841] - # ruff: disable[E741, F401, F841]
87 + # ruff: disable[E741, F841] 87 + # ruff: disable[E741, F841]
88 | print("hello") 88 | print("hello")
89 |
90 |
RUF100 [*] Unused suppression (unused: `F841`) RUF100 [*] Unused suppression (unused: `F841`)
@ -545,3 +570,79 @@ help: Remove unused suppression
- # ruff: disable[E741, F401, F841] - # ruff: disable[E741, F401, F841]
87 + # ruff: disable[E741, F401] 87 + # ruff: disable[E741, F401]
88 | print("hello") 88 | print("hello")
89 |
90 |
RUF102 [*] Invalid rule code in `# noqa`: YF829
--> suppressions.py:93:5
|
91 | def f():
92 | # Unknown rule codes
93 | # ruff: disable[YF829]
| ^^^^^^^^^^^^^^^^^^^^^^
94 | # ruff: disable[F841, RQW320]
95 | value = 0
|
help: Remove the rule code
90 |
91 | def f():
92 | # Unknown rule codes
- # ruff: disable[YF829]
93 | # ruff: disable[F841, RQW320]
94 | value = 0
95 | # ruff: enable[F841, RQW320]
RUF102 [*] Invalid rule code in `# noqa`: RQW320
--> suppressions.py:94:27
|
92 | # Unknown rule codes
93 | # ruff: disable[YF829]
94 | # ruff: disable[F841, RQW320]
| ^^^^^^
95 | value = 0
96 | # ruff: enable[F841, RQW320]
|
help: Remove the rule code
91 | def f():
92 | # Unknown rule codes
93 | # ruff: disable[YF829]
- # ruff: disable[F841, RQW320]
94 + # ruff: disable[F841]
95 | value = 0
96 | # ruff: enable[F841, RQW320]
97 | # ruff: enable[YF829]
RUF102 [*] Invalid rule code in `# noqa`: RQW320
--> suppressions.py:96:26
|
94 | # ruff: disable[F841, RQW320]
95 | value = 0
96 | # ruff: enable[F841, RQW320]
| ^^^^^^
97 | # ruff: enable[YF829]
|
help: Remove the rule code
93 | # ruff: disable[YF829]
94 | # ruff: disable[F841, RQW320]
95 | value = 0
- # ruff: enable[F841, RQW320]
96 + # ruff: enable[F841]
97 | # ruff: enable[YF829]
RUF102 [*] Invalid rule code in `# noqa`: YF829
--> suppressions.py:97:5
|
95 | value = 0
96 | # ruff: enable[F841, RQW320]
97 | # ruff: enable[YF829]
| ^^^^^^^^^^^^^^^^^^^^^
|
help: Remove the rule code
94 | # ruff: disable[F841, RQW320]
95 | value = 0
96 | # ruff: enable[F841, RQW320]
- # ruff: enable[YF829]

View File

@ -1,6 +1,6 @@
use compact_str::CompactString; use compact_str::CompactString;
use core::fmt; use core::fmt;
use ruff_db::diagnostic::Diagnostic; use ruff_db::diagnostic::{self, Diagnostic};
use ruff_diagnostics::{Edit, Fix}; use ruff_diagnostics::{Edit, Fix};
use ruff_python_ast::token::{TokenKind, Tokens}; use ruff_python_ast::token::{TokenKind, Tokens};
use ruff_python_ast::whitespace::indentation; use ruff_python_ast::whitespace::indentation;
@ -19,8 +19,8 @@ use crate::codes::Rule;
use crate::fix::edits::delete_comment; use crate::fix::edits::delete_comment;
use crate::preview::is_range_suppressions_enabled; use crate::preview::is_range_suppressions_enabled;
use crate::rules::ruff::rules::{ use crate::rules::ruff::rules::{
InvalidSuppressionComment, InvalidSuppressionCommentKind, UnmatchedSuppressionComment, InvalidRuleCode, InvalidSuppressionComment, InvalidSuppressionCommentKind,
UnusedCodes, UnusedNOQA, UnusedNOQAKind, UnmatchedSuppressionComment, UnusedCodes, UnusedNOQA, UnusedNOQAKind,
}; };
use crate::settings::LinterSettings; use crate::settings::LinterSettings;
@ -217,6 +217,26 @@ impl Suppressions {
} }
} }
if context.is_rule_enabled(Rule::InvalidRuleCode) {
for suppression in self
.valid
.iter()
.filter(|suppression| Rule::from_code(&suppression.code).is_err())
{
for comment in &suppression.comments {
let (range, edit) =
Suppressions::delete_code_or_comment(locator, suppression, comment);
let mut diagnostic = context.report_diagnostic(
InvalidRuleCode {
rule_code: suppression.code.to_string(),
},
range,
);
diagnostic.set_fix(Fix::safe_edit(edit));
}
}
}
if context.is_rule_enabled(Rule::InvalidSuppressionComment) { if context.is_rule_enabled(Rule::InvalidSuppressionComment) {
// missing codes already handled above, report the rest as invalid comments // missing codes already handled above, report the rest as invalid comments
for error in self for error in self
@ -262,6 +282,7 @@ impl Suppressions {
} }
} }
} }
fn delete_code_or_comment( fn delete_code_or_comment(
locator: &Locator<'_>, locator: &Locator<'_>,
suppression: &Suppression, suppression: &Suppression,