mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
Implement Invalid rule provided
as rule RUF102 with --fix
(#17138)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> Closes #17084 ## Summary This PR adds a new rule (RUF102) to detect and fix invalid rule codes in `noqa` comments. Invalid rule codes in `noqa` directives serve no purpose and may indicate outdated code suppressions. This extends the previous behaviour originating from `crates/ruff_linter/src/noqa.rs` which would only emit a warnigs. With this rule a `--fix` is available. The rule: 1. Analyzes all `noqa` directives to identify invalid rule codes 2. Provides autofix functionality to: - Remove the entire comment if all codes are invalid - Remove only the invalid codes when mixed with valid codes 3. Preserves original comment formatting and whitespace where possible Example cases: - `# noqa: XYZ111` → Remove entire comment (keep empty line) - `# noqa: XYZ222, XYZ333` → Remove entire comment (keep empty line) - `# noqa: F401, INVALID123` → Keep only valid codes (`# noqa: F401`) ## Test Plan - Added tests in `crates/ruff_linter/resources/test/fixtures/ruff/RUF102.py` covering different example cases. <!-- How was it tested? --> ## Notes - This does not handle cases where parsing fails. E.g. `# noqa: NON_EXISTENT, ANOTHER_INVALID` causes a `LexicalError` and the diagnostic is not propagated and we cannot handle the diagnostic. I am also unsure what proper `fix` handling would be and making the user aware we don't understand the codes is probably the best bet. - The rule is added to the Preview rule group as it's a new addition ## Questions - Should we remove the warnings, now that we have a rule? - Is the current fix behavior appropriate for all cases, particularly the handling of whitespace and line deletions? - I'm new to the codebase; let me know if there are rule utilities which could have used but didn't. --------- Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
a4ba10ff0a
commit
98b95c9c38
9 changed files with 605 additions and 0 deletions
18
crates/ruff_linter/resources/test/fixtures/ruff/RUF102.py
vendored
Normal file
18
crates/ruff_linter/resources/test/fixtures/ruff/RUF102.py
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Invalid code
|
||||||
|
import os # noqa: INVALID123
|
||||||
|
# External code
|
||||||
|
import re # noqa: V123
|
||||||
|
# Valid noqa
|
||||||
|
import sys # noqa: E402
|
||||||
|
from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
# Succeeding comment
|
||||||
|
import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
# Mixed valid and invalid
|
||||||
|
from typing import List # noqa: F401, INVALID123
|
||||||
|
# Test for multiple invalid
|
||||||
|
from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
# Test for preserving valid codes when fixing
|
||||||
|
from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
# Test for mixed code types
|
||||||
|
import json # noqa: E402, INVALID400, V100
|
|
@ -227,6 +227,13 @@ pub(crate) fn check_noqa(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if settings.rules.enabled(Rule::InvalidRuleCode)
|
||||||
|
&& !per_file_ignores.contains(Rule::InvalidRuleCode)
|
||||||
|
&& !exemption.enumerates(Rule::InvalidRuleCode)
|
||||||
|
{
|
||||||
|
ruff::rules::invalid_noqa_code(diagnostics, &noqa_directives, locator, &settings.external);
|
||||||
|
}
|
||||||
|
|
||||||
ignored_diagnostics.sort_unstable();
|
ignored_diagnostics.sort_unstable();
|
||||||
ignored_diagnostics
|
ignored_diagnostics
|
||||||
}
|
}
|
||||||
|
|
|
@ -1016,6 +1016,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||||
(Ruff, "059") => (RuleGroup::Preview, rules::ruff::rules::UnusedUnpackedVariable),
|
(Ruff, "059") => (RuleGroup::Preview, rules::ruff::rules::UnusedUnpackedVariable),
|
||||||
(Ruff, "100") => (RuleGroup::Stable, rules::ruff::rules::UnusedNOQA),
|
(Ruff, "100") => (RuleGroup::Stable, rules::ruff::rules::UnusedNOQA),
|
||||||
(Ruff, "101") => (RuleGroup::Stable, rules::ruff::rules::RedirectedNOQA),
|
(Ruff, "101") => (RuleGroup::Stable, rules::ruff::rules::RedirectedNOQA),
|
||||||
|
(Ruff, "102") => (RuleGroup::Preview, rules::ruff::rules::InvalidRuleCode),
|
||||||
|
|
||||||
(Ruff, "200") => (RuleGroup::Stable, rules::ruff::rules::InvalidPyprojectToml),
|
(Ruff, "200") => (RuleGroup::Stable, rules::ruff::rules::InvalidPyprojectToml),
|
||||||
#[cfg(any(feature = "test-rules", test))]
|
#[cfg(any(feature = "test-rules", test))]
|
||||||
|
|
|
@ -99,6 +99,7 @@ mod tests {
|
||||||
#[test_case(Rule::UnusedUnpackedVariable, Path::new("RUF059_3.py"))]
|
#[test_case(Rule::UnusedUnpackedVariable, Path::new("RUF059_3.py"))]
|
||||||
#[test_case(Rule::RedirectedNOQA, Path::new("RUF101_0.py"))]
|
#[test_case(Rule::RedirectedNOQA, Path::new("RUF101_0.py"))]
|
||||||
#[test_case(Rule::RedirectedNOQA, Path::new("RUF101_1.py"))]
|
#[test_case(Rule::RedirectedNOQA, Path::new("RUF101_1.py"))]
|
||||||
|
#[test_case(Rule::InvalidRuleCode, Path::new("RUF102.py"))]
|
||||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||||
let diagnostics = test_path(
|
let diagnostics = test_path(
|
||||||
|
@ -314,6 +315,20 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_rule_code_external_rules() -> Result<()> {
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("ruff/RUF102.py"),
|
||||||
|
&settings::LinterSettings {
|
||||||
|
external: vec!["V".to_string()],
|
||||||
|
..settings::LinterSettings::for_rule(Rule::InvalidRuleCode)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_messages!(diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ruff_per_file_ignores() -> Result<()> {
|
fn ruff_per_file_ignores() -> Result<()> {
|
||||||
let diagnostics = test_path(
|
let diagnostics = test_path(
|
||||||
|
|
160
crates/ruff_linter/src/rules/ruff/rules/invalid_rule_code.rs
Normal file
160
crates/ruff_linter/src/rules/ruff/rules/invalid_rule_code.rs
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
use crate::noqa::{Code, Directive};
|
||||||
|
use crate::registry::Rule;
|
||||||
|
use crate::Locator;
|
||||||
|
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||||
|
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||||
|
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||||
|
|
||||||
|
use crate::noqa::{Codes, NoqaDirectives};
|
||||||
|
|
||||||
|
/// ## What it does
|
||||||
|
/// Checks for `noqa` codes that are invalid.
|
||||||
|
///
|
||||||
|
/// ## Why is this bad?
|
||||||
|
/// Invalid rule codes serve no purpose and may indicate outdated code suppressions.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```python
|
||||||
|
/// import os # noqa: XYZ999
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// import os
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Or if there are still valid codes needed:
|
||||||
|
/// ```python
|
||||||
|
/// import os # noqa: E402
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Options
|
||||||
|
/// - `lint.external`
|
||||||
|
#[derive(ViolationMetadata)]
|
||||||
|
pub(crate) struct InvalidRuleCode {
|
||||||
|
pub(crate) rule_code: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AlwaysFixableViolation for InvalidRuleCode {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Invalid rule code in `# noqa`: {}", self.rule_code)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fix_title(&self) -> String {
|
||||||
|
"Remove the rule code".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RUF102 for invalid noqa codes
|
||||||
|
pub(crate) fn invalid_noqa_code(
|
||||||
|
diagnostics: &mut Vec<Diagnostic>,
|
||||||
|
noqa_directives: &NoqaDirectives,
|
||||||
|
locator: &Locator,
|
||||||
|
external: &[String],
|
||||||
|
) {
|
||||||
|
for line in noqa_directives.lines() {
|
||||||
|
let Directive::Codes(directive) = &line.directive else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let all_valid = directive.iter().all(|code| code_is_valid(code, external));
|
||||||
|
|
||||||
|
if all_valid {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (valid_codes, invalid_codes): (Vec<_>, Vec<_>) = directive
|
||||||
|
.iter()
|
||||||
|
.partition(|&code| code_is_valid(code, external));
|
||||||
|
|
||||||
|
if valid_codes.is_empty() {
|
||||||
|
diagnostics.push(all_codes_invalid_diagnostic(directive, invalid_codes));
|
||||||
|
} else {
|
||||||
|
diagnostics.extend(invalid_codes.into_iter().map(|invalid_code| {
|
||||||
|
some_codes_are_invalid_diagnostic(directive, invalid_code, locator)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn code_is_valid(code: &Code, external: &[String]) -> bool {
|
||||||
|
let code_str = code.as_str();
|
||||||
|
Rule::from_code(code_str).is_ok() || external.iter().any(|ext| code_str.starts_with(ext))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_codes_invalid_diagnostic(
|
||||||
|
directive: &Codes<'_>,
|
||||||
|
invalid_codes: Vec<&Code<'_>>,
|
||||||
|
) -> Diagnostic {
|
||||||
|
Diagnostic::new(
|
||||||
|
InvalidRuleCode {
|
||||||
|
rule_code: invalid_codes
|
||||||
|
.into_iter()
|
||||||
|
.map(Code::as_str)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", "),
|
||||||
|
},
|
||||||
|
directive.range(),
|
||||||
|
)
|
||||||
|
.with_fix(Fix::safe_edit(Edit::range_deletion(directive.range())))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn some_codes_are_invalid_diagnostic(
|
||||||
|
codes: &Codes,
|
||||||
|
invalid_code: &Code,
|
||||||
|
locator: &Locator,
|
||||||
|
) -> Diagnostic {
|
||||||
|
let diagnostic = Diagnostic::new(
|
||||||
|
InvalidRuleCode {
|
||||||
|
rule_code: invalid_code.to_string(),
|
||||||
|
},
|
||||||
|
invalid_code.range(),
|
||||||
|
);
|
||||||
|
diagnostic.with_fix(Fix::safe_edit(remove_invalid_noqa(
|
||||||
|
codes,
|
||||||
|
invalid_code,
|
||||||
|
locator,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_invalid_noqa(codes: &Codes, invalid_code: &Code, locator: &Locator) -> Edit {
|
||||||
|
// Is this the first code after the `:` that needs to get deleted
|
||||||
|
// For the first element, delete from after the `:` to the next comma (including)
|
||||||
|
// For any other element, delete from the previous comma (including) to the next comma (excluding)
|
||||||
|
let mut first = false;
|
||||||
|
|
||||||
|
// Find the index of the previous comma or colon.
|
||||||
|
let start = locator
|
||||||
|
.slice(TextRange::new(codes.start(), invalid_code.start()))
|
||||||
|
.rmatch_indices([',', ':'])
|
||||||
|
.next()
|
||||||
|
.map(|(offset, text)| {
|
||||||
|
let offset = codes.start() + TextSize::try_from(offset).unwrap();
|
||||||
|
if text == ":" {
|
||||||
|
first = true;
|
||||||
|
// Don't include the colon in the deletion range, or the noqa comment becomes invalid
|
||||||
|
offset + ':'.text_len()
|
||||||
|
} else {
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(invalid_code.start());
|
||||||
|
|
||||||
|
// Find the index of the trailing comma (if any)
|
||||||
|
let end = locator
|
||||||
|
.slice(TextRange::new(invalid_code.end(), codes.end()))
|
||||||
|
.find(',')
|
||||||
|
.map(|offset| {
|
||||||
|
let offset = invalid_code.end() + TextSize::try_from(offset).unwrap();
|
||||||
|
|
||||||
|
if first {
|
||||||
|
offset + ','.text_len()
|
||||||
|
} else {
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(invalid_code.end());
|
||||||
|
|
||||||
|
Edit::range_deletion(TextRange::new(start, end))
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ pub(crate) use invalid_assert_message_literal_argument::*;
|
||||||
pub(crate) use invalid_formatter_suppression_comment::*;
|
pub(crate) use invalid_formatter_suppression_comment::*;
|
||||||
pub(crate) use invalid_index_type::*;
|
pub(crate) use invalid_index_type::*;
|
||||||
pub(crate) use invalid_pyproject_toml::*;
|
pub(crate) use invalid_pyproject_toml::*;
|
||||||
|
pub(crate) use invalid_rule_code::*;
|
||||||
pub(crate) use map_int_version_parsing::*;
|
pub(crate) use map_int_version_parsing::*;
|
||||||
pub(crate) use missing_fstring_syntax::*;
|
pub(crate) use missing_fstring_syntax::*;
|
||||||
pub(crate) use mutable_class_default::*;
|
pub(crate) use mutable_class_default::*;
|
||||||
|
@ -78,6 +79,7 @@ mod invalid_assert_message_literal_argument;
|
||||||
mod invalid_formatter_suppression_comment;
|
mod invalid_formatter_suppression_comment;
|
||||||
mod invalid_index_type;
|
mod invalid_index_type;
|
||||||
mod invalid_pyproject_toml;
|
mod invalid_pyproject_toml;
|
||||||
|
mod invalid_rule_code;
|
||||||
mod map_int_version_parsing;
|
mod map_int_version_parsing;
|
||||||
mod missing_fstring_syntax;
|
mod missing_fstring_syntax;
|
||||||
mod mutable_class_default;
|
mod mutable_class_default;
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||||
|
---
|
||||||
|
RUF102.py:2:12: RUF102 [*] Invalid rule code in `# noqa`: INVALID123
|
||||||
|
|
|
||||||
|
1 | # Invalid code
|
||||||
|
2 | import os # noqa: INVALID123
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ RUF102
|
||||||
|
3 | # External code
|
||||||
|
4 | import re # noqa: V123
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Invalid code
|
||||||
|
2 |-import os # noqa: INVALID123
|
||||||
|
2 |+import os
|
||||||
|
3 3 | # External code
|
||||||
|
4 4 | import re # noqa: V123
|
||||||
|
5 5 | # Valid noqa
|
||||||
|
|
||||||
|
RUF102.py:4:12: RUF102 [*] Invalid rule code in `# noqa`: V123
|
||||||
|
|
|
||||||
|
2 | import os # noqa: INVALID123
|
||||||
|
3 | # External code
|
||||||
|
4 | import re # noqa: V123
|
||||||
|
| ^^^^^^^^^^^^ RUF102
|
||||||
|
5 | # Valid noqa
|
||||||
|
6 | import sys # noqa: E402
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Invalid code
|
||||||
|
2 2 | import os # noqa: INVALID123
|
||||||
|
3 3 | # External code
|
||||||
|
4 |-import re # noqa: V123
|
||||||
|
4 |+import re
|
||||||
|
5 5 | # Valid noqa
|
||||||
|
6 6 | import sys # noqa: E402
|
||||||
|
7 7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
|
||||||
|
RUF102.py:7:65: RUF102 [*] Invalid rule code in `# noqa`: INVALID456
|
||||||
|
|
|
||||||
|
5 | # Valid noqa
|
||||||
|
6 | import sys # noqa: E402
|
||||||
|
7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 | # Succeeding comment
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
4 4 | import re # noqa: V123
|
||||||
|
5 5 | # Valid noqa
|
||||||
|
6 6 | import sys # noqa: E402
|
||||||
|
7 |-from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
7 |+from functools import cache # Preceeding comment # noqa: F401
|
||||||
|
8 8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
|
||||||
|
RUF102.py:8:53: RUF102 [*] Invalid rule code in `# noqa`: INVALID789
|
||||||
|
|
|
||||||
|
6 | import sys # noqa: E402
|
||||||
|
7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ RUF102
|
||||||
|
9 | # Succeeding comment
|
||||||
|
10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
5 5 | # Valid noqa
|
||||||
|
6 6 | import sys # noqa: E402
|
||||||
|
7 7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
8 |-from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
8 |+from itertools import product # Preceeding comment
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
|
||||||
|
RUF102.py:10:13: RUF102 [*] Invalid rule code in `# noqa`: INVALID000
|
||||||
|
|
|
||||||
|
8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 | # Succeeding comment
|
||||||
|
10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ RUF102
|
||||||
|
11 | # Mixed valid and invalid
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
7 7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
8 8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 |-import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
10 |+import math # Succeeding comment
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
|
||||||
|
RUF102.py:12:40: RUF102 [*] Invalid rule code in `# noqa`: INVALID123
|
||||||
|
|
|
||||||
|
10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
11 | # Mixed valid and invalid
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
13 | # Test for multiple invalid
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 |-from typing import List # noqa: F401, INVALID123
|
||||||
|
12 |+from typing import List # noqa: F401
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
|
||||||
|
RUF102.py:14:46: RUF102 [*] Invalid rule code in `# noqa`: INVALID100
|
||||||
|
|
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 | # Test for multiple invalid
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
15 | # Test for preserving valid codes when fixing
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 |-from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
14 |+from collections import defaultdict # noqa: INVALID200, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
|
||||||
|
RUF102.py:14:58: RUF102 [*] Invalid rule code in `# noqa`: INVALID200
|
||||||
|
|
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 | # Test for multiple invalid
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
15 | # Test for preserving valid codes when fixing
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 |-from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
14 |+from collections import defaultdict # noqa: INVALID100, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
|
||||||
|
RUF102.py:16:44: RUF102 [*] Invalid rule code in `# noqa`: INVALID300
|
||||||
|
|
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
15 | # Test for preserving valid codes when fixing
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
17 | # Test for mixed code types
|
||||||
|
18 | import json # noqa: E402, INVALID400, V100
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 |-from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
16 |+from itertools import chain # noqa: E402, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
18 18 | import json # noqa: E402, INVALID400, V100
|
||||||
|
|
||||||
|
RUF102.py:18:28: RUF102 [*] Invalid rule code in `# noqa`: INVALID400
|
||||||
|
|
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 | # Test for mixed code types
|
||||||
|
18 | import json # noqa: E402, INVALID400, V100
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
18 |-import json # noqa: E402, INVALID400, V100
|
||||||
|
18 |+import json # noqa: E402, V100
|
||||||
|
|
||||||
|
RUF102.py:18:40: RUF102 [*] Invalid rule code in `# noqa`: V100
|
||||||
|
|
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 | # Test for mixed code types
|
||||||
|
18 | import json # noqa: E402, INVALID400, V100
|
||||||
|
| ^^^^ RUF102
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
18 |-import json # noqa: E402, INVALID400, V100
|
||||||
|
18 |+import json # noqa: E402, INVALID400
|
|
@ -0,0 +1,182 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||||
|
---
|
||||||
|
RUF102.py:2:12: RUF102 [*] Invalid rule code in `# noqa`: INVALID123
|
||||||
|
|
|
||||||
|
1 | # Invalid code
|
||||||
|
2 | import os # noqa: INVALID123
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ RUF102
|
||||||
|
3 | # External code
|
||||||
|
4 | import re # noqa: V123
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Invalid code
|
||||||
|
2 |-import os # noqa: INVALID123
|
||||||
|
2 |+import os
|
||||||
|
3 3 | # External code
|
||||||
|
4 4 | import re # noqa: V123
|
||||||
|
5 5 | # Valid noqa
|
||||||
|
|
||||||
|
RUF102.py:7:65: RUF102 [*] Invalid rule code in `# noqa`: INVALID456
|
||||||
|
|
|
||||||
|
5 | # Valid noqa
|
||||||
|
6 | import sys # noqa: E402
|
||||||
|
7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 | # Succeeding comment
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
4 4 | import re # noqa: V123
|
||||||
|
5 5 | # Valid noqa
|
||||||
|
6 6 | import sys # noqa: E402
|
||||||
|
7 |-from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
7 |+from functools import cache # Preceeding comment # noqa: F401
|
||||||
|
8 8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
|
||||||
|
RUF102.py:8:53: RUF102 [*] Invalid rule code in `# noqa`: INVALID789
|
||||||
|
|
|
||||||
|
6 | import sys # noqa: E402
|
||||||
|
7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ RUF102
|
||||||
|
9 | # Succeeding comment
|
||||||
|
10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
5 5 | # Valid noqa
|
||||||
|
6 6 | import sys # noqa: E402
|
||||||
|
7 7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
8 |-from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
8 |+from itertools import product # Preceeding comment
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
|
||||||
|
RUF102.py:10:13: RUF102 [*] Invalid rule code in `# noqa`: INVALID000
|
||||||
|
|
|
||||||
|
8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 | # Succeeding comment
|
||||||
|
10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ RUF102
|
||||||
|
11 | # Mixed valid and invalid
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
7 7 | from functools import cache # Preceeding comment # noqa: F401, INVALID456
|
||||||
|
8 8 | from itertools import product # Preceeding comment # noqa: INVALID789
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 |-import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
10 |+import math # Succeeding comment
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
|
||||||
|
RUF102.py:12:40: RUF102 [*] Invalid rule code in `# noqa`: INVALID123
|
||||||
|
|
|
||||||
|
10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
11 | # Mixed valid and invalid
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
13 | # Test for multiple invalid
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
9 9 | # Succeeding comment
|
||||||
|
10 10 | import math # noqa: INVALID000 # Succeeding comment
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 |-from typing import List # noqa: F401, INVALID123
|
||||||
|
12 |+from typing import List # noqa: F401
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
|
||||||
|
RUF102.py:14:46: RUF102 [*] Invalid rule code in `# noqa`: INVALID100
|
||||||
|
|
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 | # Test for multiple invalid
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
15 | # Test for preserving valid codes when fixing
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 |-from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
14 |+from collections import defaultdict # noqa: INVALID200, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
|
||||||
|
RUF102.py:14:58: RUF102 [*] Invalid rule code in `# noqa`: INVALID200
|
||||||
|
|
|
||||||
|
12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 | # Test for multiple invalid
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
15 | # Test for preserving valid codes when fixing
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
11 11 | # Mixed valid and invalid
|
||||||
|
12 12 | from typing import List # noqa: F401, INVALID123
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 |-from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
14 |+from collections import defaultdict # noqa: INVALID100, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
|
||||||
|
RUF102.py:16:44: RUF102 [*] Invalid rule code in `# noqa`: INVALID300
|
||||||
|
|
|
||||||
|
14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
15 | # Test for preserving valid codes when fixing
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
17 | # Test for mixed code types
|
||||||
|
18 | import json # noqa: E402, INVALID400, V100
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
13 13 | # Test for multiple invalid
|
||||||
|
14 14 | from collections import defaultdict # noqa: INVALID100, INVALID200, F401
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 |-from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
16 |+from itertools import chain # noqa: E402, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
18 18 | import json # noqa: E402, INVALID400, V100
|
||||||
|
|
||||||
|
RUF102.py:18:28: RUF102 [*] Invalid rule code in `# noqa`: INVALID400
|
||||||
|
|
|
||||||
|
16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 | # Test for mixed code types
|
||||||
|
18 | import json # noqa: E402, INVALID400, V100
|
||||||
|
| ^^^^^^^^^^ RUF102
|
||||||
|
|
|
||||||
|
= help: Remove the rule code
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
15 15 | # Test for preserving valid codes when fixing
|
||||||
|
16 16 | from itertools import chain # noqa: E402, INVALID300, F401
|
||||||
|
17 17 | # Test for mixed code types
|
||||||
|
18 |-import json # noqa: E402, INVALID400, V100
|
||||||
|
18 |+import json # noqa: E402, V100
|
1
ruff.schema.json
generated
1
ruff.schema.json
generated
|
@ -4028,6 +4028,7 @@
|
||||||
"RUF10",
|
"RUF10",
|
||||||
"RUF100",
|
"RUF100",
|
||||||
"RUF101",
|
"RUF101",
|
||||||
|
"RUF102",
|
||||||
"RUF2",
|
"RUF2",
|
||||||
"RUF20",
|
"RUF20",
|
||||||
"RUF200",
|
"RUF200",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue