diff --git a/crates/ruff/tests/lint.rs b/crates/ruff/tests/lint.rs index 579d185d53..01e9bc4583 100644 --- a/crates/ruff/tests/lint.rs +++ b/crates/ruff/tests/lint.rs @@ -933,3 +933,42 @@ include = ["*.ipy"] Ok(()) } + +#[test] +fn file_noqa_external() -> Result<()> { + let tempdir = TempDir::new()?; + let ruff_toml = tempdir.path().join("ruff.toml"); + fs::write( + &ruff_toml, + r#" +[lint] +external = ["AAA"] +"#, + )?; + + insta::with_settings!({ + filters => vec![(tempdir_filter(&tempdir).as_str(), "[TMP]/")] + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .args(STDIN_BASE_OPTIONS) + .arg("--config") + .arg(&ruff_toml) + .arg("-") + .pass_stdin(r#" +# flake8: noqa: AAA101, BBB102 +import os +"#), @r###" + success: false + exit_code: 1 + ----- stdout ----- + -:3:8: F401 [*] `os` imported but unused + Found 1 error. + [*] 1 fixable with the `--fix` option. + + ----- stderr ----- + warning: Invalid rule code provided to `# ruff: noqa` at -:2: BBB102 + "###); + }); + + Ok(()) +} diff --git a/crates/ruff_linter/src/checkers/noqa.rs b/crates/ruff_linter/src/checkers/noqa.rs index 8e01d671ce..58a1efed90 100644 --- a/crates/ruff_linter/src/checkers/noqa.rs +++ b/crates/ruff_linter/src/checkers/noqa.rs @@ -29,7 +29,13 @@ pub(crate) fn check_noqa( settings: &LinterSettings, ) -> Vec { // Identify any codes that are globally exempted (within the current file). - let exemption = FileExemption::try_extract(locator.contents(), comment_ranges, path, locator); + let exemption = FileExemption::try_extract( + locator.contents(), + comment_ranges, + &settings.external, + path, + locator, + ); // Extract all `noqa` directives. let mut noqa_directives = NoqaDirectives::from_commented_ranges(comment_ranges, path, locator); diff --git a/crates/ruff_linter/src/linter.rs b/crates/ruff_linter/src/linter.rs index e5a4287f67..66f98ef3bf 100644 --- a/crates/ruff_linter/src/linter.rs +++ b/crates/ruff_linter/src/linter.rs @@ -407,6 +407,7 @@ pub fn add_noqa_to_path( &diagnostics.0, &locator, indexer.comment_ranges(), + &settings.external, &directives.noqa_line_for, stylist.line_ending(), ) diff --git a/crates/ruff_linter/src/noqa.rs b/crates/ruff_linter/src/noqa.rs index e98f33bcf7..d50c3b1757 100644 --- a/crates/ruff_linter/src/noqa.rs +++ b/crates/ruff_linter/src/noqa.rs @@ -235,6 +235,7 @@ impl FileExemption { pub(crate) fn try_extract( contents: &str, comment_ranges: &CommentRanges, + external: &[String], path: &Path, locator: &Locator, ) -> Option { @@ -263,6 +264,11 @@ impl FileExemption { } ParsedFileExemption::Codes(codes) => { exempt_codes.extend(codes.into_iter().filter_map(|code| { + // Ignore externally-defined rules. + if external.iter().any(|external| code.starts_with(external)) { + return None; + } + if let Ok(rule) = Rule::from_code(get_redirect_target(code).unwrap_or(code)) { Some(rule.noqa_code()) @@ -458,6 +464,7 @@ pub(crate) fn add_noqa( diagnostics: &[Diagnostic], locator: &Locator, comment_ranges: &CommentRanges, + external: &[String], noqa_line_for: &NoqaMapping, line_ending: LineEnding, ) -> Result { @@ -466,6 +473,7 @@ pub(crate) fn add_noqa( diagnostics, locator, comment_ranges, + external, noqa_line_for, line_ending, ); @@ -478,6 +486,7 @@ fn add_noqa_inner( diagnostics: &[Diagnostic], locator: &Locator, comment_ranges: &CommentRanges, + external: &[String], noqa_line_for: &NoqaMapping, line_ending: LineEnding, ) -> (usize, String) { @@ -487,7 +496,8 @@ fn add_noqa_inner( // Whether the file is exempted from all checks. // Codes that are globally exempted (within the current file). - let exemption = FileExemption::try_extract(locator.contents(), comment_ranges, path, locator); + let exemption = + FileExemption::try_extract(locator.contents(), comment_ranges, external, path, locator); let directives = NoqaDirectives::from_commented_ranges(comment_ranges, path, locator); // Mark any non-ignored diagnostics. @@ -1001,6 +1011,7 @@ mod tests { &[], &Locator::new(contents), &CommentRanges::default(), + &[], &noqa_line_for, LineEnding::Lf, ); @@ -1021,6 +1032,7 @@ mod tests { &diagnostics, &Locator::new(contents), &CommentRanges::default(), + &[], &noqa_line_for, LineEnding::Lf, ); @@ -1048,6 +1060,7 @@ mod tests { &diagnostics, &Locator::new(contents), &comment_ranges, + &[], &noqa_line_for, LineEnding::Lf, ); @@ -1075,6 +1088,7 @@ mod tests { &diagnostics, &Locator::new(contents), &comment_ranges, + &[], &noqa_line_for, LineEnding::Lf, );