Skip to content

Commit d3288fc

Browse files
committed
Refactor suppressions checking into check_noqa
1 parent b344961 commit d3288fc

File tree

3 files changed

+30
-35
lines changed

3 files changed

+30
-35
lines changed

crates/ruff_linter/src/checkers/noqa.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ use crate::rules::pygrep_hooks;
1818
use crate::rules::ruff;
1919
use crate::rules::ruff::rules::{UnusedCodes, UnusedNOQA};
2020
use crate::settings::LinterSettings;
21+
use crate::suppression::Suppressions;
2122
use crate::{Edit, Fix, Locator};
2223

2324
use super::ast::LintContext;
2425

2526
/// RUF100
27+
#[expect(clippy::too_many_arguments)]
2628
pub(crate) fn check_noqa(
2729
context: &mut LintContext,
2830
path: &Path,
@@ -31,6 +33,7 @@ pub(crate) fn check_noqa(
3133
noqa_line_for: &NoqaMapping,
3234
analyze_directives: bool,
3335
settings: &LinterSettings,
36+
suppressions: &Suppressions,
3437
) -> Vec<usize> {
3538
// Identify any codes that are globally exempted (within the current file).
3639
let file_noqa_directives =
@@ -60,11 +63,19 @@ pub(crate) fn check_noqa(
6063
continue;
6164
}
6265

66+
// Apply file-level suppressions first
6367
if exemption.contains_secondary_code(code) {
6468
ignored_diagnostics.push(index);
6569
continue;
6670
}
6771

72+
// Apply ranged suppressions next
73+
if suppressions.check_diagnostic(diagnostic) {
74+
ignored_diagnostics.push(index);
75+
continue;
76+
}
77+
78+
// Apply end-of-line noqa suppressions last
6879
let noqa_offsets = diagnostic
6980
.parent()
7081
.into_iter()

crates/ruff_linter/src/linter.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,20 +326,13 @@ pub fn check_path(
326326
}
327327
}
328328

329-
// Apply range suppressions before noqa, so that #noqa on a line already covered by a range
330-
// will be reported as unused noqa rather than unused range.
331-
// TODO: check if enabled?
332-
{
333-
let suppressions = Suppressions::from_tokens(locator.contents(), tokens);
334-
suppressions.filter_diagnostics(&mut context);
335-
}
336-
337329
// Enforce `noqa` directives.
338330
if noqa.is_enabled()
339331
|| context
340332
.iter_enabled_rules()
341333
.any(|rule_code| rule_code.lint_source().is_noqa())
342334
{
335+
let suppressions = Suppressions::from_tokens(locator.contents(), tokens);
343336
let ignored = check_noqa(
344337
&mut context,
345338
path,
@@ -348,6 +341,7 @@ pub fn check_path(
348341
&directives.noqa_line_for,
349342
parsed.has_valid_syntax(),
350343
settings,
344+
&suppressions,
351345
);
352346
if noqa.is_enabled() {
353347
for index in ignored.iter().rev() {

crates/ruff_linter/src/suppression.rs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use compact_str::CompactString;
22
use core::fmt;
3+
use ruff_db::diagnostic::Diagnostic;
34
use ruff_python_parser::{TokenKind, Tokens};
45
use ruff_source_file::LineRanges;
56
use std::{error::Error, fmt::Formatter};
@@ -9,8 +10,6 @@ use ruff_python_trivia::{Cursor, is_python_whitespace};
910
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize, TextSlice};
1011
use smallvec::{SmallVec, smallvec};
1112

12-
use crate::checkers::ast::LintContext;
13-
1413
#[allow(unused)]
1514
#[derive(Clone, Debug, Eq, PartialEq)]
1615
enum SuppressionAction {
@@ -119,33 +118,24 @@ impl Suppressions {
119118
builder.load_from_tokens(tokens)
120119
}
121120

122-
/// Check reported diagnostics against the set of valid range suppressions, and remove any
123-
/// diagnostics from the context that should be suppressed by those ranges.
124-
pub(crate) fn filter_diagnostics(&self, context: &mut LintContext) {
125-
let mut ignored: Vec<usize> = vec![];
126-
127-
'outer: for (index, diagnostic) in context.iter().enumerate() {
128-
let Some(code) = diagnostic.secondary_code() else {
129-
continue;
130-
};
131-
let Some(span) = diagnostic.primary_span() else {
132-
continue;
133-
};
134-
let Some(range) = span.range() else {
135-
continue;
136-
};
137-
138-
for suppression in &self.valid {
139-
if *code == suppression.code.as_str() && suppression.range.contains_range(range) {
140-
ignored.push(index);
141-
continue 'outer;
142-
}
121+
/// Check if a diagnostic is suppressed by any known range suppressions
122+
pub(crate) fn check_diagnostic(&self, diagnostic: &Diagnostic) -> bool {
123+
let Some(code) = diagnostic.secondary_code() else {
124+
return false;
125+
};
126+
let Some(span) = diagnostic.primary_span() else {
127+
return false;
128+
};
129+
let Some(range) = span.range() else {
130+
return false;
131+
};
132+
133+
for suppression in &self.valid {
134+
if *code == suppression.code.as_str() && suppression.range.contains_range(range) {
135+
return true;
143136
}
144137
}
145-
146-
for index in ignored.iter().rev() {
147-
context.as_mut_vec().swap_remove(*index);
148-
}
138+
false
149139
}
150140
}
151141

0 commit comments

Comments
 (0)