11use crate :: {
22 AddVisitor , AnalysisFilter , GroupCategory , QueryMatcher , Rule , RuleGroup , RuleKey ,
3- RuleMetadata , ServiceBag , SignalEntry , Visitor ,
3+ RuleMetadata , ServiceBag , SignalEntry , SyntaxVisitor , Visitor ,
44 context:: RuleContext ,
55 matcher:: { GroupKey , MatchQueryParams } ,
66 query:: { QueryKey , Queryable } ,
77 signals:: RuleSignal ,
88} ;
99use biome_diagnostics:: Error ;
10- use biome_rowan:: { AstNode , Language , RawSyntaxKind , SyntaxKind , SyntaxNode } ;
10+ use biome_rowan:: { AstNode , Language , RawSyntaxKind , SyntaxKind , SyntaxKindSet , SyntaxNode } ;
1111use rustc_hash:: { FxHashMap , FxHashSet } ;
1212use std:: {
1313 any:: TypeId ,
1414 borrow,
1515 collections:: { BTreeMap , BTreeSet } ,
1616} ;
1717
18+ /// Number of phases supported by the [RuleRegistry].
19+ const PHASE_COUNT : usize = 2 ;
20+
1821/// Defines all the phases that the [RuleRegistry] supports.
1922#[ repr( usize ) ]
2023#[ derive( Clone , Copy , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
@@ -98,7 +101,7 @@ impl<L: Language> RegistryVisitor<L> for MetadataRegistry {
98101/// after the "SemanticModel" is ready, which demands a whole transverse of the parsed tree.
99102pub struct RuleRegistry < L : Language > {
100103 /// Holds a collection of rules for each phase.
101- phase_rules : [ PhaseRules < L > ; 2 ] ,
104+ phase_rules : [ PhaseRules < L > ; PHASE_COUNT ] ,
102105}
103106
104107impl < L : Language + Default > RuleRegistry < L > {
@@ -115,6 +118,7 @@ impl<L: Language + Default> RuleRegistry<L> {
115118 visitors : BTreeMap :: default ( ) ,
116119 services : ServiceBag :: default ( ) ,
117120 diagnostics : Vec :: new ( ) ,
121+ syntax_kind_sets : [ SyntaxKindSet :: empty ( ) ; PHASE_COUNT ] ,
118122 }
119123 }
120124}
@@ -143,6 +147,10 @@ pub struct RuleRegistryBuilder<'a, L: Language> {
143147 // Service Bag
144148 services : ServiceBag ,
145149 diagnostics : Vec < Error > ,
150+ /// Per-phase union of all [SyntaxKindSet] values from registered rules.
151+ /// Used to create a filtered [SyntaxVisitor] that only emits query matches
152+ /// for node kinds that at least one rule cares about.
153+ syntax_kind_sets : [ SyntaxKindSet < L > ; PHASE_COUNT ] ,
146154}
147155
148156impl < L : Language + Default + ' static > RegistryVisitor < L > for RuleRegistryBuilder < ' _ , L > {
@@ -167,13 +175,15 @@ impl<L: Language + Default + 'static> RegistryVisitor<L> for RuleRegistryBuilder
167175 return ;
168176 }
169177
170- let phase = R :: phase ( ) as usize ;
171- let phase = & mut self . registry . phase_rules [ phase ] ;
178+ let phase_index = R :: phase ( ) as usize ;
179+ let phase = & mut self . registry . phase_rules [ phase_index ] ;
172180
173181 let rule = RegistryRule :: new :: < R > ( phase. rule_states . len ( ) ) ;
174182
175183 match <R :: Query as Queryable >:: key ( ) {
176184 QueryKey :: Syntax ( key) => {
185+ self . syntax_kind_sets [ phase_index] = self . syntax_kind_sets [ phase_index] . union ( key) ;
186+
177187 let TypeRules :: SyntaxRules { rules } = phase
178188 . type_rules
179189 . entry ( TypeId :: of :: < SyntaxNode < L > > ( ) )
@@ -242,8 +252,25 @@ type BuilderResult<L> = (
242252 BTreeMap < ( Phases , TypeId ) , Box < dyn Visitor < Language = L > > > ,
243253) ;
244254
245- impl < L : Language > RuleRegistryBuilder < ' _ , L > {
246- pub fn build ( self ) -> BuilderResult < L > {
255+ impl < L : Language + ' static > RuleRegistryBuilder < ' _ , L > {
256+ pub fn build ( mut self ) -> BuilderResult < L > {
257+ // Replace SyntaxVisitor instances with filtered versions that only
258+ // emit query matches for node kinds that at least one rule queries.
259+ // This avoids per-node Box::new() allocations for kinds no rule
260+ // cares about.
261+ let phases = [ Phases :: Syntax , Phases :: Semantic ] ;
262+ for ( phase_index, & phase) in phases. iter ( ) . enumerate ( ) {
263+ let key = ( phase, TypeId :: of :: < SyntaxVisitor < L > > ( ) ) ;
264+ if self . visitors . contains_key ( & key) {
265+ self . visitors . insert (
266+ key,
267+ Box :: new ( SyntaxVisitor :: with_kind_set (
268+ self . syntax_kind_sets [ phase_index] ,
269+ ) ) ,
270+ ) ;
271+ }
272+ }
273+
247274 (
248275 self . registry ,
249276 self . services ,
0 commit comments