From 12f11d5ebc37333057bf9192853fbb892d5cc280 Mon Sep 17 00:00:00 2001 From: Amethyst Reese Date: Wed, 11 Feb 2026 16:03:42 -0800 Subject: [PATCH 1/3] Ensure pending suppression diagnostics are registered Fix #23235 --- crates/ruff_linter/src/suppression.rs | 115 ++++++++++++++------------ 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/crates/ruff_linter/src/suppression.rs b/crates/ruff_linter/src/suppression.rs index 85bffc19d5237..0c7bc7f97949c 100644 --- a/crates/ruff_linter/src/suppression.rs +++ b/crates/ruff_linter/src/suppression.rs @@ -222,60 +222,71 @@ impl Suppressions { pub(crate) fn check_suppressions(&self, context: &LintContext, locator: &Locator) { let mut grouped_diagnostic: Option<(TextRange, SuppressionDiagnostic)> = None; let mut unmatched_ranges = FxHashSet::default(); + + let process_pending_diagnostics = + |key: Option, + grouped_diagnostic: &Option<(TextRange, SuppressionDiagnostic)>| + -> bool { + if let Some((group_key, group)) = grouped_diagnostic + && (key.is_none() || key.is_some_and(|key| key != *group_key)) + { + if group.any_invalid() { + Suppressions::report_suppression_codes( + context, + locator, + group.suppression, + &group.invalid_codes, + true, + InvalidRuleCode { + rule_code: group.invalid_codes.iter().join(", "), + kind: InvalidRuleCodeKind::Suppression, + whole_comment: group.suppression.codes().len() + == group.invalid_codes.len(), + }, + ); + } + if group.any_unused() { + let mut codes = group.disabled_codes.clone(); + codes.extend(group.unused_codes.clone()); + Suppressions::report_suppression_codes( + context, + locator, + group.suppression, + &codes, + false, + UnusedNOQA { + codes: Some(UnusedCodes { + disabled: group + .disabled_codes + .iter() + .map(ToString::to_string) + .collect_vec(), + duplicated: group + .duplicated_codes + .iter() + .map(ToString::to_string) + .collect_vec(), + unmatched: group + .unused_codes + .iter() + .map(ToString::to_string) + .collect_vec(), + ..Default::default() + }), + kind: UnusedNOQAKind::Suppression, + }, + ); + } + true + } else { + false + } + }; + for suppression in &self.valid { let key = suppression.comments.disable_comment().range; - // Process any pending grouped diagnostics - if let Some((group_key, ref group)) = grouped_diagnostic - && key != group_key - { - if group.any_invalid() { - Suppressions::report_suppression_codes( - context, - locator, - group.suppression, - &group.invalid_codes, - true, - InvalidRuleCode { - rule_code: group.invalid_codes.iter().join(", "), - kind: InvalidRuleCodeKind::Suppression, - whole_comment: group.suppression.codes().len() - == group.invalid_codes.len(), - }, - ); - } - if group.any_unused() { - let mut codes = group.disabled_codes.clone(); - codes.extend(group.unused_codes.clone()); - Suppressions::report_suppression_codes( - context, - locator, - group.suppression, - &codes, - false, - UnusedNOQA { - codes: Some(UnusedCodes { - disabled: group - .disabled_codes - .iter() - .map(ToString::to_string) - .collect_vec(), - duplicated: group - .duplicated_codes - .iter() - .map(ToString::to_string) - .collect_vec(), - unmatched: group - .unused_codes - .iter() - .map(ToString::to_string) - .collect_vec(), - ..Default::default() - }), - kind: UnusedNOQAKind::Suppression, - }, - ); - } + if process_pending_diagnostics(Some(key), &grouped_diagnostic) { grouped_diagnostic = None; } @@ -324,6 +335,8 @@ impl Suppressions { } } + process_pending_diagnostics(None, &grouped_diagnostic); + if context.is_rule_enabled(Rule::InvalidSuppressionComment) { for error in &self.errors { context From 8f1dfcb6867867ae90cc94562b370502e1677e75 Mon Sep 17 00:00:00 2001 From: Amethyst Reese Date: Thu, 12 Feb 2026 09:26:58 -0800 Subject: [PATCH 2/3] add test case --- .../test/fixtures/ruff/suppressions.py | 7 ++++++ ...ules__ruff__tests__range_suppressions.snap | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/crates/ruff_linter/resources/test/fixtures/ruff/suppressions.py b/crates/ruff_linter/resources/test/fixtures/ruff/suppressions.py index 5f4b38f1fd8d7..6fbf4bf12cc8b 100644 --- a/crates/ruff_linter/resources/test/fixtures/ruff/suppressions.py +++ b/crates/ruff_linter/resources/test/fixtures/ruff/suppressions.py @@ -109,3 +109,10 @@ def f(): # ruff: disable # ruff: disable[] print("hello") + + +# Ensure LAST suppression in file is reported. +# https://github.com/astral-sh/ruff/issues/23235 +# ruff:disable[F401] +print("goodbye") +# ruff:enable[F401] diff --git a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__range_suppressions.snap b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__range_suppressions.snap index 11062f512a75f..5ad92799b364e 100644 --- a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__range_suppressions.snap +++ b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__range_suppressions.snap @@ -382,6 +382,7 @@ help: Remove suppression comment - # ruff: disable 109 | # ruff: disable[] 110 | print("hello") +111 | note: This is an unsafe fix and may change runtime behavior RUF103 [*] Invalid suppression comment: missing suppression codes like `[E501, ...]` @@ -399,4 +400,25 @@ help: Remove suppression comment 109 | # ruff: disable - # ruff: disable[] 110 | print("hello") +111 | +112 | note: This is an unsafe fix and may change runtime behavior + +RUF100 [*] Unused suppression (non-enabled: `F401`) + --> suppressions.py:116:1 + | +114 | # Ensure LAST suppression in file is reported. +115 | # https://github.com/astral-sh/ruff/issues/23235 +116 | # ruff:disable[F401] + | ^^^^^^^^^^^^^^^^^^^^ +117 | print("goodbye") +118 | # ruff:enable[F401] + | ------------------- + | +help: Remove unused suppression +113 | +114 | # Ensure LAST suppression in file is reported. +115 | # https://github.com/astral-sh/ruff/issues/23235 + - # ruff:disable[F401] +116 | print("goodbye") + - # ruff:enable[F401] From 6d68c59142afdf0abb2f9b94156233a3b71e4bbf Mon Sep 17 00:00:00 2001 From: Amethyst Reese Date: Thu, 12 Feb 2026 11:49:22 -0800 Subject: [PATCH 3/3] is none or --- crates/ruff_linter/src/suppression.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ruff_linter/src/suppression.rs b/crates/ruff_linter/src/suppression.rs index 0c7bc7f97949c..f17b9ec3394d7 100644 --- a/crates/ruff_linter/src/suppression.rs +++ b/crates/ruff_linter/src/suppression.rs @@ -228,7 +228,7 @@ impl Suppressions { grouped_diagnostic: &Option<(TextRange, SuppressionDiagnostic)>| -> bool { if let Some((group_key, group)) = grouped_diagnostic - && (key.is_none() || key.is_some_and(|key| key != *group_key)) + && key.is_none_or(|key| key != *group_key) { if group.any_invalid() { Suppressions::report_suppression_codes(