11#![ deny( clippy:: use_self, rustdoc:: broken_intra_doc_links) ]
22
33use biome_console:: markup;
4- use biome_parser:: AnyParse ;
54use rustc_hash:: FxHashSet ;
65use std:: collections:: { BTreeMap , BinaryHeap } ;
76use std:: fmt:: { Debug , Display , Formatter } ;
87use std:: ops;
98use std:: str:: FromStr ;
10- use std:: sync:: Arc ;
119
1210mod analyzer_plugin;
1311mod categories;
@@ -29,13 +27,16 @@ mod visitor;
2927// Re-exported for use in the `declare_group` macro
3028pub use biome_diagnostics:: category_concat;
3129
32- pub use crate :: analyzer_plugin:: { AnalyzerPlugin , AnalyzerPluginSlice , AnalyzerPluginVec } ;
30+ pub use crate :: analyzer_plugin:: {
31+ AnalyzerPlugin , AnalyzerPluginSlice , AnalyzerPluginVec , PluginTargetLanguage , PluginVisitor ,
32+ } ;
3333pub use crate :: categories:: {
3434 ActionCategory , OtherActionCategory , RefactorKind , RuleCategories , RuleCategoriesBuilder ,
3535 RuleCategory , SUPPRESSION_INLINE_ACTION_CATEGORY , SUPPRESSION_TOP_LEVEL_ACTION_CATEGORY ,
3636 SourceActionKind ,
3737} ;
3838pub use crate :: diagnostics:: { AnalyzerDiagnostic , AnalyzerSuppressionDiagnostic , RuleError } ;
39+ use crate :: matcher:: SignalRuleKey ;
3940pub use crate :: matcher:: { InspectMatcher , MatchQueryParams , QueryMatcher , RuleKey , SignalEntry } ;
4041pub use crate :: options:: { AnalyzerConfiguration , AnalyzerOptions , AnalyzerRules } ;
4142pub use crate :: query:: { AddVisitor , QueryKey , QueryMatch , Queryable } ;
@@ -76,8 +77,6 @@ pub use suppression_action::{ApplySuppression, SuppressionAction};
7677pub struct Analyzer < ' analyzer , L : Language , Matcher , Break , Diag > {
7778 /// List of visitors being run by this instance of the analyzer for each phase
7879 phases : BTreeMap < Phases , Vec < Box < dyn Visitor < Language = L > + ' analyzer > > > ,
79- /// Plugins to be run after the phases for built-in rules.
80- plugins : AnalyzerPluginVec ,
8180 /// Holds the metadata for all the rules statically known to the analyzer
8281 metadata : & ' analyzer MetadataRegistry ,
8382 /// Executor for the query matches emitted by the visitors
@@ -114,7 +113,6 @@ where
114113 ) -> Self {
115114 Self {
116115 phases : BTreeMap :: new ( ) ,
117- plugins : Vec :: new ( ) ,
118116 metadata,
119117 query_matcher,
120118 parse_suppression_comment,
@@ -132,15 +130,9 @@ where
132130 self . phases . entry ( phase) . or_default ( ) . push ( visitor) ;
133131 }
134132
135- /// Registers an [AnalyzerPlugin] to be executed after the regular phases.
136- pub fn add_plugin ( & mut self , plugin : Arc < Box < dyn AnalyzerPlugin > > ) {
137- self . plugins . push ( plugin) ;
138- }
139-
140133 pub fn run ( self , mut ctx : AnalyzerContext < L > ) -> Option < Break > {
141134 let Self {
142135 phases,
143- plugins,
144136 mut query_matcher,
145137 parse_suppression_comment,
146138 mut emit_signal,
@@ -193,54 +185,6 @@ where
193185 }
194186 }
195187
196- for plugin in plugins {
197- let root: AnyParse = ctx. root . syntax ( ) . as_send ( ) . expect ( "not a root node" ) . into ( ) ;
198- let diagnostics = plugin. evaluate ( root, ctx. options . file_path . clone ( ) ) ;
199- for diagnostic in diagnostics {
200- let name = diagnostic
201- . subcategory
202- . clone ( )
203- . unwrap_or_else ( || "anonymous" . into ( ) ) ;
204-
205- // 1. Check for top level suppression:
206- if suppressions. top_level_suppression . suppressed_plugin ( & name)
207- || suppressions
208- . top_level_suppression
209- . suppresses_category ( RuleCategory :: Lint )
210- {
211- break ;
212- }
213-
214- let suppression = diagnostic. span . and_then ( |text_range| {
215- // 2. Check for range suppression is not supported because
216- // plugins are handled separately after the basic analyze
217- // phases. At this point, we have read to the end of the
218- // file, all `// biome-ignore-end` comments are
219- // processed, thus all range suppressions are cleared.
220-
221- // 3. Check for line suppression:
222- suppressions
223- . overlapping_line_suppressions ( & text_range)
224- . iter_mut ( )
225- . find ( |s| {
226- s. text_range . contains ( text_range. start ( ) )
227- && ( s. suppressed_categories . contains ( RuleCategory :: Lint )
228- || s. suppress_all_plugins
229- || s. suppressed_plugins . contains ( & name) )
230- } )
231- } ) ;
232-
233- if let Some ( suppression) = suppression {
234- suppression. did_suppress_signal = true ;
235- } else {
236- let signal = DiagnosticSignal :: new ( || diagnostic. clone ( ) ) ;
237- if let ControlFlow :: Break ( br) = ( emit_signal) ( & signal) {
238- return Some ( br) ;
239- }
240- }
241- }
242- }
243-
244188 for range_suppression in suppressions. range_suppressions . suppressions {
245189 if range_suppression. did_suppress_signal {
246190 continue ;
@@ -252,8 +196,8 @@ where
252196 range_suppression. start_comment_range ,
253197 "Suppression comment has no effect because another suppression comment suppresses the same rule." ,
254198 ) . note (
255- markup ! { "This is the suppression comment that was used." } . to_owned ( ) ,
256- range
199+ markup ! { "This is the suppression comment that was used." } . to_owned ( ) ,
200+ range,
257201 )
258202 } ) ;
259203 if let ControlFlow :: Break ( br) = ( emit_signal) ( & signal) {
@@ -274,8 +218,8 @@ where
274218 suppression. comment_span ,
275219 "Suppression comment has no effect because another suppression comment suppresses the same rule." ,
276220 ) . note (
277- markup ! { "This is the suppression comment that was used." } . to_owned ( ) ,
278- range
221+ markup ! { "This is the suppression comment that was used." } . to_owned ( ) ,
222+ range,
279223 )
280224 } else {
281225 AnalyzerSuppressionDiagnostic :: new (
@@ -456,22 +400,35 @@ where
456400 if self
457401 . suppressions
458402 . top_level_suppression
459- . contains_rule_key ( & entry. category , & entry. rule )
460- || self
461- . suppressions
462- . top_level_suppression
463- . suppressed_categories
464- . contains ( entry. category )
403+ . suppressed_categories
404+ . contains ( entry. category )
465405 {
466406 self . signal_queue . pop ( ) ;
467407 continue ;
468408 }
469409
470- if self . suppressions . range_suppressions . suppress_rule (
471- & entry. category ,
472- & entry. rule ,
473- & entry. text_range ,
474- ) {
410+ let is_suppressed = match & entry. rule {
411+ SignalRuleKey :: Rule ( rule) => {
412+ self . suppressions
413+ . top_level_suppression
414+ . contains_rule_key ( & entry. category , rule)
415+ || self . suppressions . range_suppressions . suppress_rule (
416+ & entry. category ,
417+ rule,
418+ & entry. text_range ,
419+ )
420+ }
421+ SignalRuleKey :: Plugin ( plugin) => {
422+ self . suppressions
423+ . top_level_suppression
424+ . suppressed_plugin ( plugin)
425+ || self
426+ . suppressions
427+ . range_suppressions
428+ . suppress_plugin ( plugin. as_ref ( ) , & entry. text_range )
429+ }
430+ } ;
431+ if is_suppressed {
475432 self . signal_queue . pop ( ) ;
476433 continue ;
477434 }
@@ -497,17 +454,28 @@ where
497454 let ( is_match, is_exhaustive) =
498455 if suppression. suppressed_categories . contains ( entry. category ) {
499456 ( true , true )
500- } else if !suppression. matches_rule ( & entry. category , & entry. rule ) {
501- ( false , false )
502457 } else {
503- match suppression. suppressed_instance . as_ref ( ) {
504- None => ( true , true ) ,
505- Some ( v) => {
506- let matches_instance = instances
507- . get_or_insert_with ( || entry. instances . iter ( ) . collect ( ) )
508- . remove ( v) ;
509- ( matches_instance, false )
458+ match & entry. rule {
459+ SignalRuleKey :: Rule ( rule)
460+ if suppression. matches_rule ( & entry. category , rule) =>
461+ {
462+ match suppression. suppressed_instance . as_ref ( ) {
463+ None => ( true , true ) ,
464+ Some ( v) => {
465+ let matches_instance = instances
466+ . get_or_insert_with ( || entry. instances . iter ( ) . collect ( ) )
467+ . remove ( v) ;
468+ ( matches_instance, false )
469+ }
470+ }
471+ }
472+ SignalRuleKey :: Plugin ( plugin)
473+ if suppression. suppress_all_plugins
474+ || suppression. suppressed_plugins . contains ( plugin. as_ref ( ) ) =>
475+ {
476+ ( true , true )
510477 }
478+ _ => ( false , false ) ,
511479 }
512480 } ;
513481 if is_match {
0 commit comments