@@ -7,12 +7,18 @@ use biome_diagnostics::category;
77use biome_rowan:: { TextRange , TextSize } ;
88use rustc_hash:: { FxHashMap , FxHashSet } ;
99
10+ const PLUGIN_LINT_RULE_FILTER : RuleFilter < ' static > = RuleFilter :: Group ( "lint/plugin" ) ;
11+
1012#[ derive( Debug , Default ) ]
1113pub struct TopLevelSuppression {
1214 /// Whether this suppression suppresses all filters
1315 pub ( crate ) suppress_all : bool ,
1416 /// Filters for the current suppression
1517 pub ( crate ) filters : FxHashSet < RuleFilter < ' static > > ,
18+ /// Whether this suppression suppresses all plugins
19+ pub ( crate ) suppress_all_plugins : bool ,
20+ /// Current suppressed plugins
21+ pub ( crate ) plugins : FxHashSet < String > ,
1622 /// The range of the comment
1723 pub ( crate ) comment_range : TextRange ,
1824
@@ -48,6 +54,7 @@ impl TopLevelSuppression {
4854 // The absence of a filter means that it's a suppression all
4955 match filter {
5056 None => self . suppress_all = true ,
57+ Some ( PLUGIN_LINT_RULE_FILTER ) => self . insert_plugin ( & suppression. kind ) ,
5158 Some ( filter) => self . insert ( filter) ,
5259 }
5360 self . comment_range = comment_range;
@@ -59,10 +66,26 @@ impl TopLevelSuppression {
5966 self . filters . insert ( filter) ;
6067 }
6168
69+ pub ( crate ) fn insert_plugin ( & mut self , kind : & AnalyzerSuppressionKind ) {
70+ match kind {
71+ AnalyzerSuppressionKind :: Plugin ( Some ( name) ) => {
72+ self . plugins . insert ( ( * name) . to_string ( ) ) ;
73+ }
74+ AnalyzerSuppressionKind :: Plugin ( None ) => {
75+ self . suppress_all_plugins = true ;
76+ }
77+ _ => { }
78+ }
79+ }
80+
6281 pub ( crate ) fn suppressed_rule ( & self , filter : & RuleKey ) -> bool {
6382 self . filters . iter ( ) . any ( |f| f == filter)
6483 }
6584
85+ pub ( crate ) fn suppressed_plugin ( & self , plugin_name : & str ) -> bool {
86+ self . suppress_all_plugins || self . plugins . contains ( plugin_name)
87+ }
88+
6689 pub ( crate ) fn expand_range ( & mut self , range : TextRange ) {
6790 self . range . cover ( range) ;
6891 }
@@ -89,6 +112,10 @@ pub(crate) struct LineSuppression {
89112 pub ( crate ) suppressed_rules : FxHashSet < RuleFilter < ' static > > ,
90113 /// List of all the rule instances this comment has started suppressing.
91114 pub ( crate ) suppressed_instances : FxHashMap < String , RuleFilter < ' static > > ,
115+ /// List of plugins this comment has started suppressing
116+ pub ( crate ) suppressed_plugins : FxHashSet < String > ,
117+ /// Set to true if this comment suppress all plugins
118+ pub ( crate ) suppress_all_plugins : bool ,
92119 /// Set to `true` when a signal matching this suppression was emitted and
93120 /// suppressed
94121 pub ( crate ) did_suppress_signal : bool ,
@@ -139,6 +166,15 @@ impl RangeSuppressions {
139166 text_range : TextRange ,
140167 already_suppressed : Option < TextRange > ,
141168 ) -> Result < ( ) , AnalyzerSuppressionDiagnostic > {
169+ if let Some ( PLUGIN_LINT_RULE_FILTER ) = filter {
170+ return Err ( AnalyzerSuppressionDiagnostic :: new (
171+ category ! ( "suppressions/incorrect" ) ,
172+ text_range,
173+ markup ! { "Found a " <Emphasis >"biome-ignore-<range>" </Emphasis >" suppression on plugin. This is not supported. See https://github.com/biomejs/biome/issues/5175" }
174+ ) . hint ( markup ! {
175+ "Remove this suppression."
176+ } . to_owned ( ) ) ) ;
177+ }
142178 if suppression. is_range_start ( ) {
143179 if let Some ( range_suppression) = self . suppressions . last_mut ( ) {
144180 match filter {
@@ -270,6 +306,7 @@ impl<'analyzer> Suppressions<'analyzer> {
270306 fn push_line_suppression (
271307 & mut self ,
272308 filter : Option < RuleFilter < ' static > > ,
309+ plugin_name : Option < String > ,
273310 instance : Option < String > ,
274311 current_range : TextRange ,
275312 already_suppressed : Option < TextRange > ,
@@ -283,6 +320,16 @@ impl<'analyzer> Suppressions<'analyzer> {
283320 suppression. suppress_all = true ;
284321 suppression. suppressed_rules . clear ( ) ;
285322 suppression. suppressed_instances . clear ( ) ;
323+ suppression. suppressed_plugins . clear ( ) ;
324+ }
325+ Some ( PLUGIN_LINT_RULE_FILTER ) => {
326+ if let Some ( plugin_name) = plugin_name {
327+ suppression. suppressed_plugins . insert ( plugin_name) ;
328+ suppression. suppress_all_plugins = false ;
329+ } else {
330+ suppression. suppress_all_plugins = true ;
331+ }
332+ suppression. suppress_all = false ;
286333 }
287334 Some ( filter) => {
288335 suppression. suppressed_rules . insert ( filter) ;
@@ -307,6 +354,13 @@ impl<'analyzer> Suppressions<'analyzer> {
307354 None => {
308355 suppression. suppress_all = true ;
309356 }
357+ Some ( PLUGIN_LINT_RULE_FILTER ) => {
358+ if let Some ( plugin_name) = plugin_name {
359+ suppression. suppressed_plugins . insert ( plugin_name) ;
360+ } else {
361+ suppression. suppress_all_plugins = true ;
362+ }
363+ }
310364 Some ( filter) => {
311365 suppression. suppressed_rules . insert ( filter) ;
312366 if let Some ( instance) = instance {
@@ -329,6 +383,7 @@ impl<'analyzer> Suppressions<'analyzer> {
329383 AnalyzerSuppressionKind :: Everything => return Ok ( None ) ,
330384 AnalyzerSuppressionKind :: Rule ( rule) => rule,
331385 AnalyzerSuppressionKind :: RuleInstance ( rule, _) => rule,
386+ AnalyzerSuppressionKind :: Plugin ( _) => return Ok ( Some ( PLUGIN_LINT_RULE_FILTER ) ) ,
332387 } ;
333388
334389 let group_rule = rule. split_once ( '/' ) ;
@@ -357,11 +412,20 @@ impl<'analyzer> Suppressions<'analyzer> {
357412
358413 fn map_to_rule_instances ( & self , suppression_kind : & AnalyzerSuppressionKind ) -> Option < String > {
359414 match suppression_kind {
360- AnalyzerSuppressionKind :: Everything | AnalyzerSuppressionKind :: Rule ( _) => None ,
415+ AnalyzerSuppressionKind :: Everything
416+ | AnalyzerSuppressionKind :: Rule ( _)
417+ | AnalyzerSuppressionKind :: Plugin ( _) => None ,
361418 AnalyzerSuppressionKind :: RuleInstance ( _, instances) => Some ( ( * instances) . to_string ( ) ) ,
362419 }
363420 }
364421
422+ fn map_to_plugin_name ( & self , suppression_kind : & AnalyzerSuppressionKind ) -> Option < String > {
423+ match suppression_kind {
424+ AnalyzerSuppressionKind :: Plugin ( Some ( plugin_name) ) => Some ( ( * plugin_name) . to_string ( ) ) ,
425+ _ => None ,
426+ }
427+ }
428+
365429 pub ( crate ) fn push_suppression (
366430 & mut self ,
367431 suppression : & AnalyzerSuppression ,
@@ -370,12 +434,17 @@ impl<'analyzer> Suppressions<'analyzer> {
370434 ) -> Result < ( ) , AnalyzerSuppressionDiagnostic > {
371435 let filter = self . map_to_rule_filter ( & suppression. kind , comment_range) ?;
372436 let instances = self . map_to_rule_instances ( & suppression. kind ) ;
437+ let plugin_name: Option < String > = self . map_to_plugin_name ( & suppression. kind ) ;
373438 self . last_suppression = Some ( suppression. variant . clone ( ) ) ;
374439 let already_suppressed = self . already_suppressed ( filter. as_ref ( ) , & comment_range) ;
375440 match suppression. variant {
376- AnalyzerSuppressionVariant :: Line => {
377- self . push_line_suppression ( filter, instances, comment_range, already_suppressed)
378- }
441+ AnalyzerSuppressionVariant :: Line => self . push_line_suppression (
442+ filter,
443+ plugin_name,
444+ instances,
445+ comment_range,
446+ already_suppressed,
447+ ) ,
379448 AnalyzerSuppressionVariant :: TopLevel => self . top_level_suppression . push_suppression (
380449 suppression,
381450 filter,
0 commit comments