11use std:: iter:: FusedIterator ;
22
33use oxc_allocator:: { Address , GetAddress } ;
4- use oxc_ast:: { AstKind , ast:: Program } ;
4+ use oxc_ast:: { AstKind , AstType , ast:: Program } ;
55use oxc_cfg:: BlockNodeId ;
66use oxc_index:: { IndexSlice , IndexVec } ;
77use oxc_span:: { GetSpan , Span } ;
@@ -10,6 +10,8 @@ use oxc_syntax::{
1010 scope:: ScopeId ,
1111} ;
1212
13+ use crate :: ast_types_bitset:: AstTypesBitset ;
14+
1315/// Semantic node contains all the semantic information about an ast node.
1416#[ derive( Debug , Clone , Copy ) ]
1517pub struct AstNode < ' a > {
@@ -101,6 +103,10 @@ pub struct AstNodes<'a> {
101103 nodes : IndexVec < NodeId , AstNode < ' a > > ,
102104 /// `node` -> `parent`
103105 parent_ids : IndexVec < NodeId , NodeId > ,
106+ /// Stores a set of bits of a fixed size, where each bit represents a single [`AstKind`]. If the bit is set (1),
107+ /// then the AST contains at least one node of that kind. If the bit is not set (0), then the AST does not contain
108+ /// any nodes of that kind.
109+ pub node_kinds_set : AstTypesBitset ,
104110}
105111
106112impl < ' a > AstNodes < ' a > {
@@ -212,6 +218,7 @@ impl<'a> AstNodes<'a> {
212218 let node_id = self . parent_ids . push ( parent_node_id) ;
213219 let node = AstNode :: new ( kind, scope_id, cfg_id, flags, node_id) ;
214220 self . nodes . push ( node) ;
221+ self . node_kinds_set . set ( kind. ty ( ) ) ;
215222 node_id
216223 }
217224
@@ -234,6 +241,7 @@ impl<'a> AstNodes<'a> {
234241 ) ;
235242 self . parent_ids . push ( NodeId :: ROOT ) ;
236243 self . nodes . push ( AstNode :: new ( kind, scope_id, cfg_id, flags, NodeId :: ROOT ) ) ;
244+ self . node_kinds_set . set ( AstType :: Program ) ;
237245 NodeId :: ROOT
238246 }
239247
@@ -242,6 +250,51 @@ impl<'a> AstNodes<'a> {
242250 self . nodes . reserve ( additional) ;
243251 self . parent_ids . reserve ( additional) ;
244252 }
253+
254+ /// Checks if the AST contains any nodes of the given types.
255+ ///
256+ /// Example:
257+ /// ```ignore
258+ /// let for_stmt = AstTypesBitset::from_types(&[AstType::ForStatement]);
259+ /// let import_export_decl = AstTypesBitset::from_types(&[AstType::ImportDeclaration, AstType::ExportDeclaration]);
260+ ///
261+ /// // returns true if there is a `for` loop anywhere in the AST.
262+ /// nodes.contains_any(&for_stmt)
263+ /// // returns true if there is at least one import OR one export in the AST.
264+ /// nodes.contains_any(&import_export_decl)
265+ /// ```
266+ pub fn contains_any ( & self , bitset : & AstTypesBitset ) -> bool {
267+ self . node_kinds_set . intersects ( bitset)
268+ }
269+
270+ /// Checks if the AST contains all of the given types.
271+ ///
272+ /// Example:
273+ /// ```ignore
274+ /// let for_stmt = AstTypesBitset::from_types(&[AstType::ForStatement]);
275+ /// let import_export_decl = AstTypesBitset::from_types(&[AstType::ImportDeclaration, AstType::ExportDeclaration]);
276+ ///
277+ /// // returns true if there is a `for` loop anywhere in the AST.
278+ /// nodes.contains_all(&for_stmt)
279+ /// // returns true only if there is at least one import AND one export in the AST.
280+ /// nodes.contains_all(&import_export_decl)
281+ /// ```
282+ pub fn contains_all ( & self , bitset : & AstTypesBitset ) -> bool {
283+ self . node_kinds_set . contains ( bitset)
284+ }
285+
286+ /// Checks if the AST contains a node of the given type.
287+ ///
288+ /// Example:
289+ /// ```ignore
290+ /// // returns true if there is a `for` loop anywhere in the AST.
291+ /// nodes.contains(AstType::ForStatement)
292+ /// // returns true if there is an `ImportDeclaration` anywhere in the AST.
293+ /// nodes.contains(AstType::ImportDeclaration)
294+ /// ```
295+ pub fn contains ( & self , ty : AstType ) -> bool {
296+ self . node_kinds_set . has ( ty)
297+ }
245298}
246299
247300impl < ' a , ' n > IntoIterator for & ' n AstNodes < ' a > {
0 commit comments