From 21c5cfe236b6f52731baf080ca394b33f0fe63a4 Mon Sep 17 00:00:00 2001 From: Amethyst Reese Date: Tue, 6 Jan 2026 18:42:51 -0800 Subject: [PATCH] Consolidate diagnostics for matched disable/enable suppression comments (#22099) ## Summary Combines diagnostics for matched suppression comments, so that ranges and autofixes for both the `#ruff:disable` and `#ruff:enable` comments will be reported as a single diagnostic. ## Test Plan Snapshot changes, added new snapshot for full output from preview mode rather than just a diff. Issue #3711 --- ...ules__ruff__tests__range_suppressions.snap | 67 +- crates/ruff_linter/src/suppression.rs | 770 +++++++++--------- 2 files changed, 406 insertions(+), 431 deletions(-) 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 ddac917621..264df075d2 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 @@ -7,7 +7,7 @@ source: crates/ruff_linter/src/rules/ruff/mod.rs --- Summary --- Removed: 15 -Added: 23 +Added: 20 --- Removed --- E741 Ambiguous variable name: `I` @@ -301,6 +301,7 @@ RUF100 [*] Unused suppression (non-enabled: `E501`) | ^^^^^^^^^^^^^^^^^^^^^ 47 | I = 1 48 | # ruff: enable[E501] + | -------------------- | help: Remove unused suppression 43 | def f(): @@ -308,26 +309,10 @@ help: Remove unused suppression 45 | # logged to user - # ruff: disable[E501] 46 | I = 1 -47 | # ruff: enable[E501] -48 | - - -RUF100 [*] Unused suppression (non-enabled: `E501`) - --> suppressions.py:48:5 - | -46 | # ruff: disable[E501] -47 | I = 1 -48 | # ruff: enable[E501] - | ^^^^^^^^^^^^^^^^^^^^ - | -help: Remove unused suppression -45 | # logged to user -46 | # ruff: disable[E501] -47 | I = 1 - # ruff: enable[E501] +47 | 48 | -49 | -50 | def f(): +49 | def f(): RUF100 [*] Unused `noqa` directive (unused: `E741`, `F841`) @@ -563,6 +548,9 @@ RUF102 [*] Invalid rule code in suppression: YF829 | ^^^^^ 94 | # ruff: disable[F841, RQW320] 95 | value = 0 +96 | # ruff: enable[F841, RQW320] +97 | # ruff: enable[YF829] + | ----- | help: Remove the rule code 90 | @@ -572,6 +560,10 @@ help: Remove the rule code 93 | # ruff: disable[F841, RQW320] 94 | value = 0 95 | # ruff: enable[F841, RQW320] + - # ruff: enable[YF829] +96 | +97 | +98 | def f(): RUF102 [*] Invalid rule code in suppression: RQW320 @@ -583,6 +575,8 @@ RUF102 [*] Invalid rule code in suppression: RQW320 | ^^^^^^ 95 | value = 0 96 | # ruff: enable[F841, RQW320] + | ------ +97 | # ruff: enable[YF829] | help: Remove the rule code 91 | def f(): @@ -590,23 +584,6 @@ help: Remove the rule code 93 | # ruff: disable[YF829] - # ruff: disable[F841, RQW320] 94 + # ruff: disable[F841] -95 | value = 0 -96 | # ruff: enable[F841, RQW320] -97 | # ruff: enable[YF829] - - -RUF102 [*] Invalid rule code in suppression: RQW320 - --> suppressions.py:96:26 - | -94 | # ruff: disable[F841, RQW320] -95 | value = 0 -96 | # ruff: enable[F841, RQW320] - | ^^^^^^ -97 | # ruff: enable[YF829] - | -help: Remove the rule code -93 | # ruff: disable[YF829] -94 | # ruff: disable[F841, RQW320] 95 | value = 0 - # ruff: enable[F841, RQW320] 96 + # ruff: enable[F841] @@ -615,24 +592,6 @@ help: Remove the rule code 99 | -RUF102 [*] Invalid rule code in suppression: YF829 - --> suppressions.py:97:20 - | -95 | value = 0 -96 | # ruff: enable[F841, RQW320] -97 | # ruff: enable[YF829] - | ^^^^^ - | -help: Remove the rule code -94 | # ruff: disable[F841, RQW320] -95 | value = 0 -96 | # ruff: enable[F841, RQW320] - - # ruff: enable[YF829] -97 | -98 | -99 | def f(): - - RUF103 [*] Invalid suppression comment: missing suppression codes like `[E501, ...]` --> suppressions.py:109:5 | diff --git a/crates/ruff_linter/src/suppression.rs b/crates/ruff_linter/src/suppression.rs index cfd7510b1b..856e65699b 100644 --- a/crates/ruff_linter/src/suppression.rs +++ b/crates/ruff_linter/src/suppression.rs @@ -13,7 +13,6 @@ use ruff_python_trivia::Cursor; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize, TextSlice}; use smallvec::{SmallVec, smallvec}; -use crate::Locator; use crate::checkers::ast::LintContext; use crate::codes::Rule; use crate::fix::edits::delete_comment; @@ -24,6 +23,7 @@ use crate::rules::ruff::rules::{ UnmatchedSuppressionComment, UnusedCodes, UnusedNOQA, UnusedNOQAKind, code_is_valid, }; use crate::settings::LinterSettings; +use crate::{Locator, Violation}; #[derive(Clone, Debug, Eq, PartialEq)] enum SuppressionAction { @@ -85,11 +85,33 @@ pub(crate) struct Suppression { /// Range for which the suppression applies range: TextRange, - /// Any comments associated with the suppression - comments: SmallVec<[SuppressionComment; 2]>, - /// Whether this suppression actually suppressed a diagnostic used: Cell, + + comments: DisableEnableComments, +} + +#[derive(Debug)] +pub(crate) enum DisableEnableComments { + /// An implicitly closed disable comment without a matching enable comment. + Disable(SuppressionComment), + /// A matching pair of disable and enable comments. + DisableEnable(SuppressionComment, SuppressionComment), +} + +impl DisableEnableComments { + pub(crate) fn disable_comment(&self) -> &SuppressionComment { + match self { + DisableEnableComments::Disable(comment) => comment, + DisableEnableComments::DisableEnable(disable, _) => disable, + } + } + pub(crate) fn enable_comment(&self) -> Option<&SuppressionComment> { + match self { + DisableEnableComments::Disable(_) => None, + DisableEnableComments::DisableEnable(_, enable) => Some(enable), + } + } } #[derive(Copy, Clone, Debug)] @@ -171,23 +193,16 @@ impl Suppressions { if !code_is_valid(&suppression.code, &context.settings().external) { // InvalidRuleCode if context.is_rule_enabled(Rule::InvalidRuleCode) { - for comment in &suppression.comments { - let (range, edit) = Suppressions::delete_code_or_comment( - locator, - suppression, - comment, - true, - ); - context - .report_diagnostic( - InvalidRuleCode { - rule_code: suppression.code.to_string(), - kind: InvalidRuleCodeKind::Suppression, - }, - range, - ) - .set_fix(Fix::safe_edit(edit)); - } + Suppressions::report_suppression( + context, + locator, + suppression, + true, + InvalidRuleCode { + rule_code: suppression.code.to_string(), + kind: InvalidRuleCodeKind::Suppression, + }, + ); } } else if !suppression.used.get() { // UnusedNOQA @@ -197,42 +212,37 @@ impl Suppressions { ) else { continue; // "external" lint code, don't treat it as unused }; - for comment in &suppression.comments { - let (range, edit) = Suppressions::delete_code_or_comment( - locator, - suppression, - comment, - false, - ); - let codes = if context.is_rule_enabled(rule) { - UnusedCodes { - unmatched: vec![suppression.code.to_string()], - ..Default::default() - } - } else { - UnusedCodes { - disabled: vec![suppression.code.to_string()], - ..Default::default() - } - }; + let codes = if context.is_rule_enabled(rule) { + UnusedCodes { + unmatched: vec![suppression.code.to_string()], + ..Default::default() + } + } else { + UnusedCodes { + disabled: vec![suppression.code.to_string()], + ..Default::default() + } + }; - context - .report_diagnostic( - UnusedNOQA { - codes: Some(codes), - kind: UnusedNOQAKind::Suppression, - }, - range, - ) - .set_fix(Fix::safe_edit(edit)); - } + Suppressions::report_suppression( + context, + locator, + suppression, + false, + UnusedNOQA { + codes: Some(codes), + kind: UnusedNOQAKind::Suppression, + }, + ); } - } else if suppression.comments.len() == 1 { + } else if let DisableEnableComments::Disable(comment) = &suppression.comments { // UnmatchedSuppressionComment - let range = suppression.comments[0].range; - if unmatched_ranges.insert(range) { - context.report_diagnostic_if_enabled(UnmatchedSuppressionComment {}, range); + if unmatched_ranges.insert(comment.range) { + context.report_diagnostic_if_enabled( + UnmatchedSuppressionComment {}, + comment.range, + ); } } } @@ -267,6 +277,35 @@ impl Suppressions { } } + fn report_suppression( + context: &LintContext, + locator: &Locator, + suppression: &Suppression, + highlight_only_code: bool, + kind: T, + ) { + let disable_comment = suppression.comments.disable_comment(); + let (range, edit) = Suppressions::delete_code_or_comment( + locator, + suppression, + disable_comment, + highlight_only_code, + ); + let mut diagnostic = context.report_diagnostic(kind, range); + if let Some(enable_comment) = suppression.comments.enable_comment() { + let (enable_range, enable_range_edit) = Suppressions::delete_code_or_comment( + locator, + suppression, + enable_comment, + highlight_only_code, + ); + diagnostic.secondary_annotation("", enable_range); + diagnostic.set_fix(Fix::safe_edits(edit, [enable_range_edit])); + } else { + diagnostic.set_fix(Fix::safe_edit(edit)); + } + } + fn delete_code_or_comment( locator: &Locator<'_>, suppression: &Suppression, @@ -424,7 +463,10 @@ impl<'a> SuppressionsBuilder<'a> { self.valid.push(Suppression { code: code.into(), range: combined_range, - comments: smallvec![comment.comment.clone(), other.comment.clone()], + comments: DisableEnableComments::DisableEnable( + comment.comment.clone(), + other.comment.clone(), + ), used: false.into(), }); } @@ -441,7 +483,7 @@ impl<'a> SuppressionsBuilder<'a> { self.valid.push(Suppression { code: code.into(), range: implicit_range, - comments: smallvec![comment.comment.clone()], + comments: DisableEnableComments::Disable(comment.comment.clone()), used: false.into(), }); } @@ -643,7 +685,7 @@ mod tests { use insta::assert_debug_snapshot; use itertools::Itertools; use ruff_python_parser::{Mode, ParseOptions, parse}; - use ruff_text_size::{TextRange, TextSize}; + use ruff_text_size::{TextLen, TextRange, TextSize}; use similar::DiffableStr; use crate::{ @@ -705,24 +747,22 @@ print('hello') Suppression { covered_source: "# ruff: disable[foo]\nprint('hello')\n# ruff: enable[foo]", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo]", - action: Disable, - codes: [ - "foo", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[foo]", - action: Enable, - codes: [ - "foo", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo]", + action: Disable, + codes: [ + "foo", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[foo]", + action: Enable, + codes: [ + "foo", + ], + reason: "", + }, }, ], invalid: [], @@ -751,30 +791,28 @@ def foo(): Suppression { covered_source: "# ruff: disable[bar]\n print('hello')\n\n", code: "bar", - comments: [ - SuppressionComment { - text: "# ruff: disable[bar]", - action: Disable, - codes: [ - "bar", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[bar]", + action: Disable, + codes: [ + "bar", + ], + reason: "", + }, + enable_comment: None, }, Suppression { covered_source: "# ruff: disable[foo]\nprint('hello')\n\ndef foo():\n # ruff: disable[bar]\n print('hello')\n\n", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo]", - action: Disable, - codes: [ - "foo", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo]", + action: Disable, + codes: [ + "foo", + ], + reason: "", + }, + enable_comment: None, }, ], invalid: [], @@ -803,46 +841,42 @@ class Foo: Suppression { covered_source: "# ruff: disable[bar]\n print('hello')\n # ruff: enable[bar]", code: "bar", - comments: [ - SuppressionComment { - text: "# ruff: disable[bar]", - action: Disable, - codes: [ - "bar", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[bar]", - action: Enable, - codes: [ - "bar", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[bar]", + action: Disable, + codes: [ + "bar", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[bar]", + action: Enable, + codes: [ + "bar", + ], + reason: "", + }, }, Suppression { covered_source: "# ruff: disable[foo]\n def bar(self):\n # ruff: disable[bar]\n print('hello')\n # ruff: enable[bar]\n # ruff: enable[foo]", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo]", - action: Disable, - codes: [ - "foo", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[foo]", - action: Enable, - codes: [ - "foo", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo]", + action: Disable, + codes: [ + "foo", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[foo]", + action: Enable, + codes: [ + "foo", + ], + reason: "", + }, }, ], invalid: [], @@ -872,46 +906,42 @@ def foo(): Suppression { covered_source: "# ruff: disable[foo]\n print('hello')\n # ruff: disable[bar]\n print('hello')\n # ruff: enable[foo]", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo]", - action: Disable, - codes: [ - "foo", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[foo]", - action: Enable, - codes: [ - "foo", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo]", + action: Disable, + codes: [ + "foo", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[foo]", + action: Enable, + codes: [ + "foo", + ], + reason: "", + }, }, Suppression { covered_source: "# ruff: disable[bar]\n print('hello')\n # ruff: enable[foo]\n print('hello')\n # ruff: enable[bar]", code: "bar", - comments: [ - SuppressionComment { - text: "# ruff: disable[bar]", - action: Disable, - codes: [ - "bar", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[bar]", - action: Enable, - codes: [ - "bar", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[bar]", + action: Disable, + codes: [ + "bar", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[bar]", + action: Enable, + codes: [ + "bar", + ], + reason: "", + }, }, ], invalid: [], @@ -936,50 +966,46 @@ print('hello') Suppression { covered_source: "# ruff: disable[foo, bar]\nprint('hello')\n# ruff: enable[foo, bar]", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo, bar]", - action: Disable, - codes: [ - "foo", - "bar", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[foo, bar]", - action: Enable, - codes: [ - "foo", - "bar", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo, bar]", + action: Disable, + codes: [ + "foo", + "bar", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[foo, bar]", + action: Enable, + codes: [ + "foo", + "bar", + ], + reason: "", + }, }, Suppression { covered_source: "# ruff: disable[foo, bar]\nprint('hello')\n# ruff: enable[foo, bar]", code: "bar", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo, bar]", - action: Disable, - codes: [ - "foo", - "bar", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[foo, bar]", - action: Enable, - codes: [ - "foo", - "bar", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo, bar]", + action: Disable, + codes: [ + "foo", + "bar", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[foo, bar]", + action: Enable, + codes: [ + "foo", + "bar", + ], + reason: "", + }, }, ], invalid: [], @@ -1005,16 +1031,15 @@ print('world') Suppression { covered_source: "# ruff: disable[foo]\nprint('hello')\n# ruff: enable[bar]\nprint('world')\n", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo]", - action: Disable, - codes: [ - "foo", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo]", + action: Disable, + codes: [ + "foo", + ], + reason: "", + }, + enable_comment: None, }, ], invalid: [ @@ -1051,32 +1076,30 @@ print('hello') Suppression { covered_source: "# ruff: disable[foo, bar]\nprint('hello')\n# ruff: enable[bar, foo]\n", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo, bar]", - action: Disable, - codes: [ - "foo", - "bar", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo, bar]", + action: Disable, + codes: [ + "foo", + "bar", + ], + reason: "", + }, + enable_comment: None, }, Suppression { covered_source: "# ruff: disable[foo, bar]\nprint('hello')\n# ruff: enable[bar, foo]\n", code: "bar", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo, bar]", - action: Disable, - codes: [ - "foo", - "bar", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo, bar]", + action: Disable, + codes: [ + "foo", + "bar", + ], + reason: "", + }, + enable_comment: None, }, ], invalid: [ @@ -1116,38 +1139,35 @@ print('hello') Suppression { covered_source: "# ruff: disable[foo] first\nprint('hello')\n# ruff: disable[foo] second\nprint('hello')\n# ruff: enable[foo]", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo] first", - action: Disable, - codes: [ - "foo", - ], - reason: "first", - }, - SuppressionComment { - text: "# ruff: enable[foo]", - action: Enable, - codes: [ - "foo", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo] first", + action: Disable, + codes: [ + "foo", + ], + reason: "first", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[foo]", + action: Enable, + codes: [ + "foo", + ], + reason: "", + }, }, Suppression { covered_source: "# ruff: disable[foo] second\nprint('hello')\n# ruff: enable[foo]\n", code: "foo", - comments: [ - SuppressionComment { - text: "# ruff: disable[foo] second", - action: Disable, - codes: [ - "foo", - ], - reason: "second", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[foo] second", + action: Disable, + codes: [ + "foo", + ], + reason: "second", + }, + enable_comment: None, }, ], invalid: [], @@ -1189,100 +1209,92 @@ def bar(): Suppression { covered_source: "# ruff: disable[delta] unmatched\n pass\n # ruff: enable[beta,gamma]\n# ruff: enable[alpha]\n\n# ruff: disable # parse error!\n", code: "delta", - comments: [ - SuppressionComment { - text: "# ruff: disable[delta] unmatched", - action: Disable, - codes: [ - "delta", - ], - reason: "unmatched", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[delta] unmatched", + action: Disable, + codes: [ + "delta", + ], + reason: "unmatched", + }, + enable_comment: None, }, Suppression { covered_source: "# ruff: disable[beta,gamma]\n if True:\n # ruff: disable[delta] unmatched\n pass\n # ruff: enable[beta,gamma]", code: "beta", - comments: [ - SuppressionComment { - text: "# ruff: disable[beta,gamma]", - action: Disable, - codes: [ - "beta", - "gamma", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[beta,gamma]", - action: Enable, - codes: [ - "beta", - "gamma", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[beta,gamma]", + action: Disable, + codes: [ + "beta", + "gamma", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[beta,gamma]", + action: Enable, + codes: [ + "beta", + "gamma", + ], + reason: "", + }, }, Suppression { covered_source: "# ruff: disable[beta,gamma]\n if True:\n # ruff: disable[delta] unmatched\n pass\n # ruff: enable[beta,gamma]", code: "gamma", - comments: [ - SuppressionComment { - text: "# ruff: disable[beta,gamma]", - action: Disable, - codes: [ - "beta", - "gamma", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[beta,gamma]", - action: Enable, - codes: [ - "beta", - "gamma", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[beta,gamma]", + action: Disable, + codes: [ + "beta", + "gamma", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[beta,gamma]", + action: Enable, + codes: [ + "beta", + "gamma", + ], + reason: "", + }, }, Suppression { covered_source: "# ruff: disable[zeta] unmatched\n pass\n# ruff: enable[zeta] underindented\n pass\n", code: "zeta", - comments: [ - SuppressionComment { - text: "# ruff: disable[zeta] unmatched", - action: Disable, - codes: [ - "zeta", - ], - reason: "unmatched", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[zeta] unmatched", + action: Disable, + codes: [ + "zeta", + ], + reason: "unmatched", + }, + enable_comment: None, }, Suppression { covered_source: "# ruff: disable[alpha]\ndef foo():\n # ruff: disable[beta,gamma]\n if True:\n # ruff: disable[delta] unmatched\n pass\n # ruff: enable[beta,gamma]\n# ruff: enable[alpha]", code: "alpha", - comments: [ - SuppressionComment { - text: "# ruff: disable[alpha]", - action: Disable, - codes: [ - "alpha", - ], - reason: "", - }, - SuppressionComment { - text: "# ruff: enable[alpha]", - action: Enable, - codes: [ - "alpha", - ], - reason: "", - }, - ], + disable_comment: SuppressionComment { + text: "# ruff: disable[alpha]", + action: Disable, + codes: [ + "alpha", + ], + reason: "", + }, + enable_comment: SuppressionComment { + text: "# ruff: enable[alpha]", + action: Enable, + codes: [ + "alpha", + ], + reason: "", + }, }, ], invalid: [ @@ -1532,10 +1544,8 @@ def bar(): #[test] fn comment_attributes() { let source = "# ruff: disable[foo, bar] hello world"; - let mut parser = SuppressionParser::new( - source, - TextRange::new(0.into(), TextSize::try_from(source.len()).unwrap()), - ); + let mut parser = + SuppressionParser::new(source, TextRange::new(0.into(), source.text_len())); let comment = parser.parse_comment().unwrap(); assert_eq!(comment.action, SuppressionAction::Disable); assert_eq!( @@ -1554,12 +1564,12 @@ def bar(): source: &'_ str, ) -> Result, ParseError> { let offset = TextSize::new(source.find('#').unwrap_or(0).try_into().unwrap()); - let mut parser = SuppressionParser::new( - source, - TextRange::new(offset, TextSize::try_from(source.len()).unwrap()), - ); + let mut parser = SuppressionParser::new(source, TextRange::new(offset, source.text_len())); match parser.parse_comment() { - Ok(comment) => Ok(DebugSuppressionComment { source, comment }), + Ok(comment) => Ok(DebugSuppressionComment { + source, + comment: Some(comment), + }), Err(error) => Err(error), } } @@ -1639,16 +1649,18 @@ def bar(): .field("covered_source", &&self.source[self.suppression.range]) .field("code", &self.suppression.code) .field( - "comments", - &self - .suppression - .comments - .iter() - .map(|comment| DebugSuppressionComment { - source: self.source, - comment: comment.clone(), - }) - .collect_vec(), + "disable_comment", + &DebugSuppressionComment { + source: self.source, + comment: Some(self.suppression.comments.disable_comment().clone()), + }, + ) + .field( + "enable_comment", + &DebugSuppressionComment { + source: self.source, + comment: self.suppression.comments.enable_comment().cloned(), + }, ) .finish() } @@ -1667,7 +1679,7 @@ def bar(): "comment", &DebugSuppressionComment { source: self.source, - comment: self.invalid.comment.clone(), + comment: Some(self.invalid.comment.clone()), }, ) .finish() @@ -1690,23 +1702,27 @@ def bar(): struct DebugSuppressionComment<'a> { source: &'a str, - comment: SuppressionComment, + comment: Option, } impl fmt::Debug for DebugSuppressionComment<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("SuppressionComment") - .field("text", &&self.source[self.comment.range]) - .field("action", &self.comment.action) - .field( - "codes", - &DebugCodes { - source: self.source, - codes: &self.comment.codes, - }, - ) - .field("reason", &&self.source[self.comment.reason]) - .finish() + match &self.comment { + Some(comment) => f + .debug_struct("SuppressionComment") + .field("text", &&self.source[comment.range]) + .field("action", &comment.action) + .field( + "codes", + &DebugCodes { + source: self.source, + codes: &comment.codes, + }, + ) + .field("reason", &&self.source[comment.reason]) + .finish(), + None => f.debug_tuple("None").finish(), + } } }