Skip to main content

tsz_parser/parser/
node_access.rs

1//! `NodeArena` access methods, `NodeView`, and `NodeAccess` trait.
2//!
3//! This module contains all node access/query methods, the `NodeView` ergonomic wrapper,
4//! `Node` kind utility methods, and the `NodeAccess` trait.
5use super::base::{NodeIndex, NodeList};
6use super::node::{
7    AccessExprData, AccessorData, ArrayTypeData, BinaryExprData, BindingElementData,
8    BindingPatternData, BlockData, CallExprData, CaseClauseData, CatchClauseData, ClassData,
9    CompositeTypeData, ComputedPropertyData, ConditionalExprData, ConditionalTypeData,
10    ConstructorData, DecoratorData, EnumData, EnumMemberData, ExportAssignmentData, ExportDeclData,
11    ExprStatementData, ExprWithTypeArgsData, ExtendedNodeInfo, ForInOfData, FunctionData,
12    FunctionTypeData, HeritageData, IdentifierData, IfStatementData, ImportClauseData,
13    ImportDeclData, IndexSignatureData, IndexedAccessTypeData, InferTypeData, InterfaceData,
14    JsxAttributeData, JsxAttributesData, JsxClosingData, JsxElementData, JsxExpressionData,
15    JsxFragmentData, JsxNamespacedNameData, JsxOpeningData, JsxSpreadAttributeData, JsxTextData,
16    JumpData, LabeledData, LiteralData, LiteralExprData, LiteralTypeData, LoopData, MappedTypeData,
17    MethodDeclData, ModuleBlockData, ModuleData, NamedImportsData, NamedTupleMemberData, Node,
18    NodeArena, ParameterData, ParenthesizedData, PropertyAssignmentData, PropertyDeclData,
19    QualifiedNameData, ReturnData, ShorthandPropertyData, SignatureData, SourceFileData,
20    SpecifierData, SpreadData, SwitchData, TaggedTemplateData, TemplateExprData,
21    TemplateLiteralTypeData, TemplateSpanData, TryData, TupleTypeData, TypeAliasData,
22    TypeAssertionData, TypeLiteralData, TypeOperatorData, TypeParameterData, TypePredicateData,
23    TypeQueryData, TypeRefData, UnaryExprData, UnaryExprDataEx, VariableData,
24    VariableDeclarationData, WrappedTypeData,
25};
26use super::syntax_kind_ext::{
27    ARRAY_BINDING_PATTERN, ARRAY_LITERAL_EXPRESSION, ARRAY_TYPE, ARROW_FUNCTION, AS_EXPRESSION,
28    AWAIT_EXPRESSION, BINARY_EXPRESSION, BINDING_ELEMENT, BLOCK, BREAK_STATEMENT, CALL_EXPRESSION,
29    CALL_SIGNATURE, CASE_BLOCK, CASE_CLAUSE, CATCH_CLAUSE, CLASS_DECLARATION, CLASS_EXPRESSION,
30    CLASS_STATIC_BLOCK_DECLARATION, COMPUTED_PROPERTY_NAME, CONDITIONAL_EXPRESSION,
31    CONDITIONAL_TYPE, CONSTRUCT_SIGNATURE, CONSTRUCTOR, CONSTRUCTOR_TYPE, CONTINUE_STATEMENT,
32    DEBUGGER_STATEMENT, DECORATOR, DEFAULT_CLAUSE, DO_STATEMENT, ELEMENT_ACCESS_EXPRESSION,
33    ENUM_DECLARATION, ENUM_MEMBER, EXPORT_ASSIGNMENT, EXPORT_DECLARATION, EXPORT_SPECIFIER,
34    EXPRESSION_STATEMENT, EXPRESSION_WITH_TYPE_ARGUMENTS, FOR_IN_STATEMENT, FOR_OF_STATEMENT,
35    FOR_STATEMENT, FUNCTION_DECLARATION, FUNCTION_EXPRESSION, FUNCTION_TYPE, GET_ACCESSOR,
36    HERITAGE_CLAUSE, IF_STATEMENT, IMPORT_CLAUSE, IMPORT_DECLARATION, IMPORT_EQUALS_DECLARATION,
37    IMPORT_SPECIFIER, IMPORT_TYPE, INDEX_SIGNATURE, INDEXED_ACCESS_TYPE, INFER_TYPE,
38    INTERFACE_DECLARATION, INTERSECTION_TYPE, JSX_ATTRIBUTE, JSX_ATTRIBUTES, JSX_CLOSING_ELEMENT,
39    JSX_ELEMENT, JSX_EXPRESSION, JSX_FRAGMENT, JSX_NAMESPACED_NAME, JSX_OPENING_ELEMENT,
40    JSX_SELF_CLOSING_ELEMENT, JSX_SPREAD_ATTRIBUTE, LABELED_STATEMENT, LITERAL_TYPE, MAPPED_TYPE,
41    METHOD_DECLARATION, METHOD_SIGNATURE, MODULE_BLOCK, MODULE_DECLARATION, NAMED_EXPORTS,
42    NAMED_IMPORTS, NAMED_TUPLE_MEMBER, NAMESPACE_EXPORT, NAMESPACE_EXPORT_DECLARATION,
43    NAMESPACE_IMPORT, NEW_EXPRESSION, NON_NULL_EXPRESSION, OBJECT_BINDING_PATTERN,
44    OBJECT_LITERAL_EXPRESSION, OPTIONAL_TYPE, PARAMETER, PARENTHESIZED_EXPRESSION,
45    PARENTHESIZED_TYPE, POSTFIX_UNARY_EXPRESSION, PREFIX_UNARY_EXPRESSION,
46    PROPERTY_ACCESS_EXPRESSION, PROPERTY_ASSIGNMENT, PROPERTY_DECLARATION, PROPERTY_SIGNATURE,
47    QUALIFIED_NAME, REST_TYPE, RETURN_STATEMENT, SATISFIES_EXPRESSION, SET_ACCESSOR,
48    SHORTHAND_PROPERTY_ASSIGNMENT, SOURCE_FILE, SPREAD_ASSIGNMENT, SPREAD_ELEMENT,
49    SWITCH_STATEMENT, TAGGED_TEMPLATE_EXPRESSION, TEMPLATE_EXPRESSION, TEMPLATE_LITERAL_TYPE,
50    TEMPLATE_SPAN, THROW_STATEMENT, TRY_STATEMENT, TUPLE_TYPE, TYPE_ALIAS_DECLARATION,
51    TYPE_ASSERTION, TYPE_LITERAL, TYPE_OPERATOR, TYPE_PARAMETER, TYPE_PREDICATE, TYPE_QUERY,
52    TYPE_REFERENCE, UNION_TYPE, VARIABLE_DECLARATION, VARIABLE_DECLARATION_LIST,
53    VARIABLE_STATEMENT, WHILE_STATEMENT, WITH_STATEMENT, YIELD_EXPRESSION,
54};
55
56impl NodeArena {
57    /// Get a thin node by index
58    #[inline]
59    #[must_use]
60    pub fn get(&self, index: NodeIndex) -> Option<&Node> {
61        if index.is_none() {
62            None
63        } else {
64            self.nodes.get(index.0 as usize)
65        }
66    }
67
68    /// Get a mutable thin node by index
69    #[inline]
70    #[must_use]
71    pub fn get_mut(&mut self, index: NodeIndex) -> Option<&mut Node> {
72        if index.is_none() {
73            None
74        } else {
75            self.nodes.get_mut(index.0 as usize)
76        }
77    }
78
79    /// Get extended info for a node
80    #[inline]
81    #[must_use]
82    pub fn get_extended(&self, index: NodeIndex) -> Option<&ExtendedNodeInfo> {
83        if index.is_none() {
84            None
85        } else {
86            self.extended_info.get(index.0 as usize)
87        }
88    }
89
90    /// Get mutable extended info for a node
91    #[inline]
92    #[must_use]
93    pub fn get_extended_mut(&mut self, index: NodeIndex) -> Option<&mut ExtendedNodeInfo> {
94        if index.is_none() {
95            None
96        } else {
97            self.extended_info.get_mut(index.0 as usize)
98        }
99    }
100
101    /// Get identifier data for a node.
102    /// Returns None if node is not an identifier or has no data.
103    #[inline]
104    #[must_use]
105    pub fn get_identifier(&self, node: &Node) -> Option<&IdentifierData> {
106        use tsz_scanner::SyntaxKind;
107        if node.has_data()
108            && (node.kind == SyntaxKind::Identifier as u16
109                || node.kind == SyntaxKind::PrivateIdentifier as u16)
110        {
111            self.identifiers.get(node.data_index as usize)
112        } else {
113            None
114        }
115    }
116
117    /// Get literal data for a node.
118    /// Returns None if node is not a literal or has no data.
119    #[inline]
120    #[must_use]
121    pub fn get_literal(&self, node: &Node) -> Option<&LiteralData> {
122        use tsz_scanner::SyntaxKind;
123        if node.has_data()
124            && matches!(node.kind,
125                k if k == SyntaxKind::StringLiteral as u16 ||
126                     k == SyntaxKind::NumericLiteral as u16 ||
127                     k == SyntaxKind::BigIntLiteral as u16 ||
128                     k == SyntaxKind::RegularExpressionLiteral as u16 ||
129                     k == SyntaxKind::NoSubstitutionTemplateLiteral as u16 ||
130                     k == SyntaxKind::TemplateHead as u16 ||
131                     k == SyntaxKind::TemplateMiddle as u16 ||
132                     k == SyntaxKind::TemplateTail as u16
133            )
134        {
135            self.literals.get(node.data_index as usize)
136        } else {
137            None
138        }
139    }
140
141    /// Get binary expression data.
142    /// Returns None if node is not a binary expression or has no data.
143    #[inline]
144    #[must_use]
145    pub fn get_binary_expr(&self, node: &Node) -> Option<&BinaryExprData> {
146        use super::syntax_kind_ext::BINARY_EXPRESSION;
147        if node.has_data() && node.kind == BINARY_EXPRESSION {
148            self.binary_exprs.get(node.data_index as usize)
149        } else {
150            None
151        }
152    }
153
154    /// Get call expression data.
155    /// Returns None if node is not a call/new expression or has no data.
156    #[inline]
157    #[must_use]
158    pub fn get_call_expr(&self, node: &Node) -> Option<&CallExprData> {
159        use super::syntax_kind_ext::{CALL_EXPRESSION, NEW_EXPRESSION};
160        if node.has_data() && (node.kind == CALL_EXPRESSION || node.kind == NEW_EXPRESSION) {
161            self.call_exprs.get(node.data_index as usize)
162        } else {
163            None
164        }
165    }
166
167    /// Check if a function-like node is immediately invoked (IIFE pattern).
168    ///
169    /// Detects patterns like `(function() {})()`, `(() => expr)()`,
170    /// `((fn))()` (arbitrary paren nesting), and `new (function() {})()`.
171    #[must_use]
172    pub fn is_immediately_invoked(&self, func_idx: NodeIndex) -> bool {
173        use super::syntax_kind_ext::{CALL_EXPRESSION, NEW_EXPRESSION, PARENTHESIZED_EXPRESSION};
174
175        let mut current = func_idx;
176        // Guard against pathological nesting depth
177        for _ in 0..100 {
178            let Some(ext) = self.get_extended(current) else {
179                return false;
180            };
181            if ext.parent.is_none() {
182                return false;
183            }
184            let Some(parent_node) = self.get(ext.parent) else {
185                return false;
186            };
187            if parent_node.kind == PARENTHESIZED_EXPRESSION {
188                current = ext.parent;
189                continue;
190            }
191            if (parent_node.kind == CALL_EXPRESSION || parent_node.kind == NEW_EXPRESSION)
192                && let Some(call) = self.get_call_expr(parent_node)
193                && call.expression == current
194            {
195                return true;
196            }
197            return false;
198        }
199        false
200    }
201
202    /// Skip through parenthesized expressions to the underlying expression.
203    ///
204    /// Unwraps any number of `(expr)` wrappers.
205    /// Uses a bounded loop (max 100 iterations) to guard against pathological input.
206    #[must_use]
207    pub fn skip_parenthesized(&self, mut idx: NodeIndex) -> NodeIndex {
208        for _ in 0..100 {
209            let Some(node) = self.get(idx) else {
210                return idx;
211            };
212            if node.kind == PARENTHESIZED_EXPRESSION
213                && let Some(paren) = self.get_parenthesized(node) {
214                    idx = paren.expression;
215                    continue;
216                }
217            return idx;
218        }
219        idx
220    }
221
222    /// Skip through parenthesized, non-null assertion, and type assertion expressions.
223    ///
224    /// Unwraps `(expr)`, `expr!`, `expr as T`, `<T>expr`, and `expr satisfies T` wrappers.
225    /// Uses a bounded loop (max 100 iterations) to guard against pathological input.
226    #[must_use]
227    pub fn skip_parenthesized_and_assertions(&self, mut idx: NodeIndex) -> NodeIndex {
228        for _ in 0..100 {
229            let Some(node) = self.get(idx) else {
230                return idx;
231            };
232            if node.kind == PARENTHESIZED_EXPRESSION
233                && let Some(paren) = self.get_parenthesized(node)
234            {
235                idx = paren.expression;
236                continue;
237            }
238            if node.kind == NON_NULL_EXPRESSION
239                && let Some(unary) = self.get_unary_expr_ex(node)
240            {
241                idx = unary.expression;
242                continue;
243            }
244            if (node.kind == TYPE_ASSERTION
245                || node.kind == AS_EXPRESSION
246                || node.kind == SATISFIES_EXPRESSION)
247                && let Some(assertion) = self.get_type_assertion(node)
248            {
249                idx = assertion.expression;
250                continue;
251            }
252            return idx;
253        }
254        idx
255    }
256
257    /// Check whether a namespace/module declaration is instantiated (has runtime value declarations).
258    ///
259    /// Returns `true` if the namespace contains value declarations (variables, functions,
260    /// classes, enums, expression statements, export assignments), or is a
261    /// `NAMESPACE_EXPORT_DECLARATION` (`export as namespace X`), which always produces a
262    /// runtime global.
263    ///
264    /// Recursively walks dotted namespaces (`namespace Foo.Bar`) and `EXPORT_DECLARATION`
265    /// wrappers to find the innermost `MODULE_BLOCK`, then checks each statement.
266    #[must_use]
267    pub fn is_namespace_instantiated(&self, namespace_idx: NodeIndex) -> bool {
268        let Some(node) = self.get(namespace_idx) else {
269            return false;
270        };
271
272        // `export as namespace X` always creates a global runtime value.
273        if node.kind == NAMESPACE_EXPORT_DECLARATION {
274            return true;
275        }
276
277        if node.kind != MODULE_DECLARATION {
278            return false;
279        }
280        let Some(module_decl) = self.get_module(node) else {
281            return false;
282        };
283        self.module_body_has_runtime_members(module_decl.body)
284    }
285
286    /// Check whether a module body contains runtime value declarations.
287    ///
288    /// Helper for [`is_namespace_instantiated`]. Handles dotted namespaces
289    /// (body is another `MODULE_DECLARATION`) and `MODULE_BLOCK` bodies.
290    fn module_body_has_runtime_members(&self, body_idx: NodeIndex) -> bool {
291        if body_idx.is_none() {
292            return false;
293        }
294        let Some(body_node) = self.get(body_idx) else {
295            return false;
296        };
297
298        // Dotted namespace: `namespace Foo.Bar { ... }` — recurse into inner module
299        if body_node.kind == MODULE_DECLARATION {
300            return self.is_namespace_instantiated(body_idx);
301        }
302
303        if body_node.kind != MODULE_BLOCK {
304            return false;
305        }
306
307        let Some(module_block) = self.get_module_block(body_node) else {
308            return false;
309        };
310        let Some(statements) = &module_block.statements else {
311            return false;
312        };
313
314        for &stmt_idx in &statements.nodes {
315            let Some(stmt_node) = self.get(stmt_idx) else {
316                continue;
317            };
318            if self.is_runtime_module_statement(stmt_node, stmt_idx) {
319                return true;
320            }
321        }
322
323        false
324    }
325
326    /// Check if a statement inside a module block is a runtime value declaration.
327    fn is_runtime_module_statement(&self, node: &Node, node_idx: NodeIndex) -> bool {
328        match node.kind {
329            k if k == VARIABLE_STATEMENT
330                || k == FUNCTION_DECLARATION
331                || k == CLASS_DECLARATION
332                || k == ENUM_DECLARATION
333                || k == EXPRESSION_STATEMENT
334                || k == EXPORT_ASSIGNMENT =>
335            {
336                true
337            }
338            k if k == EXPORT_DECLARATION => {
339                if let Some(export_decl) = self.get_export_decl(node)
340                    && let Some(clause) = self.get(export_decl.export_clause)
341                {
342                    match clause.kind {
343                        k if k == VARIABLE_STATEMENT
344                            || k == FUNCTION_DECLARATION
345                            || k == CLASS_DECLARATION
346                            || k == ENUM_DECLARATION =>
347                        {
348                            true
349                        }
350                        k if k == MODULE_DECLARATION => {
351                            self.is_namespace_instantiated(export_decl.export_clause)
352                        }
353                        _ => false,
354                    }
355                } else {
356                    false
357                }
358            }
359            k if k == MODULE_DECLARATION => self.is_namespace_instantiated(node_idx),
360            _ => false,
361        }
362    }
363
364    /// Get access expression data (property access or element access).
365    /// Returns None if node is not an access expression or has no data.
366    #[inline]
367    #[must_use]
368    pub fn get_access_expr(&self, node: &Node) -> Option<&AccessExprData> {
369        use super::syntax_kind_ext::{ELEMENT_ACCESS_EXPRESSION, PROPERTY_ACCESS_EXPRESSION};
370        if node.has_data()
371            && (node.kind == PROPERTY_ACCESS_EXPRESSION || node.kind == ELEMENT_ACCESS_EXPRESSION)
372        {
373            self.access_exprs.get(node.data_index as usize)
374        } else {
375            None
376        }
377    }
378
379    /// Get conditional expression data (ternary: a ? b : c).
380    /// Returns None if node is not a conditional expression or has no data.
381    #[inline]
382    #[must_use]
383    pub fn get_conditional_expr(&self, node: &Node) -> Option<&ConditionalExprData> {
384        use super::syntax_kind_ext::CONDITIONAL_EXPRESSION;
385        if node.has_data() && node.kind == CONDITIONAL_EXPRESSION {
386            self.conditional_exprs.get(node.data_index as usize)
387        } else {
388            None
389        }
390    }
391
392    /// Get qualified name data (A.B syntax).
393    /// Returns None if node is not a qualified name or has no data.
394    #[inline]
395    #[must_use]
396    pub fn get_qualified_name(&self, node: &Node) -> Option<&QualifiedNameData> {
397        use super::syntax_kind_ext::QUALIFIED_NAME;
398        if node.has_data() && node.kind == QUALIFIED_NAME {
399            self.qualified_names.get(node.data_index as usize)
400        } else {
401            None
402        }
403    }
404
405    /// Get literal expression data (array or object literal).
406    /// Returns None if node is not a literal expression or has no data.
407    #[inline]
408    #[must_use]
409    pub fn get_literal_expr(&self, node: &Node) -> Option<&LiteralExprData> {
410        use super::syntax_kind_ext::{ARRAY_LITERAL_EXPRESSION, OBJECT_LITERAL_EXPRESSION};
411        if node.has_data()
412            && (node.kind == ARRAY_LITERAL_EXPRESSION || node.kind == OBJECT_LITERAL_EXPRESSION)
413        {
414            self.literal_exprs.get(node.data_index as usize)
415        } else {
416            None
417        }
418    }
419
420    /// Get property assignment data.
421    /// Returns None if node is not a property assignment or has no data.
422    #[inline]
423    #[must_use]
424    pub fn get_property_assignment(&self, node: &Node) -> Option<&PropertyAssignmentData> {
425        use super::syntax_kind_ext::PROPERTY_ASSIGNMENT;
426        if node.has_data() && node.kind == PROPERTY_ASSIGNMENT {
427            self.property_assignments.get(node.data_index as usize)
428        } else {
429            None
430        }
431    }
432
433    /// Get type assertion data (as/satisfies/type assertion).
434    /// Returns None if node is not a type assertion or has no data.
435    #[inline]
436    #[must_use]
437    pub fn get_type_assertion(&self, node: &Node) -> Option<&TypeAssertionData> {
438        use super::syntax_kind_ext::{AS_EXPRESSION, SATISFIES_EXPRESSION, TYPE_ASSERTION};
439        if node.has_data()
440            && (node.kind == TYPE_ASSERTION
441                || node.kind == AS_EXPRESSION
442                || node.kind == SATISFIES_EXPRESSION)
443        {
444            self.type_assertions.get(node.data_index as usize)
445        } else {
446            None
447        }
448    }
449
450    /// Get unary expression data (prefix or postfix).
451    /// Returns None if node is not a unary expression or has no data.
452    #[inline]
453    #[must_use]
454    pub fn get_unary_expr(&self, node: &Node) -> Option<&UnaryExprData> {
455        use super::syntax_kind_ext::{POSTFIX_UNARY_EXPRESSION, PREFIX_UNARY_EXPRESSION};
456        if node.has_data()
457            && (node.kind == PREFIX_UNARY_EXPRESSION || node.kind == POSTFIX_UNARY_EXPRESSION)
458        {
459            self.unary_exprs.get(node.data_index as usize)
460        } else {
461            None
462        }
463    }
464
465    /// Get extended unary expression data (await/yield/non-null/spread).
466    /// Returns None if node is not an await/yield/non-null/spread expression or has no data.
467    #[inline]
468    #[must_use]
469    pub fn get_unary_expr_ex(&self, node: &Node) -> Option<&UnaryExprDataEx> {
470        use super::syntax_kind_ext::{
471            AWAIT_EXPRESSION, NON_NULL_EXPRESSION, SPREAD_ELEMENT, YIELD_EXPRESSION,
472        };
473        if node.has_data()
474            && (node.kind == AWAIT_EXPRESSION
475                || node.kind == YIELD_EXPRESSION
476                || node.kind == NON_NULL_EXPRESSION
477                || node.kind == SPREAD_ELEMENT)
478        {
479            self.unary_exprs_ex.get(node.data_index as usize)
480        } else {
481            None
482        }
483    }
484
485    /// Get function data.
486    /// Returns None if node is not a function-like node or has no data.
487    #[inline]
488    #[must_use]
489    pub fn get_function(&self, node: &Node) -> Option<&FunctionData> {
490        if node.has_data()
491            && matches!(
492                node.kind,
493                FUNCTION_DECLARATION | FUNCTION_EXPRESSION | ARROW_FUNCTION
494            )
495        {
496            self.functions.get(node.data_index as usize)
497        } else {
498            None
499        }
500    }
501
502    /// Get class data.
503    /// Returns None if node is not a class declaration/expression or has no data.
504    #[inline]
505    #[must_use]
506    pub fn get_class(&self, node: &Node) -> Option<&ClassData> {
507        use super::syntax_kind_ext::{CLASS_DECLARATION, CLASS_EXPRESSION};
508        if node.has_data() && (node.kind == CLASS_DECLARATION || node.kind == CLASS_EXPRESSION) {
509            self.classes.get(node.data_index as usize)
510        } else {
511            None
512        }
513    }
514
515    /// Get block data.
516    /// Returns None if node is not a block or has no data.
517    #[inline]
518    #[must_use]
519    pub fn get_block(&self, node: &Node) -> Option<&BlockData> {
520        use super::syntax_kind_ext::{BLOCK, CASE_BLOCK, CLASS_STATIC_BLOCK_DECLARATION};
521        if node.has_data()
522            && (node.kind == BLOCK
523                || node.kind == CLASS_STATIC_BLOCK_DECLARATION
524                || node.kind == CASE_BLOCK)
525        {
526            self.blocks.get(node.data_index as usize)
527        } else {
528            None
529        }
530    }
531
532    /// Get source file data.
533    /// Returns None if node is not a source file or has no data.
534    #[inline]
535    #[must_use]
536    pub fn get_source_file(&self, node: &Node) -> Option<&SourceFileData> {
537        use super::syntax_kind_ext::SOURCE_FILE;
538        if node.has_data() && node.kind == SOURCE_FILE {
539            self.source_files.get(node.data_index as usize)
540        } else {
541            None
542        }
543    }
544
545    /// Get variable data (`VariableStatement` or `VariableDeclarationList`).
546    #[inline]
547    #[must_use]
548    pub fn get_variable(&self, node: &Node) -> Option<&VariableData> {
549        use super::syntax_kind_ext::{VARIABLE_DECLARATION_LIST, VARIABLE_STATEMENT};
550        if node.has_data()
551            && (node.kind == VARIABLE_STATEMENT || node.kind == VARIABLE_DECLARATION_LIST)
552        {
553            self.variables.get(node.data_index as usize)
554        } else {
555            None
556        }
557    }
558
559    /// Get variable declaration data.
560    #[inline]
561    #[must_use]
562    pub fn get_variable_declaration(&self, node: &Node) -> Option<&VariableDeclarationData> {
563        use super::syntax_kind_ext::VARIABLE_DECLARATION;
564        if node.has_data() && node.kind == VARIABLE_DECLARATION {
565            self.variable_declarations.get(node.data_index as usize)
566        } else {
567            None
568        }
569    }
570
571    /// Get interface data.
572    #[inline]
573    #[must_use]
574    pub fn get_interface(&self, node: &Node) -> Option<&InterfaceData> {
575        use super::syntax_kind_ext::INTERFACE_DECLARATION;
576        if node.has_data() && node.kind == INTERFACE_DECLARATION {
577            self.interfaces.get(node.data_index as usize)
578        } else {
579            None
580        }
581    }
582
583    /// Get type alias data.
584    #[inline]
585    #[must_use]
586    pub fn get_type_alias(&self, node: &Node) -> Option<&TypeAliasData> {
587        use super::syntax_kind_ext::TYPE_ALIAS_DECLARATION;
588        if node.has_data() && node.kind == TYPE_ALIAS_DECLARATION {
589            self.type_aliases.get(node.data_index as usize)
590        } else {
591            None
592        }
593    }
594
595    /// Get enum data.
596    #[inline]
597    #[must_use]
598    pub fn get_enum(&self, node: &Node) -> Option<&EnumData> {
599        use super::syntax_kind_ext::ENUM_DECLARATION;
600        if node.has_data() && node.kind == ENUM_DECLARATION {
601            self.enums.get(node.data_index as usize)
602        } else {
603            None
604        }
605    }
606
607    /// Get enum member data.
608    #[inline]
609    #[must_use]
610    pub fn get_enum_member(&self, node: &Node) -> Option<&EnumMemberData> {
611        use super::syntax_kind_ext::ENUM_MEMBER;
612        if node.has_data() && node.kind == ENUM_MEMBER {
613            self.enum_members.get(node.data_index as usize)
614        } else {
615            None
616        }
617    }
618
619    /// Get module data.
620    #[inline]
621    #[must_use]
622    pub fn get_module(&self, node: &Node) -> Option<&ModuleData> {
623        use super::syntax_kind_ext::MODULE_DECLARATION;
624        if node.has_data() && node.kind == MODULE_DECLARATION {
625            self.modules.get(node.data_index as usize)
626        } else {
627            None
628        }
629    }
630
631    /// Get module block data.
632    #[inline]
633    #[must_use]
634    pub fn get_module_block(&self, node: &Node) -> Option<&ModuleBlockData> {
635        use super::syntax_kind_ext::MODULE_BLOCK;
636        if node.has_data() && node.kind == MODULE_BLOCK {
637            self.module_blocks.get(node.data_index as usize)
638        } else {
639            None
640        }
641    }
642
643    /// Get if statement data.
644    #[inline]
645    #[must_use]
646    pub fn get_if_statement(&self, node: &Node) -> Option<&IfStatementData> {
647        use super::syntax_kind_ext::IF_STATEMENT;
648        if node.has_data() && node.kind == IF_STATEMENT {
649            self.if_statements.get(node.data_index as usize)
650        } else {
651            None
652        }
653    }
654
655    /// Get loop data (while, for, do-while).
656    #[inline]
657    #[must_use]
658    pub fn get_loop(&self, node: &Node) -> Option<&LoopData> {
659        use super::syntax_kind_ext::{DO_STATEMENT, FOR_STATEMENT, WHILE_STATEMENT};
660        if node.has_data()
661            && (node.kind == WHILE_STATEMENT
662                || node.kind == DO_STATEMENT
663                || node.kind == FOR_STATEMENT)
664        {
665            self.loops.get(node.data_index as usize)
666        } else {
667            None
668        }
669    }
670
671    /// Get for-in/for-of data.
672    #[inline]
673    #[must_use]
674    pub fn get_for_in_of(&self, node: &Node) -> Option<&ForInOfData> {
675        use super::syntax_kind_ext::{FOR_IN_STATEMENT, FOR_OF_STATEMENT};
676        if node.has_data() && (node.kind == FOR_IN_STATEMENT || node.kind == FOR_OF_STATEMENT) {
677            self.for_in_of.get(node.data_index as usize)
678        } else {
679            None
680        }
681    }
682
683    /// Get switch data.
684    #[inline]
685    #[must_use]
686    pub fn get_switch(&self, node: &Node) -> Option<&SwitchData> {
687        use super::syntax_kind_ext::SWITCH_STATEMENT;
688        if node.has_data() && node.kind == SWITCH_STATEMENT {
689            self.switch_data.get(node.data_index as usize)
690        } else {
691            None
692        }
693    }
694
695    /// Get case clause data.
696    #[inline]
697    #[must_use]
698    pub fn get_case_clause(&self, node: &Node) -> Option<&CaseClauseData> {
699        use super::syntax_kind_ext::{CASE_CLAUSE, DEFAULT_CLAUSE};
700        if node.has_data() && (node.kind == CASE_CLAUSE || node.kind == DEFAULT_CLAUSE) {
701            self.case_clauses.get(node.data_index as usize)
702        } else {
703            None
704        }
705    }
706
707    /// Get try data.
708    #[inline]
709    #[must_use]
710    pub fn get_try(&self, node: &Node) -> Option<&TryData> {
711        use super::syntax_kind_ext::TRY_STATEMENT;
712        if node.has_data() && node.kind == TRY_STATEMENT {
713            self.try_data.get(node.data_index as usize)
714        } else {
715            None
716        }
717    }
718
719    /// Get catch clause data.
720    #[inline]
721    #[must_use]
722    pub fn get_catch_clause(&self, node: &Node) -> Option<&CatchClauseData> {
723        use super::syntax_kind_ext::CATCH_CLAUSE;
724        if node.has_data() && node.kind == CATCH_CLAUSE {
725            self.catch_clauses.get(node.data_index as usize)
726        } else {
727            None
728        }
729    }
730
731    /// Get labeled statement data.
732    #[inline]
733    #[must_use]
734    pub fn get_labeled_statement(&self, node: &Node) -> Option<&LabeledData> {
735        use super::syntax_kind_ext::LABELED_STATEMENT;
736        if node.has_data() && node.kind == LABELED_STATEMENT {
737            self.labeled_data.get(node.data_index as usize)
738        } else {
739            None
740        }
741    }
742
743    /// Get jump data (break/continue statements).
744    #[inline]
745    #[must_use]
746    pub fn get_jump_data(&self, node: &Node) -> Option<&JumpData> {
747        use super::syntax_kind_ext::{BREAK_STATEMENT, CONTINUE_STATEMENT};
748        if node.has_data() && (node.kind == BREAK_STATEMENT || node.kind == CONTINUE_STATEMENT) {
749            self.jump_data.get(node.data_index as usize)
750        } else {
751            None
752        }
753    }
754
755    /// Get with statement data (stored in if statement pool).
756    #[inline]
757    #[must_use]
758    pub fn get_with_statement(&self, node: &Node) -> Option<&IfStatementData> {
759        use super::syntax_kind_ext::WITH_STATEMENT;
760        if node.has_data() && node.kind == WITH_STATEMENT {
761            self.if_statements.get(node.data_index as usize)
762        } else {
763            None
764        }
765    }
766
767    /// Get import declaration data (handles both `IMPORT_DECLARATION` and `IMPORT_EQUALS_DECLARATION`).
768    #[inline]
769    #[must_use]
770    pub fn get_import_decl(&self, node: &Node) -> Option<&ImportDeclData> {
771        use super::syntax_kind_ext::{IMPORT_DECLARATION, IMPORT_EQUALS_DECLARATION};
772        if node.has_data()
773            && (node.kind == IMPORT_DECLARATION || node.kind == IMPORT_EQUALS_DECLARATION)
774        {
775            self.import_decls.get(node.data_index as usize)
776        } else {
777            None
778        }
779    }
780
781    /// Get import clause data.
782    #[inline]
783    #[must_use]
784    pub fn get_import_clause(&self, node: &Node) -> Option<&ImportClauseData> {
785        use super::syntax_kind_ext::IMPORT_CLAUSE;
786        if node.has_data() && node.kind == IMPORT_CLAUSE {
787            self.import_clauses.get(node.data_index as usize)
788        } else {
789            None
790        }
791    }
792
793    /// Get named imports/exports data.
794    /// Works for `NAMED_IMPORTS`, `NAMESPACE_IMPORT`, and `NAMED_EXPORTS` (they share the same data structure).
795    #[inline]
796    #[must_use]
797    pub fn get_named_imports(&self, node: &Node) -> Option<&NamedImportsData> {
798        use super::syntax_kind_ext::{NAMED_EXPORTS, NAMED_IMPORTS, NAMESPACE_IMPORT};
799        if node.has_data()
800            && (node.kind == NAMED_IMPORTS
801                || node.kind == NAMED_EXPORTS
802                || node.kind == NAMESPACE_IMPORT)
803        {
804            self.named_imports.get(node.data_index as usize)
805        } else {
806            None
807        }
808    }
809
810    /// Get import/export specifier data.
811    #[inline]
812    #[must_use]
813    pub fn get_specifier(&self, node: &Node) -> Option<&SpecifierData> {
814        use super::syntax_kind_ext::{EXPORT_SPECIFIER, IMPORT_SPECIFIER};
815        if node.has_data() && (node.kind == IMPORT_SPECIFIER || node.kind == EXPORT_SPECIFIER) {
816            self.specifiers.get(node.data_index as usize)
817        } else {
818            None
819        }
820    }
821
822    /// Get export declaration data.
823    #[inline]
824    #[must_use]
825    pub fn get_export_decl(&self, node: &Node) -> Option<&ExportDeclData> {
826        use super::syntax_kind_ext::{EXPORT_DECLARATION, NAMESPACE_EXPORT_DECLARATION};
827        if node.has_data()
828            && (node.kind == EXPORT_DECLARATION || node.kind == NAMESPACE_EXPORT_DECLARATION)
829        {
830            self.export_decls.get(node.data_index as usize)
831        } else {
832            None
833        }
834    }
835
836    /// Get export assignment data (export = expr).
837    #[inline]
838    #[must_use]
839    pub fn get_export_assignment(&self, node: &Node) -> Option<&ExportAssignmentData> {
840        use super::syntax_kind_ext::EXPORT_ASSIGNMENT;
841        if node.has_data() && node.kind == EXPORT_ASSIGNMENT {
842            self.export_assignments.get(node.data_index as usize)
843        } else {
844            None
845        }
846    }
847
848    /// Get parameter data.
849    #[inline]
850    #[must_use]
851    pub fn get_parameter(&self, node: &Node) -> Option<&ParameterData> {
852        use super::syntax_kind_ext::PARAMETER;
853        if node.has_data() && node.kind == PARAMETER {
854            self.parameters.get(node.data_index as usize)
855        } else {
856            None
857        }
858    }
859
860    /// Get property declaration data.
861    #[inline]
862    #[must_use]
863    pub fn get_property_decl(&self, node: &Node) -> Option<&PropertyDeclData> {
864        use super::syntax_kind_ext::PROPERTY_DECLARATION;
865        if node.has_data() && node.kind == PROPERTY_DECLARATION {
866            self.property_decls.get(node.data_index as usize)
867        } else {
868            None
869        }
870    }
871
872    /// Get method declaration data.
873    #[inline]
874    #[must_use]
875    pub fn get_method_decl(&self, node: &Node) -> Option<&MethodDeclData> {
876        use super::syntax_kind_ext::METHOD_DECLARATION;
877        if node.has_data() && node.kind == METHOD_DECLARATION {
878            self.method_decls.get(node.data_index as usize)
879        } else {
880            None
881        }
882    }
883
884    /// Get constructor data.
885    #[inline]
886    #[must_use]
887    pub fn get_constructor(&self, node: &Node) -> Option<&ConstructorData> {
888        use super::syntax_kind_ext::CONSTRUCTOR;
889        if node.has_data() && node.kind == CONSTRUCTOR {
890            self.constructors.get(node.data_index as usize)
891        } else {
892            None
893        }
894    }
895
896    /// Get accessor data (get/set accessor).
897    #[inline]
898    #[must_use]
899    pub fn get_accessor(&self, node: &Node) -> Option<&AccessorData> {
900        use super::syntax_kind_ext::{GET_ACCESSOR, SET_ACCESSOR};
901        if node.has_data() && (node.kind == GET_ACCESSOR || node.kind == SET_ACCESSOR) {
902            self.accessors.get(node.data_index as usize)
903        } else {
904            None
905        }
906    }
907
908    /// Get decorator data.
909    #[inline]
910    #[must_use]
911    pub fn get_decorator(&self, node: &Node) -> Option<&DecoratorData> {
912        use super::syntax_kind_ext::DECORATOR;
913        if node.has_data() && node.kind == DECORATOR {
914            self.decorators.get(node.data_index as usize)
915        } else {
916            None
917        }
918    }
919
920    /// Get type reference data.
921    #[inline]
922    #[must_use]
923    pub fn get_type_ref(&self, node: &Node) -> Option<&TypeRefData> {
924        use super::syntax_kind_ext::TYPE_REFERENCE;
925        if node.has_data() && node.kind == TYPE_REFERENCE {
926            self.type_refs.get(node.data_index as usize)
927        } else {
928            None
929        }
930    }
931
932    /// Get expression statement data (returns the expression node index).
933    #[inline]
934    #[must_use]
935    pub fn get_expression_statement(&self, node: &Node) -> Option<&ExprStatementData> {
936        use super::syntax_kind_ext::EXPRESSION_STATEMENT;
937        if node.has_data() && node.kind == EXPRESSION_STATEMENT {
938            self.expr_statements.get(node.data_index as usize)
939        } else {
940            None
941        }
942    }
943
944    /// Get return statement data (returns the expression node index).
945    #[inline]
946    #[must_use]
947    pub fn get_return_statement(&self, node: &Node) -> Option<&ReturnData> {
948        use super::syntax_kind_ext::{RETURN_STATEMENT, THROW_STATEMENT};
949        if node.has_data() && (node.kind == RETURN_STATEMENT || node.kind == THROW_STATEMENT) {
950            self.return_data.get(node.data_index as usize)
951        } else {
952            None
953        }
954    }
955
956    /// Get JSX element data.
957    #[inline]
958    #[must_use]
959    pub fn get_jsx_element(&self, node: &Node) -> Option<&JsxElementData> {
960        use super::syntax_kind_ext::JSX_ELEMENT;
961        if node.has_data() && node.kind == JSX_ELEMENT {
962            self.jsx_elements.get(node.data_index as usize)
963        } else {
964            None
965        }
966    }
967
968    /// Get JSX opening/self-closing element data.
969    #[inline]
970    #[must_use]
971    pub fn get_jsx_opening(&self, node: &Node) -> Option<&JsxOpeningData> {
972        use super::syntax_kind_ext::{JSX_OPENING_ELEMENT, JSX_SELF_CLOSING_ELEMENT};
973        if node.has_data()
974            && (node.kind == JSX_OPENING_ELEMENT || node.kind == JSX_SELF_CLOSING_ELEMENT)
975        {
976            self.jsx_opening.get(node.data_index as usize)
977        } else {
978            None
979        }
980    }
981
982    /// Get JSX closing element data.
983    #[inline]
984    #[must_use]
985    pub fn get_jsx_closing(&self, node: &Node) -> Option<&JsxClosingData> {
986        use super::syntax_kind_ext::JSX_CLOSING_ELEMENT;
987        if node.has_data() && node.kind == JSX_CLOSING_ELEMENT {
988            self.jsx_closing.get(node.data_index as usize)
989        } else {
990            None
991        }
992    }
993
994    /// Get JSX fragment data.
995    #[inline]
996    #[must_use]
997    pub fn get_jsx_fragment(&self, node: &Node) -> Option<&JsxFragmentData> {
998        use super::syntax_kind_ext::JSX_FRAGMENT;
999        if node.has_data() && node.kind == JSX_FRAGMENT {
1000            self.jsx_fragments.get(node.data_index as usize)
1001        } else {
1002            None
1003        }
1004    }
1005
1006    /// Get JSX attributes data.
1007    #[inline]
1008    #[must_use]
1009    pub fn get_jsx_attributes(&self, node: &Node) -> Option<&JsxAttributesData> {
1010        use super::syntax_kind_ext::JSX_ATTRIBUTES;
1011        if node.has_data() && node.kind == JSX_ATTRIBUTES {
1012            self.jsx_attributes.get(node.data_index as usize)
1013        } else {
1014            None
1015        }
1016    }
1017
1018    /// Get JSX attribute data.
1019    #[inline]
1020    #[must_use]
1021    pub fn get_jsx_attribute(&self, node: &Node) -> Option<&JsxAttributeData> {
1022        use super::syntax_kind_ext::JSX_ATTRIBUTE;
1023        if node.has_data() && node.kind == JSX_ATTRIBUTE {
1024            self.jsx_attribute.get(node.data_index as usize)
1025        } else {
1026            None
1027        }
1028    }
1029
1030    /// Get JSX spread attribute data.
1031    #[inline]
1032    #[must_use]
1033    pub fn get_jsx_spread_attribute(&self, node: &Node) -> Option<&JsxSpreadAttributeData> {
1034        use super::syntax_kind_ext::JSX_SPREAD_ATTRIBUTE;
1035        if node.has_data() && node.kind == JSX_SPREAD_ATTRIBUTE {
1036            self.jsx_spread_attributes.get(node.data_index as usize)
1037        } else {
1038            None
1039        }
1040    }
1041
1042    /// Get JSX expression data.
1043    #[inline]
1044    #[must_use]
1045    pub fn get_jsx_expression(&self, node: &Node) -> Option<&JsxExpressionData> {
1046        use super::syntax_kind_ext::JSX_EXPRESSION;
1047        if node.has_data() && node.kind == JSX_EXPRESSION {
1048            self.jsx_expressions.get(node.data_index as usize)
1049        } else {
1050            None
1051        }
1052    }
1053
1054    /// Get JSX text data.
1055    #[inline]
1056    #[must_use]
1057    pub fn get_jsx_text(&self, node: &Node) -> Option<&JsxTextData> {
1058        use tsz_scanner::SyntaxKind;
1059        if node.has_data() && node.kind == SyntaxKind::JsxText as u16 {
1060            self.jsx_text.get(node.data_index as usize)
1061        } else {
1062            None
1063        }
1064    }
1065
1066    /// Get JSX namespaced name data.
1067    #[inline]
1068    #[must_use]
1069    pub fn get_jsx_namespaced_name(&self, node: &Node) -> Option<&JsxNamespacedNameData> {
1070        use super::syntax_kind_ext::JSX_NAMESPACED_NAME;
1071        if node.has_data() && node.kind == JSX_NAMESPACED_NAME {
1072            self.jsx_namespaced_names.get(node.data_index as usize)
1073        } else {
1074            None
1075        }
1076    }
1077
1078    /// Get signature data (call, construct, method, property signatures).
1079    #[inline]
1080    #[must_use]
1081    pub fn get_signature(&self, node: &Node) -> Option<&SignatureData> {
1082        use super::syntax_kind_ext::{
1083            CALL_SIGNATURE, CONSTRUCT_SIGNATURE, METHOD_SIGNATURE, PROPERTY_SIGNATURE,
1084        };
1085        if node.has_data()
1086            && (node.kind == CALL_SIGNATURE
1087                || node.kind == CONSTRUCT_SIGNATURE
1088                || node.kind == METHOD_SIGNATURE
1089                || node.kind == PROPERTY_SIGNATURE)
1090        {
1091            self.signatures.get(node.data_index as usize)
1092        } else {
1093            None
1094        }
1095    }
1096
1097    /// Get index signature data.
1098    #[inline]
1099    #[must_use]
1100    pub fn get_index_signature(&self, node: &Node) -> Option<&IndexSignatureData> {
1101        use super::syntax_kind_ext::INDEX_SIGNATURE;
1102        if node.has_data() && node.kind == INDEX_SIGNATURE {
1103            self.index_signatures.get(node.data_index as usize)
1104        } else {
1105            None
1106        }
1107    }
1108
1109    /// Get heritage clause data.
1110    #[inline]
1111    #[must_use]
1112    pub fn get_heritage_clause(&self, node: &Node) -> Option<&HeritageData> {
1113        use super::syntax_kind_ext::HERITAGE_CLAUSE;
1114        if node.has_data() && node.kind == HERITAGE_CLAUSE {
1115            self.heritage_clauses.get(node.data_index as usize)
1116        } else {
1117            None
1118        }
1119    }
1120
1121    /// Get composite type data (union or intersection).
1122    #[inline]
1123    #[must_use]
1124    pub fn get_composite_type(&self, node: &Node) -> Option<&CompositeTypeData> {
1125        use super::syntax_kind_ext::{INTERSECTION_TYPE, UNION_TYPE};
1126        if node.has_data() && (node.kind == UNION_TYPE || node.kind == INTERSECTION_TYPE) {
1127            self.composite_types.get(node.data_index as usize)
1128        } else {
1129            None
1130        }
1131    }
1132
1133    /// Get array type data.
1134    #[inline]
1135    #[must_use]
1136    pub fn get_array_type(&self, node: &Node) -> Option<&ArrayTypeData> {
1137        use super::syntax_kind_ext::ARRAY_TYPE;
1138        if node.has_data() && node.kind == ARRAY_TYPE {
1139            self.array_types.get(node.data_index as usize)
1140        } else {
1141            None
1142        }
1143    }
1144
1145    /// Get tuple type data.
1146    #[inline]
1147    #[must_use]
1148    pub fn get_tuple_type(&self, node: &Node) -> Option<&TupleTypeData> {
1149        use super::syntax_kind_ext::TUPLE_TYPE;
1150        if node.has_data() && node.kind == TUPLE_TYPE {
1151            self.tuple_types.get(node.data_index as usize)
1152        } else {
1153            None
1154        }
1155    }
1156
1157    /// Get function type data.
1158    #[inline]
1159    #[must_use]
1160    pub fn get_function_type(&self, node: &Node) -> Option<&FunctionTypeData> {
1161        use super::syntax_kind_ext::{CONSTRUCTOR_TYPE, FUNCTION_TYPE};
1162        if node.has_data() && (node.kind == FUNCTION_TYPE || node.kind == CONSTRUCTOR_TYPE) {
1163            self.function_types.get(node.data_index as usize)
1164        } else {
1165            None
1166        }
1167    }
1168
1169    /// Get type literal data.
1170    #[inline]
1171    #[must_use]
1172    pub fn get_type_literal(&self, node: &Node) -> Option<&TypeLiteralData> {
1173        use super::syntax_kind_ext::TYPE_LITERAL;
1174        if node.has_data() && node.kind == TYPE_LITERAL {
1175            self.type_literals.get(node.data_index as usize)
1176        } else {
1177            None
1178        }
1179    }
1180
1181    /// Get conditional type data.
1182    #[inline]
1183    #[must_use]
1184    pub fn get_conditional_type(&self, node: &Node) -> Option<&ConditionalTypeData> {
1185        use super::syntax_kind_ext::CONDITIONAL_TYPE;
1186        if node.has_data() && node.kind == CONDITIONAL_TYPE {
1187            self.conditional_types.get(node.data_index as usize)
1188        } else {
1189            None
1190        }
1191    }
1192
1193    /// Get mapped type data.
1194    #[inline]
1195    #[must_use]
1196    pub fn get_mapped_type(&self, node: &Node) -> Option<&MappedTypeData> {
1197        use super::syntax_kind_ext::MAPPED_TYPE;
1198        if node.has_data() && node.kind == MAPPED_TYPE {
1199            self.mapped_types.get(node.data_index as usize)
1200        } else {
1201            None
1202        }
1203    }
1204
1205    /// Get indexed access type data.
1206    #[inline]
1207    #[must_use]
1208    pub fn get_indexed_access_type(&self, node: &Node) -> Option<&IndexedAccessTypeData> {
1209        use super::syntax_kind_ext::INDEXED_ACCESS_TYPE;
1210        if node.has_data() && node.kind == INDEXED_ACCESS_TYPE {
1211            self.indexed_access_types.get(node.data_index as usize)
1212        } else {
1213            None
1214        }
1215    }
1216
1217    /// Get literal type data.
1218    #[inline]
1219    #[must_use]
1220    pub fn get_literal_type(&self, node: &Node) -> Option<&LiteralTypeData> {
1221        use super::syntax_kind_ext::LITERAL_TYPE;
1222        if node.has_data() && node.kind == LITERAL_TYPE {
1223            self.literal_types.get(node.data_index as usize)
1224        } else {
1225            None
1226        }
1227    }
1228
1229    /// Get wrapped type data (parenthesized, optional, rest types).
1230    #[inline]
1231    #[must_use]
1232    pub fn get_wrapped_type(&self, node: &Node) -> Option<&WrappedTypeData> {
1233        use super::syntax_kind_ext::{OPTIONAL_TYPE, PARENTHESIZED_TYPE, REST_TYPE};
1234        if node.has_data()
1235            && (node.kind == PARENTHESIZED_TYPE
1236                || node.kind == OPTIONAL_TYPE
1237                || node.kind == REST_TYPE)
1238        {
1239            self.wrapped_types.get(node.data_index as usize)
1240        } else {
1241            None
1242        }
1243    }
1244
1245    /// Get heritage clause data.
1246    #[inline]
1247    #[must_use]
1248    pub fn get_heritage(&self, node: &Node) -> Option<&HeritageData> {
1249        use super::syntax_kind_ext::HERITAGE_CLAUSE;
1250        if node.has_data() && node.kind == HERITAGE_CLAUSE {
1251            self.heritage_clauses.get(node.data_index as usize)
1252        } else {
1253            None
1254        }
1255    }
1256
1257    /// Get expression with type arguments data (e.g., `extends Base<T>`).
1258    #[inline]
1259    #[must_use]
1260    pub fn get_expr_type_args(&self, node: &Node) -> Option<&ExprWithTypeArgsData> {
1261        use super::syntax_kind_ext::EXPRESSION_WITH_TYPE_ARGUMENTS;
1262        if node.has_data() && node.kind == EXPRESSION_WITH_TYPE_ARGUMENTS {
1263            self.expr_with_type_args.get(node.data_index as usize)
1264        } else {
1265            None
1266        }
1267    }
1268
1269    /// Get type query data (typeof in type position).
1270    #[inline]
1271    #[must_use]
1272    pub fn get_type_query(&self, node: &Node) -> Option<&TypeQueryData> {
1273        use super::syntax_kind_ext::TYPE_QUERY;
1274        if node.has_data() && node.kind == TYPE_QUERY {
1275            self.type_queries.get(node.data_index as usize)
1276        } else {
1277            None
1278        }
1279    }
1280
1281    /// Get type operator data (keyof, unique, readonly).
1282    #[inline]
1283    #[must_use]
1284    pub fn get_type_operator(&self, node: &Node) -> Option<&TypeOperatorData> {
1285        use super::syntax_kind_ext::TYPE_OPERATOR;
1286        if node.has_data() && node.kind == TYPE_OPERATOR {
1287            self.type_operators.get(node.data_index as usize)
1288        } else {
1289            None
1290        }
1291    }
1292
1293    /// Get infer type data.
1294    #[inline]
1295    #[must_use]
1296    pub fn get_infer_type(&self, node: &Node) -> Option<&InferTypeData> {
1297        use super::syntax_kind_ext::INFER_TYPE;
1298        if node.has_data() && node.kind == INFER_TYPE {
1299            self.infer_types.get(node.data_index as usize)
1300        } else {
1301            None
1302        }
1303    }
1304
1305    /// Get template literal type data.
1306    #[inline]
1307    #[must_use]
1308    pub fn get_template_literal_type(&self, node: &Node) -> Option<&TemplateLiteralTypeData> {
1309        use super::syntax_kind_ext::TEMPLATE_LITERAL_TYPE;
1310        if node.has_data() && node.kind == TEMPLATE_LITERAL_TYPE {
1311            self.template_literal_types.get(node.data_index as usize)
1312        } else {
1313            None
1314        }
1315    }
1316
1317    /// Get named tuple member data.
1318    #[inline]
1319    #[must_use]
1320    pub fn get_named_tuple_member(&self, node: &Node) -> Option<&NamedTupleMemberData> {
1321        use super::syntax_kind_ext::NAMED_TUPLE_MEMBER;
1322        if node.has_data() && node.kind == NAMED_TUPLE_MEMBER {
1323            self.named_tuple_members.get(node.data_index as usize)
1324        } else {
1325            None
1326        }
1327    }
1328
1329    /// Get type predicate data.
1330    #[inline]
1331    #[must_use]
1332    pub fn get_type_predicate(&self, node: &Node) -> Option<&TypePredicateData> {
1333        use super::syntax_kind_ext::TYPE_PREDICATE;
1334        if node.has_data() && node.kind == TYPE_PREDICATE {
1335            self.type_predicates.get(node.data_index as usize)
1336        } else {
1337            None
1338        }
1339    }
1340
1341    /// Get type parameter data.
1342    #[inline]
1343    #[must_use]
1344    pub fn get_type_parameter(&self, node: &Node) -> Option<&TypeParameterData> {
1345        use super::syntax_kind_ext::TYPE_PARAMETER;
1346        if node.has_data() && node.kind == TYPE_PARAMETER {
1347            self.type_parameters.get(node.data_index as usize)
1348        } else {
1349            None
1350        }
1351    }
1352
1353    /// Get parenthesized expression data.
1354    /// Returns None if node is not a parenthesized expression or has no data.
1355    #[inline]
1356    #[must_use]
1357    pub fn get_parenthesized(&self, node: &Node) -> Option<&ParenthesizedData> {
1358        use super::syntax_kind_ext::PARENTHESIZED_EXPRESSION;
1359        if node.has_data() && node.kind == PARENTHESIZED_EXPRESSION {
1360            self.parenthesized.get(node.data_index as usize)
1361        } else {
1362            None
1363        }
1364    }
1365
1366    /// Get template expression data.
1367    #[inline]
1368    #[must_use]
1369    pub fn get_template_expr(&self, node: &Node) -> Option<&TemplateExprData> {
1370        use super::syntax_kind_ext::TEMPLATE_EXPRESSION;
1371        if node.has_data() && node.kind == TEMPLATE_EXPRESSION {
1372            self.template_exprs.get(node.data_index as usize)
1373        } else {
1374            None
1375        }
1376    }
1377
1378    /// Get template span data. Accepts both `TEMPLATE_SPAN` (expression-level)
1379    /// and `TEMPLATE_LITERAL_TYPE_SPAN` (type-level) since both store data in
1380    /// the same `template_spans` array.
1381    #[inline]
1382    #[must_use]
1383    pub fn get_template_span(&self, node: &Node) -> Option<&TemplateSpanData> {
1384        use super::syntax_kind_ext::{TEMPLATE_LITERAL_TYPE_SPAN, TEMPLATE_SPAN};
1385        if node.has_data()
1386            && (node.kind == TEMPLATE_SPAN || node.kind == TEMPLATE_LITERAL_TYPE_SPAN)
1387        {
1388            self.template_spans.get(node.data_index as usize)
1389        } else {
1390            None
1391        }
1392    }
1393
1394    /// Get tagged template expression data.
1395    #[inline]
1396    #[must_use]
1397    pub fn get_tagged_template(&self, node: &Node) -> Option<&TaggedTemplateData> {
1398        use super::syntax_kind_ext::TAGGED_TEMPLATE_EXPRESSION;
1399        if node.has_data() && node.kind == TAGGED_TEMPLATE_EXPRESSION {
1400            self.tagged_templates.get(node.data_index as usize)
1401        } else {
1402            None
1403        }
1404    }
1405
1406    /// Get spread element/assignment data.
1407    #[inline]
1408    #[must_use]
1409    pub fn get_spread(&self, node: &Node) -> Option<&SpreadData> {
1410        use super::syntax_kind_ext::{SPREAD_ASSIGNMENT, SPREAD_ELEMENT};
1411        if node.has_data() && (node.kind == SPREAD_ELEMENT || node.kind == SPREAD_ASSIGNMENT) {
1412            self.spread_data.get(node.data_index as usize)
1413        } else {
1414            None
1415        }
1416    }
1417
1418    /// Get shorthand property assignment data.
1419    #[inline]
1420    #[must_use]
1421    pub fn get_shorthand_property(&self, node: &Node) -> Option<&ShorthandPropertyData> {
1422        use super::syntax_kind_ext::SHORTHAND_PROPERTY_ASSIGNMENT;
1423        if node.has_data() && node.kind == SHORTHAND_PROPERTY_ASSIGNMENT {
1424            self.shorthand_properties.get(node.data_index as usize)
1425        } else {
1426            None
1427        }
1428    }
1429
1430    /// Get binding pattern data (`ObjectBindingPattern` or `ArrayBindingPattern`).
1431    #[inline]
1432    #[must_use]
1433    pub fn get_binding_pattern(&self, node: &Node) -> Option<&BindingPatternData> {
1434        if node.has_data() && node.is_binding_pattern() {
1435            self.binding_patterns.get(node.data_index as usize)
1436        } else {
1437            None
1438        }
1439    }
1440
1441    /// Get binding element data.
1442    #[inline]
1443    #[must_use]
1444    pub fn get_binding_element(&self, node: &Node) -> Option<&BindingElementData> {
1445        use super::syntax_kind_ext::BINDING_ELEMENT;
1446        if node.has_data() && node.kind == BINDING_ELEMENT {
1447            self.binding_elements.get(node.data_index as usize)
1448        } else {
1449            None
1450        }
1451    }
1452
1453    /// Get computed property name data
1454    #[inline]
1455    #[must_use]
1456    pub fn get_computed_property(&self, node: &Node) -> Option<&ComputedPropertyData> {
1457        use super::syntax_kind_ext::COMPUTED_PROPERTY_NAME;
1458        if node.has_data() && node.kind == COMPUTED_PROPERTY_NAME {
1459            self.computed_properties.get(node.data_index as usize)
1460        } else {
1461            None
1462        }
1463    }
1464
1465    /// Number of nodes in the arena
1466    #[must_use]
1467    pub const fn len(&self) -> usize {
1468        self.nodes.len()
1469    }
1470
1471    /// Check if arena is empty
1472    #[must_use]
1473    pub const fn is_empty(&self) -> bool {
1474        self.nodes.is_empty()
1475    }
1476}
1477
1478// =============================================================================
1479// Index-based convenience accessors: get(index) + get_TYPE(node) in one call
1480// =============================================================================
1481
1482/// Generate `get_*_at(index: NodeIndex) -> Option<&T>` convenience methods
1483/// that combine `arena.get(index)` with a typed getter in a single call.
1484macro_rules! define_at_accessors {
1485    ($($at_name:ident => $getter:ident -> $ret:ty);* $(;)?) => {
1486        impl NodeArena {
1487            $(
1488                #[inline]
1489#[must_use]
1490                pub fn $at_name(&self, index: NodeIndex) -> Option<&$ret> {
1491                    self.$getter(self.get(index)?)
1492                }
1493            )*
1494        }
1495    };
1496}
1497
1498define_at_accessors! {
1499    get_identifier_at => get_identifier -> IdentifierData;
1500    get_literal_at => get_literal -> LiteralData;
1501    get_binary_expr_at => get_binary_expr -> BinaryExprData;
1502    get_call_expr_at => get_call_expr -> CallExprData;
1503    get_access_expr_at => get_access_expr -> AccessExprData;
1504    get_conditional_expr_at => get_conditional_expr -> ConditionalExprData;
1505    get_qualified_name_at => get_qualified_name -> QualifiedNameData;
1506    get_literal_expr_at => get_literal_expr -> LiteralExprData;
1507    get_property_assignment_at => get_property_assignment -> PropertyAssignmentData;
1508    get_type_assertion_at => get_type_assertion -> TypeAssertionData;
1509    get_unary_expr_at => get_unary_expr -> UnaryExprData;
1510    get_unary_expr_ex_at => get_unary_expr_ex -> UnaryExprDataEx;
1511    get_function_at => get_function -> FunctionData;
1512    get_class_at => get_class -> ClassData;
1513    get_block_at => get_block -> BlockData;
1514    get_source_file_at => get_source_file -> SourceFileData;
1515    get_variable_at => get_variable -> VariableData;
1516    get_variable_declaration_at => get_variable_declaration -> VariableDeclarationData;
1517    get_interface_at => get_interface -> InterfaceData;
1518    get_type_alias_at => get_type_alias -> TypeAliasData;
1519    get_enum_at => get_enum -> EnumData;
1520    get_enum_member_at => get_enum_member -> EnumMemberData;
1521    get_module_at => get_module -> ModuleData;
1522    get_module_block_at => get_module_block -> ModuleBlockData;
1523    get_if_statement_at => get_if_statement -> IfStatementData;
1524    get_loop_at => get_loop -> LoopData;
1525    get_for_in_of_at => get_for_in_of -> ForInOfData;
1526    get_switch_at => get_switch -> SwitchData;
1527    get_case_clause_at => get_case_clause -> CaseClauseData;
1528    get_try_at => get_try -> TryData;
1529    get_catch_clause_at => get_catch_clause -> CatchClauseData;
1530    get_labeled_statement_at => get_labeled_statement -> LabeledData;
1531    get_jump_data_at => get_jump_data -> JumpData;
1532    get_with_statement_at => get_with_statement -> IfStatementData;
1533    get_import_decl_at => get_import_decl -> ImportDeclData;
1534    get_import_clause_at => get_import_clause -> ImportClauseData;
1535    get_named_imports_at => get_named_imports -> NamedImportsData;
1536    get_specifier_at => get_specifier -> SpecifierData;
1537    get_export_decl_at => get_export_decl -> ExportDeclData;
1538    get_export_assignment_at => get_export_assignment -> ExportAssignmentData;
1539    get_parameter_at => get_parameter -> ParameterData;
1540    get_property_decl_at => get_property_decl -> PropertyDeclData;
1541    get_method_decl_at => get_method_decl -> MethodDeclData;
1542    get_constructor_at => get_constructor -> ConstructorData;
1543    get_accessor_at => get_accessor -> AccessorData;
1544    get_decorator_at => get_decorator -> DecoratorData;
1545    get_type_ref_at => get_type_ref -> TypeRefData;
1546    get_expression_statement_at => get_expression_statement -> ExprStatementData;
1547    get_return_statement_at => get_return_statement -> ReturnData;
1548    get_jsx_element_at => get_jsx_element -> JsxElementData;
1549    get_jsx_opening_at => get_jsx_opening -> JsxOpeningData;
1550    get_jsx_closing_at => get_jsx_closing -> JsxClosingData;
1551    get_jsx_fragment_at => get_jsx_fragment -> JsxFragmentData;
1552    get_jsx_attributes_at => get_jsx_attributes -> JsxAttributesData;
1553    get_jsx_attribute_at => get_jsx_attribute -> JsxAttributeData;
1554    get_jsx_spread_attribute_at => get_jsx_spread_attribute -> JsxSpreadAttributeData;
1555    get_jsx_expression_at => get_jsx_expression -> JsxExpressionData;
1556    get_jsx_text_at => get_jsx_text -> JsxTextData;
1557    get_jsx_namespaced_name_at => get_jsx_namespaced_name -> JsxNamespacedNameData;
1558    get_signature_at => get_signature -> SignatureData;
1559    get_index_signature_at => get_index_signature -> IndexSignatureData;
1560    get_heritage_clause_at => get_heritage_clause -> HeritageData;
1561    get_composite_type_at => get_composite_type -> CompositeTypeData;
1562    get_array_type_at => get_array_type -> ArrayTypeData;
1563    get_tuple_type_at => get_tuple_type -> TupleTypeData;
1564    get_function_type_at => get_function_type -> FunctionTypeData;
1565    get_type_literal_at => get_type_literal -> TypeLiteralData;
1566    get_conditional_type_at => get_conditional_type -> ConditionalTypeData;
1567    get_mapped_type_at => get_mapped_type -> MappedTypeData;
1568    get_indexed_access_type_at => get_indexed_access_type -> IndexedAccessTypeData;
1569    get_literal_type_at => get_literal_type -> LiteralTypeData;
1570    get_wrapped_type_at => get_wrapped_type -> WrappedTypeData;
1571    get_expr_type_args_at => get_expr_type_args -> ExprWithTypeArgsData;
1572    get_type_query_at => get_type_query -> TypeQueryData;
1573    get_type_operator_at => get_type_operator -> TypeOperatorData;
1574    get_infer_type_at => get_infer_type -> InferTypeData;
1575    get_template_literal_type_at => get_template_literal_type -> TemplateLiteralTypeData;
1576    get_named_tuple_member_at => get_named_tuple_member -> NamedTupleMemberData;
1577    get_type_predicate_at => get_type_predicate -> TypePredicateData;
1578    get_type_parameter_at => get_type_parameter -> TypeParameterData;
1579    get_parenthesized_at => get_parenthesized -> ParenthesizedData;
1580    get_template_expr_at => get_template_expr -> TemplateExprData;
1581    get_template_span_at => get_template_span -> TemplateSpanData;
1582    get_tagged_template_at => get_tagged_template -> TaggedTemplateData;
1583    get_spread_at => get_spread -> SpreadData;
1584    get_shorthand_property_at => get_shorthand_property -> ShorthandPropertyData;
1585    get_binding_pattern_at => get_binding_pattern -> BindingPatternData;
1586    get_binding_element_at => get_binding_element -> BindingElementData;
1587    get_computed_property_at => get_computed_property -> ComputedPropertyData
1588}
1589
1590// =============================================================================
1591// Node View - Ergonomic wrapper for reading Nodes
1592// =============================================================================
1593
1594/// A view into a node that provides convenient access to both the Node
1595/// header and its type-specific data. This avoids the need to pass the arena
1596/// around when working with node data.
1597#[derive(Clone, Copy)]
1598pub struct NodeView<'a> {
1599    pub node: &'a Node,
1600    pub arena: &'a NodeArena,
1601    pub index: NodeIndex,
1602}
1603
1604impl<'a> NodeView<'a> {
1605    /// Create a new `NodeView`.
1606    #[inline]
1607    #[must_use]
1608    pub fn new(arena: &'a NodeArena, index: NodeIndex) -> Option<Self> {
1609        arena.get(index).map(|node| NodeView { node, arena, index })
1610    }
1611
1612    /// Get the `SyntaxKind`.
1613    #[inline]
1614    #[must_use]
1615    pub const fn kind(&self) -> u16 {
1616        self.node.kind
1617    }
1618
1619    /// Get the start position.
1620    #[inline]
1621    #[must_use]
1622    pub const fn pos(&self) -> u32 {
1623        self.node.pos
1624    }
1625
1626    /// Get the end position.
1627    #[inline]
1628    #[must_use]
1629    pub const fn end(&self) -> u32 {
1630        self.node.end
1631    }
1632
1633    /// Get the flags.
1634    #[inline]
1635    #[must_use]
1636    pub const fn flags(&self) -> u16 {
1637        self.node.flags
1638    }
1639
1640    /// Check if this node has associated data.
1641    #[inline]
1642    #[must_use]
1643    pub const fn has_data(&self) -> bool {
1644        self.node.has_data()
1645    }
1646
1647    /// Get extended node info (`parent`, `id`, modifier/transform flags).
1648    #[inline]
1649    #[must_use]
1650    pub fn extended(&self) -> Option<&'a ExtendedNodeInfo> {
1651        self.arena.get_extended(self.index)
1652    }
1653
1654    /// Get parent node index.
1655    #[inline]
1656    #[must_use]
1657    pub fn parent(&self) -> NodeIndex {
1658        self.extended().map_or(NodeIndex::NONE, |e| e.parent)
1659    }
1660
1661    /// Get node id.
1662    #[inline]
1663    #[must_use]
1664    pub fn id(&self) -> u32 {
1665        self.extended().map_or(0, |e| e.id)
1666    }
1667
1668    /// Get a child node as a `NodeView`.
1669    #[inline]
1670    #[must_use]
1671    pub fn child(&self, index: NodeIndex) -> Option<Self> {
1672        NodeView::new(self.arena, index)
1673    }
1674
1675    // Typed data accessors - return Option<&T> based on node kind
1676
1677    /// Get identifier data (for `Identifier`, `PrivateIdentifier` nodes).
1678    #[inline]
1679    #[must_use]
1680    pub fn as_identifier(&self) -> Option<&'a IdentifierData> {
1681        self.arena.get_identifier(self.node)
1682    }
1683
1684    /// Get literal data (for `StringLiteral`, `NumericLiteral`, etc.).
1685    #[inline]
1686    #[must_use]
1687    pub fn as_literal(&self) -> Option<&'a LiteralData> {
1688        self.arena.get_literal(self.node)
1689    }
1690
1691    /// Get binary expression data
1692    #[inline]
1693    #[must_use]
1694    pub fn as_binary_expr(&self) -> Option<&'a BinaryExprData> {
1695        self.arena.get_binary_expr(self.node)
1696    }
1697
1698    /// Get call expression data
1699    #[inline]
1700    #[must_use]
1701    pub fn as_call_expr(&self) -> Option<&'a CallExprData> {
1702        self.arena.get_call_expr(self.node)
1703    }
1704
1705    /// Get function data
1706    #[inline]
1707    #[must_use]
1708    pub fn as_function(&self) -> Option<&'a FunctionData> {
1709        self.arena.get_function(self.node)
1710    }
1711
1712    /// Get class data
1713    #[inline]
1714    #[must_use]
1715    pub fn as_class(&self) -> Option<&'a ClassData> {
1716        self.arena.get_class(self.node)
1717    }
1718
1719    /// Get block data
1720    #[inline]
1721    #[must_use]
1722    pub fn as_block(&self) -> Option<&'a BlockData> {
1723        self.arena.get_block(self.node)
1724    }
1725
1726    /// Get source file data
1727    #[inline]
1728    #[must_use]
1729    pub fn as_source_file(&self) -> Option<&'a SourceFileData> {
1730        self.arena.get_source_file(self.node)
1731    }
1732}
1733
1734// =============================================================================
1735// Node Kind Utilities
1736// =============================================================================
1737
1738impl Node {
1739    /// Check if this is an identifier node
1740    #[inline]
1741    #[must_use]
1742    pub const fn is_identifier(&self) -> bool {
1743        use tsz_scanner::SyntaxKind;
1744        self.kind == SyntaxKind::Identifier as u16
1745    }
1746
1747    /// Check if this is a string literal
1748    #[inline]
1749    #[must_use]
1750    pub const fn is_string_literal(&self) -> bool {
1751        use tsz_scanner::SyntaxKind;
1752        self.kind == SyntaxKind::StringLiteral as u16
1753    }
1754
1755    /// Check if this is a numeric literal
1756    #[inline]
1757    #[must_use]
1758    pub const fn is_numeric_literal(&self) -> bool {
1759        use tsz_scanner::SyntaxKind;
1760        self.kind == SyntaxKind::NumericLiteral as u16
1761    }
1762
1763    /// Check if this is a function declaration
1764    #[inline]
1765    #[must_use]
1766    pub const fn is_function_declaration(&self) -> bool {
1767        use super::syntax_kind_ext::FUNCTION_DECLARATION;
1768        self.kind == FUNCTION_DECLARATION
1769    }
1770
1771    /// Check if this is a class declaration
1772    #[inline]
1773    #[must_use]
1774    pub const fn is_class_declaration(&self) -> bool {
1775        use super::syntax_kind_ext::CLASS_DECLARATION;
1776        self.kind == CLASS_DECLARATION
1777    }
1778
1779    /// Check if this is any kind of function-like node
1780    #[inline]
1781    #[must_use]
1782    pub const fn is_function_like(&self) -> bool {
1783        matches!(
1784            self.kind,
1785            FUNCTION_DECLARATION
1786                | FUNCTION_EXPRESSION
1787                | ARROW_FUNCTION
1788                | METHOD_DECLARATION
1789                | CONSTRUCTOR
1790                | GET_ACCESSOR
1791                | SET_ACCESSOR
1792        )
1793    }
1794
1795    /// Check if this is a binding pattern (array or object destructuring)
1796    #[inline]
1797    #[must_use]
1798    pub const fn is_binding_pattern(&self) -> bool {
1799        self.kind == OBJECT_BINDING_PATTERN || self.kind == ARRAY_BINDING_PATTERN
1800    }
1801
1802    /// Check if this is a statement
1803    #[inline]
1804    #[must_use]
1805    pub fn is_statement(&self) -> bool {
1806        (BLOCK..=DEBUGGER_STATEMENT).contains(&self.kind) || self.kind == VARIABLE_STATEMENT
1807    }
1808
1809    /// Check if this is a declaration
1810    #[inline]
1811    #[must_use]
1812    pub fn is_declaration(&self) -> bool {
1813        (VARIABLE_DECLARATION..=EXPORT_SPECIFIER).contains(&self.kind)
1814    }
1815
1816    /// Check if this is a type node
1817    #[inline]
1818    #[must_use]
1819    pub fn is_type_node(&self) -> bool {
1820        (TYPE_PREDICATE..=IMPORT_TYPE).contains(&self.kind)
1821    }
1822}
1823
1824impl NodeArena {
1825    #[inline]
1826    fn add_opt_child(children: &mut Vec<NodeIndex>, idx: NodeIndex) {
1827        if idx.is_some() {
1828            children.push(idx);
1829        }
1830    }
1831
1832    #[inline]
1833    fn add_list(children: &mut Vec<NodeIndex>, list: &NodeList) {
1834        children.extend(list.nodes.iter().copied());
1835    }
1836
1837    #[inline]
1838    fn add_opt_list(children: &mut Vec<NodeIndex>, list: Option<&NodeList>) {
1839        if let Some(l) = list {
1840            children.extend(l.nodes.iter().copied());
1841        }
1842    }
1843
1844    fn collect_name_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
1845        match node.kind {
1846            QUALIFIED_NAME => {
1847                if let Some(data) = self.get_qualified_name(node) {
1848                    children.push(data.left);
1849                    children.push(data.right);
1850                    return true;
1851                }
1852            }
1853            COMPUTED_PROPERTY_NAME => {
1854                if let Some(data) = self.get_computed_property(node) {
1855                    children.push(data.expression);
1856                    return true;
1857                }
1858            }
1859            _ => {}
1860        }
1861        false
1862    }
1863
1864    fn collect_expression_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
1865        match node.kind {
1866            BINARY_EXPRESSION => {
1867                if let Some(data) = self.get_binary_expr(node) {
1868                    children.push(data.left);
1869                    children.push(data.right);
1870                    return true;
1871                }
1872            }
1873            PREFIX_UNARY_EXPRESSION | POSTFIX_UNARY_EXPRESSION => {
1874                if let Some(data) = self.get_unary_expr(node) {
1875                    children.push(data.operand);
1876                    return true;
1877                }
1878            }
1879            CALL_EXPRESSION | NEW_EXPRESSION => {
1880                if let Some(data) = self.get_call_expr(node) {
1881                    children.push(data.expression);
1882                    Self::add_opt_list(children, data.type_arguments.as_ref());
1883                    Self::add_opt_list(children, data.arguments.as_ref());
1884                    return true;
1885                }
1886            }
1887            TAGGED_TEMPLATE_EXPRESSION => {
1888                if let Some(data) = self.get_tagged_template(node) {
1889                    children.push(data.tag);
1890                    Self::add_opt_list(children, data.type_arguments.as_ref());
1891                    children.push(data.template);
1892                    return true;
1893                }
1894            }
1895            TEMPLATE_EXPRESSION => {
1896                if let Some(data) = self.get_template_expr(node) {
1897                    children.push(data.head);
1898                    Self::add_list(children, &data.template_spans);
1899                    return true;
1900                }
1901            }
1902            TEMPLATE_SPAN => {
1903                if let Some(data) = self.get_template_span(node) {
1904                    children.push(data.expression);
1905                    children.push(data.literal);
1906                    return true;
1907                }
1908            }
1909            PROPERTY_ACCESS_EXPRESSION | ELEMENT_ACCESS_EXPRESSION => {
1910                if let Some(data) = self.get_access_expr(node) {
1911                    children.push(data.expression);
1912                    children.push(data.name_or_argument);
1913                    return true;
1914                }
1915            }
1916            CONDITIONAL_EXPRESSION => {
1917                if let Some(data) = self.get_conditional_expr(node) {
1918                    children.push(data.condition);
1919                    children.push(data.when_true);
1920                    children.push(data.when_false);
1921                    return true;
1922                }
1923            }
1924            ARROW_FUNCTION | FUNCTION_EXPRESSION => {
1925                if let Some(data) = self.get_function(node) {
1926                    Self::add_opt_list(children, data.modifiers.as_ref());
1927                    Self::add_opt_list(children, data.type_parameters.as_ref());
1928                    Self::add_list(children, &data.parameters);
1929                    Self::add_opt_child(children, data.type_annotation);
1930                    children.push(data.body);
1931                    return true;
1932                }
1933            }
1934            ARRAY_LITERAL_EXPRESSION | OBJECT_LITERAL_EXPRESSION => {
1935                if let Some(data) = self.get_literal_expr(node) {
1936                    Self::add_list(children, &data.elements);
1937                    return true;
1938                }
1939            }
1940            PARENTHESIZED_EXPRESSION => {
1941                if let Some(data) = self.get_parenthesized(node) {
1942                    children.push(data.expression);
1943                    return true;
1944                }
1945            }
1946            YIELD_EXPRESSION | AWAIT_EXPRESSION | NON_NULL_EXPRESSION => {
1947                if let Some(data) = self.get_unary_expr_ex(node) {
1948                    children.push(data.expression);
1949                    return true;
1950                }
1951            }
1952            SPREAD_ASSIGNMENT | SPREAD_ELEMENT => {
1953                if let Some(data) = self.get_spread(node) {
1954                    children.push(data.expression);
1955                    return true;
1956                }
1957            }
1958            AS_EXPRESSION | SATISFIES_EXPRESSION => {
1959                if let Some(data) = self.get_type_assertion(node) {
1960                    children.push(data.expression);
1961                    children.push(data.type_node);
1962                    return true;
1963                }
1964            }
1965            TYPE_ASSERTION => {
1966                if let Some(data) = self.get_type_assertion(node) {
1967                    children.push(data.type_node);
1968                    children.push(data.expression);
1969                    return true;
1970                }
1971            }
1972            _ => {}
1973        }
1974        false
1975    }
1976
1977    fn collect_statement_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
1978        match node.kind {
1979            VARIABLE_STATEMENT => {
1980                if let Some(data) = self.get_variable(node) {
1981                    Self::add_opt_list(children, data.modifiers.as_ref());
1982                    Self::add_list(children, &data.declarations);
1983                    return true;
1984                }
1985            }
1986            VARIABLE_DECLARATION_LIST => {
1987                if let Some(data) = self.get_variable(node) {
1988                    Self::add_list(children, &data.declarations);
1989                    return true;
1990                }
1991            }
1992            VARIABLE_DECLARATION => {
1993                if let Some(data) = self.get_variable_declaration(node) {
1994                    children.push(data.name);
1995                    Self::add_opt_child(children, data.type_annotation);
1996                    Self::add_opt_child(children, data.initializer);
1997                    return true;
1998                }
1999            }
2000            EXPRESSION_STATEMENT => {
2001                if let Some(data) = self.get_expression_statement(node) {
2002                    children.push(data.expression);
2003                    return true;
2004                }
2005            }
2006            IF_STATEMENT => {
2007                if let Some(data) = self.get_if_statement(node) {
2008                    children.push(data.expression);
2009                    children.push(data.then_statement);
2010                    Self::add_opt_child(children, data.else_statement);
2011                    return true;
2012                }
2013            }
2014            WHILE_STATEMENT | DO_STATEMENT | FOR_STATEMENT => {
2015                if let Some(data) = self.get_loop(node) {
2016                    Self::add_opt_child(children, data.initializer);
2017                    Self::add_opt_child(children, data.condition);
2018                    Self::add_opt_child(children, data.incrementor);
2019                    children.push(data.statement);
2020                    return true;
2021                }
2022            }
2023            FOR_IN_STATEMENT | FOR_OF_STATEMENT => {
2024                if let Some(data) = self.get_for_in_of(node) {
2025                    children.push(data.initializer);
2026                    children.push(data.expression);
2027                    children.push(data.statement);
2028                    return true;
2029                }
2030            }
2031            SWITCH_STATEMENT => {
2032                if let Some(data) = self.get_switch(node) {
2033                    children.push(data.expression);
2034                    children.push(data.case_block);
2035                    return true;
2036                }
2037            }
2038            CASE_BLOCK | BLOCK | CLASS_STATIC_BLOCK_DECLARATION => {
2039                if let Some(data) = self.get_block(node) {
2040                    Self::add_list(children, &data.statements);
2041                    return true;
2042                }
2043            }
2044            CASE_CLAUSE | DEFAULT_CLAUSE => {
2045                if let Some(data) = self.get_case_clause(node) {
2046                    Self::add_opt_child(children, data.expression);
2047                    Self::add_list(children, &data.statements);
2048                    return true;
2049                }
2050            }
2051            RETURN_STATEMENT => {
2052                if let Some(data) = self.get_return_statement(node) {
2053                    Self::add_opt_child(children, data.expression);
2054                    return true;
2055                }
2056            }
2057            THROW_STATEMENT => {
2058                if let Some(data) = self.get_return_statement(node) {
2059                    children.push(data.expression);
2060                    return true;
2061                }
2062            }
2063            TRY_STATEMENT => {
2064                if let Some(data) = self.get_try(node) {
2065                    children.push(data.try_block);
2066                    Self::add_opt_child(children, data.catch_clause);
2067                    Self::add_opt_child(children, data.finally_block);
2068                    return true;
2069                }
2070            }
2071            CATCH_CLAUSE => {
2072                if let Some(data) = self.get_catch_clause(node) {
2073                    Self::add_opt_child(children, data.variable_declaration);
2074                    children.push(data.block);
2075                    return true;
2076                }
2077            }
2078            LABELED_STATEMENT => {
2079                if let Some(data) = self.get_labeled_statement(node) {
2080                    children.push(data.label);
2081                    children.push(data.statement);
2082                    return true;
2083                }
2084            }
2085            BREAK_STATEMENT | CONTINUE_STATEMENT => {
2086                if let Some(data) = self.get_jump_data(node) {
2087                    Self::add_opt_child(children, data.label);
2088                    return true;
2089                }
2090            }
2091            WITH_STATEMENT => {
2092                if let Some(data) = self.get_with_statement(node) {
2093                    children.push(data.expression);
2094                    children.push(data.then_statement);
2095                    return true;
2096                }
2097            }
2098            _ => {}
2099        }
2100        false
2101    }
2102
2103    fn collect_declaration_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2104        match node.kind {
2105            FUNCTION_DECLARATION => {
2106                if let Some(data) = self.get_function(node) {
2107                    Self::add_opt_list(children, data.modifiers.as_ref());
2108                    Self::add_opt_child(children, data.name);
2109                    Self::add_opt_list(children, data.type_parameters.as_ref());
2110                    Self::add_list(children, &data.parameters);
2111                    Self::add_opt_child(children, data.type_annotation);
2112                    children.push(data.body);
2113                    return true;
2114                }
2115            }
2116            CLASS_DECLARATION | CLASS_EXPRESSION => {
2117                if let Some(data) = self.get_class(node) {
2118                    Self::add_opt_list(children, data.modifiers.as_ref());
2119                    Self::add_opt_child(children, data.name);
2120                    Self::add_opt_list(children, data.type_parameters.as_ref());
2121                    Self::add_opt_list(children, data.heritage_clauses.as_ref());
2122                    Self::add_list(children, &data.members);
2123                    return true;
2124                }
2125            }
2126            INTERFACE_DECLARATION => {
2127                if let Some(data) = self.get_interface(node) {
2128                    Self::add_opt_list(children, data.modifiers.as_ref());
2129                    Self::add_opt_child(children, data.name);
2130                    Self::add_opt_list(children, data.type_parameters.as_ref());
2131                    Self::add_opt_list(children, data.heritage_clauses.as_ref());
2132                    Self::add_list(children, &data.members);
2133                    return true;
2134                }
2135            }
2136            TYPE_ALIAS_DECLARATION => {
2137                if let Some(data) = self.get_type_alias(node) {
2138                    Self::add_opt_list(children, data.modifiers.as_ref());
2139                    Self::add_opt_child(children, data.name);
2140                    Self::add_opt_list(children, data.type_parameters.as_ref());
2141                    children.push(data.type_node);
2142                    return true;
2143                }
2144            }
2145            ENUM_DECLARATION => {
2146                if let Some(data) = self.get_enum(node) {
2147                    Self::add_opt_list(children, data.modifiers.as_ref());
2148                    Self::add_opt_child(children, data.name);
2149                    Self::add_list(children, &data.members);
2150                    return true;
2151                }
2152            }
2153            ENUM_MEMBER => {
2154                if let Some(data) = self.get_enum_member(node) {
2155                    Self::add_opt_child(children, data.name);
2156                    Self::add_opt_child(children, data.initializer);
2157                    return true;
2158                }
2159            }
2160            MODULE_DECLARATION => {
2161                if let Some(data) = self.get_module(node) {
2162                    Self::add_opt_list(children, data.modifiers.as_ref());
2163                    Self::add_opt_child(children, data.name);
2164                    Self::add_opt_child(children, data.body);
2165                    return true;
2166                }
2167            }
2168            MODULE_BLOCK => {
2169                if let Some(data) = self.get_module_block(node) {
2170                    Self::add_opt_list(children, data.statements.as_ref());
2171                    return true;
2172                }
2173            }
2174            _ => {}
2175        }
2176        false
2177    }
2178
2179    fn collect_import_export_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2180        match node.kind {
2181            IMPORT_DECLARATION | IMPORT_EQUALS_DECLARATION => {
2182                if let Some(data) = self.get_import_decl(node) {
2183                    Self::add_opt_list(children, data.modifiers.as_ref());
2184                    Self::add_opt_child(children, data.import_clause);
2185                    children.push(data.module_specifier);
2186                    Self::add_opt_child(children, data.attributes);
2187                    return true;
2188                }
2189            }
2190            IMPORT_CLAUSE => {
2191                if let Some(data) = self.get_import_clause(node) {
2192                    Self::add_opt_child(children, data.name);
2193                    Self::add_opt_child(children, data.named_bindings);
2194                    return true;
2195                }
2196            }
2197            NAMESPACE_IMPORT | NAMESPACE_EXPORT => {
2198                if let Some(data) = self.get_named_imports(node) {
2199                    children.push(data.name);
2200                    return true;
2201                }
2202            }
2203            NAMED_IMPORTS | NAMED_EXPORTS => {
2204                if let Some(data) = self.get_named_imports(node) {
2205                    Self::add_list(children, &data.elements);
2206                    return true;
2207                }
2208            }
2209            IMPORT_SPECIFIER | EXPORT_SPECIFIER => {
2210                if let Some(data) = self.get_specifier(node) {
2211                    Self::add_opt_child(children, data.property_name);
2212                    children.push(data.name);
2213                    return true;
2214                }
2215            }
2216            EXPORT_DECLARATION => {
2217                if let Some(data) = self.get_export_decl(node) {
2218                    Self::add_opt_list(children, data.modifiers.as_ref());
2219                    Self::add_opt_child(children, data.export_clause);
2220                    Self::add_opt_child(children, data.module_specifier);
2221                    Self::add_opt_child(children, data.attributes);
2222                    return true;
2223                }
2224            }
2225            EXPORT_ASSIGNMENT => {
2226                if let Some(data) = self.get_export_assignment(node) {
2227                    Self::add_opt_list(children, data.modifiers.as_ref());
2228                    children.push(data.expression);
2229                    return true;
2230                }
2231            }
2232            _ => {}
2233        }
2234        false
2235    }
2236
2237    fn collect_type_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2238        match node.kind {
2239            TYPE_REFERENCE => {
2240                if let Some(data) = self.get_type_ref(node) {
2241                    children.push(data.type_name);
2242                    Self::add_opt_list(children, data.type_arguments.as_ref());
2243                    return true;
2244                }
2245            }
2246            FUNCTION_TYPE | CONSTRUCTOR_TYPE => {
2247                if let Some(data) = self.get_function_type(node) {
2248                    Self::add_opt_list(children, data.type_parameters.as_ref());
2249                    Self::add_list(children, &data.parameters);
2250                    children.push(data.type_annotation);
2251                    return true;
2252                }
2253            }
2254            TYPE_QUERY => {
2255                if let Some(data) = self.get_type_query(node) {
2256                    children.push(data.expr_name);
2257                    Self::add_opt_list(children, data.type_arguments.as_ref());
2258                    return true;
2259                }
2260            }
2261            TYPE_LITERAL => {
2262                if let Some(data) = self.get_type_literal(node) {
2263                    Self::add_list(children, &data.members);
2264                    return true;
2265                }
2266            }
2267            ARRAY_TYPE => {
2268                if let Some(data) = self.get_array_type(node) {
2269                    children.push(data.element_type);
2270                    return true;
2271                }
2272            }
2273            TUPLE_TYPE => {
2274                if let Some(data) = self.get_tuple_type(node) {
2275                    Self::add_list(children, &data.elements);
2276                    return true;
2277                }
2278            }
2279            OPTIONAL_TYPE | REST_TYPE | PARENTHESIZED_TYPE => {
2280                if let Some(data) = self.get_wrapped_type(node) {
2281                    children.push(data.type_node);
2282                    return true;
2283                }
2284            }
2285            UNION_TYPE | INTERSECTION_TYPE => {
2286                if let Some(data) = self.get_composite_type(node) {
2287                    Self::add_list(children, &data.types);
2288                    return true;
2289                }
2290            }
2291            CONDITIONAL_TYPE => {
2292                if let Some(data) = self.get_conditional_type(node) {
2293                    children.push(data.check_type);
2294                    children.push(data.extends_type);
2295                    children.push(data.true_type);
2296                    children.push(data.false_type);
2297                    return true;
2298                }
2299            }
2300            INFER_TYPE => {
2301                if let Some(data) = self.get_infer_type(node) {
2302                    children.push(data.type_parameter);
2303                    return true;
2304                }
2305            }
2306            TYPE_OPERATOR => {
2307                if let Some(data) = self.get_type_operator(node) {
2308                    children.push(data.type_node);
2309                    return true;
2310                }
2311            }
2312            INDEXED_ACCESS_TYPE => {
2313                if let Some(data) = self.get_indexed_access_type(node) {
2314                    children.push(data.object_type);
2315                    children.push(data.index_type);
2316                    return true;
2317                }
2318            }
2319            MAPPED_TYPE => {
2320                if let Some(data) = self.get_mapped_type(node) {
2321                    Self::add_opt_child(children, data.type_parameter);
2322                    Self::add_opt_child(children, data.name_type);
2323                    Self::add_opt_child(children, data.type_node);
2324                    Self::add_opt_list(children, data.members.as_ref());
2325                    return true;
2326                }
2327            }
2328            LITERAL_TYPE => {
2329                if let Some(data) = self.get_literal_type(node) {
2330                    Self::add_opt_child(children, data.literal);
2331                    return true;
2332                }
2333            }
2334            TEMPLATE_LITERAL_TYPE => {
2335                if let Some(data) = self.get_template_literal_type(node) {
2336                    children.push(data.head);
2337                    Self::add_list(children, &data.template_spans);
2338                    return true;
2339                }
2340            }
2341            NAMED_TUPLE_MEMBER => {
2342                if let Some(data) = self.get_named_tuple_member(node) {
2343                    children.push(data.name);
2344                    children.push(data.type_node);
2345                    return true;
2346                }
2347            }
2348            TYPE_PREDICATE => {
2349                if let Some(data) = self.get_type_predicate(node) {
2350                    children.push(data.parameter_name);
2351                    Self::add_opt_child(children, data.type_node);
2352                    return true;
2353                }
2354            }
2355            _ => {}
2356        }
2357        false
2358    }
2359
2360    fn collect_member_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2361        match node.kind {
2362            PROPERTY_DECLARATION => {
2363                if let Some(data) = self.get_property_decl(node) {
2364                    Self::add_opt_list(children, data.modifiers.as_ref());
2365                    Self::add_opt_child(children, data.name);
2366                    Self::add_opt_child(children, data.type_annotation);
2367                    Self::add_opt_child(children, data.initializer);
2368                    return true;
2369                }
2370            }
2371            METHOD_DECLARATION => {
2372                if let Some(data) = self.get_method_decl(node) {
2373                    Self::add_opt_list(children, data.modifiers.as_ref());
2374                    Self::add_opt_child(children, data.name);
2375                    Self::add_opt_list(children, data.type_parameters.as_ref());
2376                    Self::add_list(children, &data.parameters);
2377                    Self::add_opt_child(children, data.type_annotation);
2378                    children.push(data.body);
2379                    return true;
2380                }
2381            }
2382            CONSTRUCTOR => {
2383                if let Some(data) = self.get_constructor(node) {
2384                    Self::add_opt_list(children, data.modifiers.as_ref());
2385                    Self::add_opt_list(children, data.type_parameters.as_ref());
2386                    Self::add_list(children, &data.parameters);
2387                    children.push(data.body);
2388                    return true;
2389                }
2390            }
2391            GET_ACCESSOR | SET_ACCESSOR => {
2392                if let Some(data) = self.get_accessor(node) {
2393                    Self::add_opt_list(children, data.modifiers.as_ref());
2394                    Self::add_opt_child(children, data.name);
2395                    Self::add_opt_list(children, data.type_parameters.as_ref());
2396                    Self::add_list(children, &data.parameters);
2397                    Self::add_opt_child(children, data.type_annotation);
2398                    children.push(data.body);
2399                    children.push(data.body);
2400                    return true;
2401                }
2402            }
2403            PARAMETER => {
2404                if let Some(data) = self.get_parameter(node) {
2405                    Self::add_opt_list(children, data.modifiers.as_ref());
2406                    Self::add_opt_child(children, data.name);
2407                    Self::add_opt_child(children, data.type_annotation);
2408                    Self::add_opt_child(children, data.initializer);
2409                    return true;
2410                }
2411            }
2412            TYPE_PARAMETER => {
2413                if let Some(data) = self.get_type_parameter(node) {
2414                    Self::add_opt_list(children, data.modifiers.as_ref());
2415                    children.push(data.name);
2416                    Self::add_opt_child(children, data.constraint);
2417                    Self::add_opt_child(children, data.default);
2418                    return true;
2419                }
2420            }
2421            DECORATOR => {
2422                if let Some(data) = self.get_decorator(node) {
2423                    children.push(data.expression);
2424                    return true;
2425                }
2426            }
2427            HERITAGE_CLAUSE => {
2428                if let Some(data) = self.get_heritage_clause(node) {
2429                    Self::add_list(children, &data.types);
2430                    return true;
2431                }
2432            }
2433            EXPRESSION_WITH_TYPE_ARGUMENTS => {
2434                if let Some(data) = self.get_expr_type_args(node) {
2435                    children.push(data.expression);
2436                    Self::add_opt_list(children, data.type_arguments.as_ref());
2437                    return true;
2438                }
2439            }
2440            _ => {}
2441        }
2442        false
2443    }
2444
2445    fn collect_pattern_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2446        match node.kind {
2447            OBJECT_BINDING_PATTERN | ARRAY_BINDING_PATTERN => {
2448                if let Some(data) = self.get_binding_pattern(node) {
2449                    Self::add_list(children, &data.elements);
2450                    return true;
2451                }
2452            }
2453            BINDING_ELEMENT => {
2454                if let Some(data) = self.get_binding_element(node) {
2455                    Self::add_opt_child(children, data.property_name);
2456                    children.push(data.name);
2457                    Self::add_opt_child(children, data.initializer);
2458                    return true;
2459                }
2460            }
2461            PROPERTY_ASSIGNMENT => {
2462                if let Some(data) = self.get_property_assignment(node) {
2463                    Self::add_opt_list(children, data.modifiers.as_ref());
2464                    Self::add_opt_child(children, data.name);
2465                    children.push(data.initializer);
2466                    return true;
2467                }
2468            }
2469            SHORTHAND_PROPERTY_ASSIGNMENT => {
2470                if let Some(data) = self.get_shorthand_property(node) {
2471                    Self::add_opt_list(children, data.modifiers.as_ref());
2472                    children.push(data.name);
2473                    Self::add_opt_child(children, data.object_assignment_initializer);
2474                    return true;
2475                }
2476            }
2477            _ => {}
2478        }
2479        false
2480    }
2481
2482    fn collect_jsx_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2483        match node.kind {
2484            JSX_ELEMENT => {
2485                if let Some(data) = self.get_jsx_element(node) {
2486                    children.push(data.opening_element);
2487                    Self::add_list(children, &data.children);
2488                    Self::add_opt_child(children, data.closing_element);
2489                    return true;
2490                }
2491            }
2492            JSX_SELF_CLOSING_ELEMENT | JSX_OPENING_ELEMENT => {
2493                if let Some(data) = self.get_jsx_opening(node) {
2494                    children.push(data.tag_name);
2495                    Self::add_opt_list(children, data.type_arguments.as_ref());
2496                    Self::add_opt_child(children, data.attributes);
2497                    return true;
2498                }
2499            }
2500            JSX_CLOSING_ELEMENT => {
2501                if let Some(data) = self.get_jsx_closing(node) {
2502                    children.push(data.tag_name);
2503                    return true;
2504                }
2505            }
2506            JSX_FRAGMENT => {
2507                if let Some(data) = self.get_jsx_fragment(node) {
2508                    children.push(data.opening_fragment);
2509                    Self::add_list(children, &data.children);
2510                    children.push(data.closing_fragment);
2511                    return true;
2512                }
2513            }
2514            JSX_ATTRIBUTES => {
2515                if let Some(data) = self.get_jsx_attributes(node) {
2516                    Self::add_list(children, &data.properties);
2517                    return true;
2518                }
2519            }
2520            JSX_ATTRIBUTE => {
2521                if let Some(data) = self.get_jsx_attribute(node) {
2522                    children.push(data.name);
2523                    Self::add_opt_child(children, data.initializer);
2524                    return true;
2525                }
2526            }
2527            JSX_SPREAD_ATTRIBUTE => {
2528                if let Some(data) = self.get_jsx_spread_attribute(node) {
2529                    children.push(data.expression);
2530                    return true;
2531                }
2532            }
2533            JSX_EXPRESSION => {
2534                if let Some(data) = self.get_jsx_expression(node) {
2535                    Self::add_opt_child(children, data.expression);
2536                    return true;
2537                }
2538            }
2539            JSX_NAMESPACED_NAME => {
2540                if let Some(data) = self.get_jsx_namespaced_name(node) {
2541                    children.push(data.namespace);
2542                    children.push(data.name);
2543                    return true;
2544                }
2545            }
2546            _ => {}
2547        }
2548        false
2549    }
2550
2551    fn collect_signature_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2552        match node.kind {
2553            CALL_SIGNATURE | CONSTRUCT_SIGNATURE => {
2554                if let Some(data) = self.get_signature(node) {
2555                    Self::add_opt_list(children, data.type_parameters.as_ref());
2556                    Self::add_opt_list(children, data.parameters.as_ref());
2557                    Self::add_opt_child(children, data.type_annotation);
2558                    return true;
2559                }
2560            }
2561            INDEX_SIGNATURE => {
2562                if let Some(data) = self.get_index_signature(node) {
2563                    Self::add_opt_list(children, data.modifiers.as_ref());
2564                    Self::add_list(children, &data.parameters);
2565                    Self::add_opt_child(children, data.type_annotation);
2566                    return true;
2567                }
2568            }
2569            PROPERTY_SIGNATURE => {
2570                if let Some(data) = self.get_signature(node) {
2571                    Self::add_opt_list(children, data.modifiers.as_ref());
2572                    Self::add_opt_child(children, data.name);
2573                    Self::add_opt_child(children, data.type_annotation);
2574                    return true;
2575                }
2576            }
2577            METHOD_SIGNATURE => {
2578                if let Some(data) = self.get_signature(node) {
2579                    Self::add_opt_list(children, data.modifiers.as_ref());
2580                    Self::add_opt_child(children, data.name);
2581                    Self::add_opt_list(children, data.type_parameters.as_ref());
2582                    Self::add_opt_list(children, data.parameters.as_ref());
2583                    Self::add_opt_child(children, data.type_annotation);
2584                    return true;
2585                }
2586            }
2587            _ => {}
2588        }
2589        false
2590    }
2591
2592    fn collect_source_children(&self, node: &Node, children: &mut Vec<NodeIndex>) -> bool {
2593        if node.kind == SOURCE_FILE
2594            && let Some(data) = self.get_source_file(node)
2595        {
2596            Self::add_list(children, &data.statements);
2597            children.push(data.end_of_file_token);
2598            return true;
2599        }
2600        false
2601    }
2602}
2603
2604// =============================================================================
2605// Node Access Trait - Unified Interface for Arena Types
2606// =============================================================================
2607
2608/// Common node information that both arena types can provide.
2609/// This struct contains the essential fields needed by most consumers.
2610#[derive(Clone, Debug)]
2611pub struct NodeInfo {
2612    pub kind: u16,
2613    pub flags: u32,
2614    pub modifier_flags: u32,
2615    pub pos: u32,
2616    pub end: u32,
2617    pub parent: NodeIndex,
2618    pub id: u32,
2619}
2620
2621impl NodeInfo {
2622    /// Create from a Node and its extended info
2623    #[must_use]
2624    pub fn from_thin(node: &Node, ext: &ExtendedNodeInfo) -> Self {
2625        Self {
2626            kind: node.kind,
2627            flags: u32::from(node.flags),
2628            modifier_flags: ext.modifier_flags,
2629            pos: node.pos,
2630            end: node.end,
2631            parent: ext.parent,
2632            id: ext.id,
2633        }
2634    }
2635}
2636
2637/// Trait for unified access to AST nodes across different arena implementations.
2638/// This allows consumers (binder, checker, emitter) to work with either
2639/// different arena implementations without code changes.
2640pub trait NodeAccess {
2641    /// Get basic node information by index
2642    fn node_info(&self, index: NodeIndex) -> Option<NodeInfo>;
2643
2644    /// Get the syntax kind of a node
2645    fn kind(&self, index: NodeIndex) -> Option<u16>;
2646
2647    /// Get the source position range
2648    fn pos_end(&self, index: NodeIndex) -> Option<(u32, u32)>;
2649
2650    /// Check if a node exists
2651    fn exists(&self, index: NodeIndex) -> bool {
2652        index.is_some() && self.kind(index).is_some()
2653    }
2654
2655    /// Get identifier text (if this is an identifier node)
2656    fn get_identifier_text(&self, index: NodeIndex) -> Option<&str>;
2657
2658    /// Get literal value text (if this is a literal node)
2659    fn get_literal_text(&self, index: NodeIndex) -> Option<&str>;
2660
2661    /// Get children of a node (for traversal)
2662    fn get_children(&self, index: NodeIndex) -> Vec<NodeIndex>;
2663}
2664
2665/// Implementation of `NodeAccess` for `NodeArena`
2666impl NodeAccess for NodeArena {
2667    fn node_info(&self, index: NodeIndex) -> Option<NodeInfo> {
2668        if index.is_none() {
2669            return None;
2670        }
2671        let node = self.nodes.get(index.0 as usize)?;
2672        let ext = self.extended_info.get(index.0 as usize)?;
2673        Some(NodeInfo::from_thin(node, ext))
2674    }
2675
2676    fn kind(&self, index: NodeIndex) -> Option<u16> {
2677        if index.is_none() {
2678            return None;
2679        }
2680        self.nodes.get(index.0 as usize).map(|n| n.kind)
2681    }
2682
2683    fn pos_end(&self, index: NodeIndex) -> Option<(u32, u32)> {
2684        if index.is_none() {
2685            return None;
2686        }
2687        self.nodes.get(index.0 as usize).map(|n| (n.pos, n.end))
2688    }
2689
2690    fn get_identifier_text(&self, index: NodeIndex) -> Option<&str> {
2691        let node = self.get(index)?;
2692        let data = self.get_identifier(node)?;
2693        // Use atom for O(1) lookup if available, otherwise fall back to escaped_text
2694        Some(self.resolve_identifier_text(data))
2695    }
2696
2697    fn get_literal_text(&self, index: NodeIndex) -> Option<&str> {
2698        let node = self.get(index)?;
2699        let data = self.get_literal(node)?;
2700        Some(&data.text)
2701    }
2702
2703    fn get_children(&self, index: NodeIndex) -> Vec<NodeIndex> {
2704        if index.is_none() {
2705            return Vec::new();
2706        }
2707
2708        let Some(node) = self.nodes.get(index.0 as usize) else {
2709            return Vec::new();
2710        };
2711
2712        let mut children = Vec::new();
2713
2714        if self.collect_name_children(node, &mut children)
2715            || self.collect_expression_children(node, &mut children)
2716            || self.collect_statement_children(node, &mut children)
2717            || self.collect_declaration_children(node, &mut children)
2718            || self.collect_import_export_children(node, &mut children)
2719            || self.collect_type_children(node, &mut children)
2720            || self.collect_member_children(node, &mut children)
2721            || self.collect_pattern_children(node, &mut children)
2722            || self.collect_jsx_children(node, &mut children)
2723            || self.collect_signature_children(node, &mut children)
2724            || self.collect_source_children(node, &mut children)
2725        {
2726            return children;
2727        }
2728
2729        children
2730    }
2731}