diff --git a/crates/ruff/resources/test/fixtures/ruff/noqa.py b/crates/ruff/resources/test/fixtures/ruff/noqa.py new file mode 100644 index 0000000000..30e59400c6 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/ruff/noqa.py @@ -0,0 +1,23 @@ +def f(): + # These should both be ignored by the `noqa`. + I = 1 # noqa: E741, F841 + + +def f(): + # These should both be ignored by the `noqa`. + I = 1 # noqa: E741,F841 + + +def f(): + # These should both be ignored by the `noqa`. + I = 1 # noqa: E741 F841 + + +def f(): + # These should both be ignored by the `noqa`. + I = 1 # noqa: E741 , F841 + + +def f(): + # Only `E741` should be ignored by the `noqa`. + I = 1 # noqa: E741.F841 diff --git a/crates/ruff/src/noqa.rs b/crates/ruff/src/noqa.rs index 808ea4ee19..9dbf993ae3 100644 --- a/crates/ruff/src/noqa.rs +++ b/crates/ruff/src/noqa.rs @@ -24,7 +24,6 @@ static NOQA_LINE_REGEX: Lazy = Lazy::new(|| { ) .unwrap() }); -static SPLIT_COMMA_REGEX: Lazy = Lazy::new(|| Regex::new(r"[,\s]").unwrap()); #[derive(Debug)] pub(crate) enum Directive<'a> { @@ -46,12 +45,12 @@ pub(crate) fn extract_noqa_directive<'a>(range: TextRange, locator: &'a Locator) caps.name("trailing_spaces"), ) { (Some(leading_spaces), Some(noqa), Some(codes), Some(trailing_spaces)) => { - let codes: Vec<&str> = SPLIT_COMMA_REGEX - .split(codes.as_str().trim()) + let codes = codes + .as_str() + .split(|c: char| c.is_whitespace() || c == ',') .map(str::trim) .filter(|code| !code.is_empty()) - .collect(); - + .collect_vec(); let start = range.start() + TextSize::try_from(noqa.start()).unwrap(); if codes.is_empty() { #[allow(deprecated)] @@ -105,11 +104,11 @@ fn parse_file_exemption(line: &str) -> ParsedExemption { if remainder.is_empty() { return ParsedExemption::All; } else if let Some(codes) = remainder.strip_prefix(':') { - let codes: Vec<&str> = SPLIT_COMMA_REGEX - .split(codes.trim()) + let codes = codes + .split(|c: char| c.is_whitespace() || c == ',') .map(str::trim) .filter(|code| !code.is_empty()) - .collect(); + .collect_vec(); if codes.is_empty() { warn!("Expected rule codes on `noqa` directive: \"{line}\""); } diff --git a/crates/ruff/src/rules/ruff/mod.rs b/crates/ruff/src/rules/ruff/mod.rs index 7a8f38254b..3bc568f354 100644 --- a/crates/ruff/src/rules/ruff/mod.rs +++ b/crates/ruff/src/rules/ruff/mod.rs @@ -46,6 +46,16 @@ mod tests { Ok(()) } + #[test] + fn noqa() -> Result<()> { + let diagnostics = test_path( + Path::new("ruff/noqa.py"), + &settings::Settings::for_rules(vec![Rule::UnusedVariable, Rule::AmbiguousVariableName]), + )?; + assert_messages!(diagnostics); + Ok(()) + } + #[test] fn ruf100_0() -> Result<()> { let diagnostics = test_path( diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__noqa.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__noqa.snap new file mode 100644 index 0000000000..01c68b7ef6 --- /dev/null +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__noqa.snap @@ -0,0 +1,20 @@ +--- +source: crates/ruff/src/rules/ruff/mod.rs +--- +noqa.py:23:5: F841 [*] Local variable `I` is assigned to but never used + | +23 | def f(): +24 | # Only `E741` should be ignored by the `noqa`. +25 | I = 1 # noqa: E741.F841 + | ^ F841 + | + = help: Remove assignment to unused variable `I` + +ℹ Suggested fix +20 20 | +21 21 | def f(): +22 22 | # Only `E741` should be ignored by the `noqa`. +23 |- I = 1 # noqa: E741.F841 + 23 |+ pass # noqa: E741.F841 + +