From 429d87647173b1a0a4ada27ecc2ea1f518f65752 Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 12 Feb 2026 08:06:28 +0000 Subject: [PATCH] feat(semantic): assign ast node ids during semantic build (#19263) Entire-Checkpoint: a4f3fdbfe5b0 --- crates/oxc_ast/src/generated/ast_kind.rs | 395 +++++++++++++++++++++ crates/oxc_semantic/src/node/nodes.rs | 2 + tasks/ast_tools/src/generators/ast_kind.rs | 44 +++ 3 files changed, 441 insertions(+) diff --git a/crates/oxc_ast/src/generated/ast_kind.rs b/crates/oxc_ast/src/generated/ast_kind.rs index 7f8985300c498..cbb269d5e4e9d 100644 --- a/crates/oxc_ast/src/generated/ast_kind.rs +++ b/crates/oxc_ast/src/generated/ast_kind.rs @@ -8,6 +8,7 @@ use std::ptr; use oxc_allocator::{Address, GetAddress, UnstableAddress}; use oxc_span::{GetSpan, Span}; +use oxc_syntax::node::NodeId; use crate::ast::*; @@ -429,6 +430,400 @@ impl AstKind<'_> { // discriminants, so it's valid to read `AstKind`'s discriminant as `AstType`. unsafe { *ptr::from_ref(self).cast::().as_ref().unwrap_unchecked() } } + + /// Get [`NodeId`] of an [`AstKind`]. + #[inline] + pub fn node_id(&self) -> NodeId { + match self { + Self::Program(it) => it.node_id(), + Self::IdentifierName(it) => it.node_id(), + Self::IdentifierReference(it) => it.node_id(), + Self::BindingIdentifier(it) => it.node_id(), + Self::LabelIdentifier(it) => it.node_id(), + Self::ThisExpression(it) => it.node_id(), + Self::ArrayExpression(it) => it.node_id(), + Self::Elision(it) => it.node_id(), + Self::ObjectExpression(it) => it.node_id(), + Self::ObjectProperty(it) => it.node_id(), + Self::TemplateLiteral(it) => it.node_id(), + Self::TaggedTemplateExpression(it) => it.node_id(), + Self::TemplateElement(it) => it.node_id(), + Self::ComputedMemberExpression(it) => it.node_id(), + Self::StaticMemberExpression(it) => it.node_id(), + Self::PrivateFieldExpression(it) => it.node_id(), + Self::CallExpression(it) => it.node_id(), + Self::NewExpression(it) => it.node_id(), + Self::MetaProperty(it) => it.node_id(), + Self::SpreadElement(it) => it.node_id(), + Self::UpdateExpression(it) => it.node_id(), + Self::UnaryExpression(it) => it.node_id(), + Self::BinaryExpression(it) => it.node_id(), + Self::PrivateInExpression(it) => it.node_id(), + Self::LogicalExpression(it) => it.node_id(), + Self::ConditionalExpression(it) => it.node_id(), + Self::AssignmentExpression(it) => it.node_id(), + Self::ArrayAssignmentTarget(it) => it.node_id(), + Self::ObjectAssignmentTarget(it) => it.node_id(), + Self::AssignmentTargetRest(it) => it.node_id(), + Self::AssignmentTargetWithDefault(it) => it.node_id(), + Self::AssignmentTargetPropertyIdentifier(it) => it.node_id(), + Self::AssignmentTargetPropertyProperty(it) => it.node_id(), + Self::SequenceExpression(it) => it.node_id(), + Self::Super(it) => it.node_id(), + Self::AwaitExpression(it) => it.node_id(), + Self::ChainExpression(it) => it.node_id(), + Self::ParenthesizedExpression(it) => it.node_id(), + Self::Directive(it) => it.node_id(), + Self::Hashbang(it) => it.node_id(), + Self::BlockStatement(it) => it.node_id(), + Self::VariableDeclaration(it) => it.node_id(), + Self::VariableDeclarator(it) => it.node_id(), + Self::EmptyStatement(it) => it.node_id(), + Self::ExpressionStatement(it) => it.node_id(), + Self::IfStatement(it) => it.node_id(), + Self::DoWhileStatement(it) => it.node_id(), + Self::WhileStatement(it) => it.node_id(), + Self::ForStatement(it) => it.node_id(), + Self::ForInStatement(it) => it.node_id(), + Self::ForOfStatement(it) => it.node_id(), + Self::ContinueStatement(it) => it.node_id(), + Self::BreakStatement(it) => it.node_id(), + Self::ReturnStatement(it) => it.node_id(), + Self::WithStatement(it) => it.node_id(), + Self::SwitchStatement(it) => it.node_id(), + Self::SwitchCase(it) => it.node_id(), + Self::LabeledStatement(it) => it.node_id(), + Self::ThrowStatement(it) => it.node_id(), + Self::TryStatement(it) => it.node_id(), + Self::CatchClause(it) => it.node_id(), + Self::CatchParameter(it) => it.node_id(), + Self::DebuggerStatement(it) => it.node_id(), + Self::AssignmentPattern(it) => it.node_id(), + Self::ObjectPattern(it) => it.node_id(), + Self::BindingProperty(it) => it.node_id(), + Self::ArrayPattern(it) => it.node_id(), + Self::BindingRestElement(it) => it.node_id(), + Self::Function(it) => it.node_id(), + Self::FormalParameters(it) => it.node_id(), + Self::FormalParameter(it) => it.node_id(), + Self::FormalParameterRest(it) => it.node_id(), + Self::FunctionBody(it) => it.node_id(), + Self::ArrowFunctionExpression(it) => it.node_id(), + Self::YieldExpression(it) => it.node_id(), + Self::Class(it) => it.node_id(), + Self::ClassBody(it) => it.node_id(), + Self::MethodDefinition(it) => it.node_id(), + Self::PropertyDefinition(it) => it.node_id(), + Self::PrivateIdentifier(it) => it.node_id(), + Self::StaticBlock(it) => it.node_id(), + Self::AccessorProperty(it) => it.node_id(), + Self::ImportExpression(it) => it.node_id(), + Self::ImportDeclaration(it) => it.node_id(), + Self::ImportSpecifier(it) => it.node_id(), + Self::ImportDefaultSpecifier(it) => it.node_id(), + Self::ImportNamespaceSpecifier(it) => it.node_id(), + Self::WithClause(it) => it.node_id(), + Self::ImportAttribute(it) => it.node_id(), + Self::ExportNamedDeclaration(it) => it.node_id(), + Self::ExportDefaultDeclaration(it) => it.node_id(), + Self::ExportAllDeclaration(it) => it.node_id(), + Self::ExportSpecifier(it) => it.node_id(), + Self::V8IntrinsicExpression(it) => it.node_id(), + Self::BooleanLiteral(it) => it.node_id(), + Self::NullLiteral(it) => it.node_id(), + Self::NumericLiteral(it) => it.node_id(), + Self::StringLiteral(it) => it.node_id(), + Self::BigIntLiteral(it) => it.node_id(), + Self::RegExpLiteral(it) => it.node_id(), + Self::JSXElement(it) => it.node_id(), + Self::JSXOpeningElement(it) => it.node_id(), + Self::JSXClosingElement(it) => it.node_id(), + Self::JSXFragment(it) => it.node_id(), + Self::JSXOpeningFragment(it) => it.node_id(), + Self::JSXClosingFragment(it) => it.node_id(), + Self::JSXNamespacedName(it) => it.node_id(), + Self::JSXMemberExpression(it) => it.node_id(), + Self::JSXExpressionContainer(it) => it.node_id(), + Self::JSXEmptyExpression(it) => it.node_id(), + Self::JSXAttribute(it) => it.node_id(), + Self::JSXSpreadAttribute(it) => it.node_id(), + Self::JSXIdentifier(it) => it.node_id(), + Self::JSXSpreadChild(it) => it.node_id(), + Self::JSXText(it) => it.node_id(), + Self::TSThisParameter(it) => it.node_id(), + Self::TSEnumDeclaration(it) => it.node_id(), + Self::TSEnumBody(it) => it.node_id(), + Self::TSEnumMember(it) => it.node_id(), + Self::TSTypeAnnotation(it) => it.node_id(), + Self::TSLiteralType(it) => it.node_id(), + Self::TSConditionalType(it) => it.node_id(), + Self::TSUnionType(it) => it.node_id(), + Self::TSIntersectionType(it) => it.node_id(), + Self::TSParenthesizedType(it) => it.node_id(), + Self::TSTypeOperator(it) => it.node_id(), + Self::TSArrayType(it) => it.node_id(), + Self::TSIndexedAccessType(it) => it.node_id(), + Self::TSTupleType(it) => it.node_id(), + Self::TSNamedTupleMember(it) => it.node_id(), + Self::TSOptionalType(it) => it.node_id(), + Self::TSRestType(it) => it.node_id(), + Self::TSAnyKeyword(it) => it.node_id(), + Self::TSStringKeyword(it) => it.node_id(), + Self::TSBooleanKeyword(it) => it.node_id(), + Self::TSNumberKeyword(it) => it.node_id(), + Self::TSNeverKeyword(it) => it.node_id(), + Self::TSIntrinsicKeyword(it) => it.node_id(), + Self::TSUnknownKeyword(it) => it.node_id(), + Self::TSNullKeyword(it) => it.node_id(), + Self::TSUndefinedKeyword(it) => it.node_id(), + Self::TSVoidKeyword(it) => it.node_id(), + Self::TSSymbolKeyword(it) => it.node_id(), + Self::TSThisType(it) => it.node_id(), + Self::TSObjectKeyword(it) => it.node_id(), + Self::TSBigIntKeyword(it) => it.node_id(), + Self::TSTypeReference(it) => it.node_id(), + Self::TSQualifiedName(it) => it.node_id(), + Self::TSTypeParameterInstantiation(it) => it.node_id(), + Self::TSTypeParameter(it) => it.node_id(), + Self::TSTypeParameterDeclaration(it) => it.node_id(), + Self::TSTypeAliasDeclaration(it) => it.node_id(), + Self::TSClassImplements(it) => it.node_id(), + Self::TSInterfaceDeclaration(it) => it.node_id(), + Self::TSInterfaceBody(it) => it.node_id(), + Self::TSPropertySignature(it) => it.node_id(), + Self::TSIndexSignature(it) => it.node_id(), + Self::TSCallSignatureDeclaration(it) => it.node_id(), + Self::TSMethodSignature(it) => it.node_id(), + Self::TSConstructSignatureDeclaration(it) => it.node_id(), + Self::TSIndexSignatureName(it) => it.node_id(), + Self::TSInterfaceHeritage(it) => it.node_id(), + Self::TSTypePredicate(it) => it.node_id(), + Self::TSModuleDeclaration(it) => it.node_id(), + Self::TSGlobalDeclaration(it) => it.node_id(), + Self::TSModuleBlock(it) => it.node_id(), + Self::TSTypeLiteral(it) => it.node_id(), + Self::TSInferType(it) => it.node_id(), + Self::TSTypeQuery(it) => it.node_id(), + Self::TSImportType(it) => it.node_id(), + Self::TSImportTypeQualifiedName(it) => it.node_id(), + Self::TSFunctionType(it) => it.node_id(), + Self::TSConstructorType(it) => it.node_id(), + Self::TSMappedType(it) => it.node_id(), + Self::TSTemplateLiteralType(it) => it.node_id(), + Self::TSAsExpression(it) => it.node_id(), + Self::TSSatisfiesExpression(it) => it.node_id(), + Self::TSTypeAssertion(it) => it.node_id(), + Self::TSImportEqualsDeclaration(it) => it.node_id(), + Self::TSExternalModuleReference(it) => it.node_id(), + Self::TSNonNullExpression(it) => it.node_id(), + Self::Decorator(it) => it.node_id(), + Self::TSExportAssignment(it) => it.node_id(), + Self::TSNamespaceExportDeclaration(it) => it.node_id(), + Self::TSInstantiationExpression(it) => it.node_id(), + Self::JSDocNullableType(it) => it.node_id(), + Self::JSDocNonNullableType(it) => it.node_id(), + Self::JSDocUnknownType(it) => it.node_id(), + } + } + + /// Set [`NodeId`] of an [`AstKind`]. + #[expect( + clippy::inline_always, + reason = "enables compile-time match elimination in semantic builder" + )] + #[inline(always)] + pub fn set_node_id(&self, node_id: NodeId) { + match self { + Self::Program(it) => it.set_node_id(node_id), + Self::IdentifierName(it) => it.set_node_id(node_id), + Self::IdentifierReference(it) => it.set_node_id(node_id), + Self::BindingIdentifier(it) => it.set_node_id(node_id), + Self::LabelIdentifier(it) => it.set_node_id(node_id), + Self::ThisExpression(it) => it.set_node_id(node_id), + Self::ArrayExpression(it) => it.set_node_id(node_id), + Self::Elision(it) => it.set_node_id(node_id), + Self::ObjectExpression(it) => it.set_node_id(node_id), + Self::ObjectProperty(it) => it.set_node_id(node_id), + Self::TemplateLiteral(it) => it.set_node_id(node_id), + Self::TaggedTemplateExpression(it) => it.set_node_id(node_id), + Self::TemplateElement(it) => it.set_node_id(node_id), + Self::ComputedMemberExpression(it) => it.set_node_id(node_id), + Self::StaticMemberExpression(it) => it.set_node_id(node_id), + Self::PrivateFieldExpression(it) => it.set_node_id(node_id), + Self::CallExpression(it) => it.set_node_id(node_id), + Self::NewExpression(it) => it.set_node_id(node_id), + Self::MetaProperty(it) => it.set_node_id(node_id), + Self::SpreadElement(it) => it.set_node_id(node_id), + Self::UpdateExpression(it) => it.set_node_id(node_id), + Self::UnaryExpression(it) => it.set_node_id(node_id), + Self::BinaryExpression(it) => it.set_node_id(node_id), + Self::PrivateInExpression(it) => it.set_node_id(node_id), + Self::LogicalExpression(it) => it.set_node_id(node_id), + Self::ConditionalExpression(it) => it.set_node_id(node_id), + Self::AssignmentExpression(it) => it.set_node_id(node_id), + Self::ArrayAssignmentTarget(it) => it.set_node_id(node_id), + Self::ObjectAssignmentTarget(it) => it.set_node_id(node_id), + Self::AssignmentTargetRest(it) => it.set_node_id(node_id), + Self::AssignmentTargetWithDefault(it) => it.set_node_id(node_id), + Self::AssignmentTargetPropertyIdentifier(it) => it.set_node_id(node_id), + Self::AssignmentTargetPropertyProperty(it) => it.set_node_id(node_id), + Self::SequenceExpression(it) => it.set_node_id(node_id), + Self::Super(it) => it.set_node_id(node_id), + Self::AwaitExpression(it) => it.set_node_id(node_id), + Self::ChainExpression(it) => it.set_node_id(node_id), + Self::ParenthesizedExpression(it) => it.set_node_id(node_id), + Self::Directive(it) => it.set_node_id(node_id), + Self::Hashbang(it) => it.set_node_id(node_id), + Self::BlockStatement(it) => it.set_node_id(node_id), + Self::VariableDeclaration(it) => it.set_node_id(node_id), + Self::VariableDeclarator(it) => it.set_node_id(node_id), + Self::EmptyStatement(it) => it.set_node_id(node_id), + Self::ExpressionStatement(it) => it.set_node_id(node_id), + Self::IfStatement(it) => it.set_node_id(node_id), + Self::DoWhileStatement(it) => it.set_node_id(node_id), + Self::WhileStatement(it) => it.set_node_id(node_id), + Self::ForStatement(it) => it.set_node_id(node_id), + Self::ForInStatement(it) => it.set_node_id(node_id), + Self::ForOfStatement(it) => it.set_node_id(node_id), + Self::ContinueStatement(it) => it.set_node_id(node_id), + Self::BreakStatement(it) => it.set_node_id(node_id), + Self::ReturnStatement(it) => it.set_node_id(node_id), + Self::WithStatement(it) => it.set_node_id(node_id), + Self::SwitchStatement(it) => it.set_node_id(node_id), + Self::SwitchCase(it) => it.set_node_id(node_id), + Self::LabeledStatement(it) => it.set_node_id(node_id), + Self::ThrowStatement(it) => it.set_node_id(node_id), + Self::TryStatement(it) => it.set_node_id(node_id), + Self::CatchClause(it) => it.set_node_id(node_id), + Self::CatchParameter(it) => it.set_node_id(node_id), + Self::DebuggerStatement(it) => it.set_node_id(node_id), + Self::AssignmentPattern(it) => it.set_node_id(node_id), + Self::ObjectPattern(it) => it.set_node_id(node_id), + Self::BindingProperty(it) => it.set_node_id(node_id), + Self::ArrayPattern(it) => it.set_node_id(node_id), + Self::BindingRestElement(it) => it.set_node_id(node_id), + Self::Function(it) => it.set_node_id(node_id), + Self::FormalParameters(it) => it.set_node_id(node_id), + Self::FormalParameter(it) => it.set_node_id(node_id), + Self::FormalParameterRest(it) => it.set_node_id(node_id), + Self::FunctionBody(it) => it.set_node_id(node_id), + Self::ArrowFunctionExpression(it) => it.set_node_id(node_id), + Self::YieldExpression(it) => it.set_node_id(node_id), + Self::Class(it) => it.set_node_id(node_id), + Self::ClassBody(it) => it.set_node_id(node_id), + Self::MethodDefinition(it) => it.set_node_id(node_id), + Self::PropertyDefinition(it) => it.set_node_id(node_id), + Self::PrivateIdentifier(it) => it.set_node_id(node_id), + Self::StaticBlock(it) => it.set_node_id(node_id), + Self::AccessorProperty(it) => it.set_node_id(node_id), + Self::ImportExpression(it) => it.set_node_id(node_id), + Self::ImportDeclaration(it) => it.set_node_id(node_id), + Self::ImportSpecifier(it) => it.set_node_id(node_id), + Self::ImportDefaultSpecifier(it) => it.set_node_id(node_id), + Self::ImportNamespaceSpecifier(it) => it.set_node_id(node_id), + Self::WithClause(it) => it.set_node_id(node_id), + Self::ImportAttribute(it) => it.set_node_id(node_id), + Self::ExportNamedDeclaration(it) => it.set_node_id(node_id), + Self::ExportDefaultDeclaration(it) => it.set_node_id(node_id), + Self::ExportAllDeclaration(it) => it.set_node_id(node_id), + Self::ExportSpecifier(it) => it.set_node_id(node_id), + Self::V8IntrinsicExpression(it) => it.set_node_id(node_id), + Self::BooleanLiteral(it) => it.set_node_id(node_id), + Self::NullLiteral(it) => it.set_node_id(node_id), + Self::NumericLiteral(it) => it.set_node_id(node_id), + Self::StringLiteral(it) => it.set_node_id(node_id), + Self::BigIntLiteral(it) => it.set_node_id(node_id), + Self::RegExpLiteral(it) => it.set_node_id(node_id), + Self::JSXElement(it) => it.set_node_id(node_id), + Self::JSXOpeningElement(it) => it.set_node_id(node_id), + Self::JSXClosingElement(it) => it.set_node_id(node_id), + Self::JSXFragment(it) => it.set_node_id(node_id), + Self::JSXOpeningFragment(it) => it.set_node_id(node_id), + Self::JSXClosingFragment(it) => it.set_node_id(node_id), + Self::JSXNamespacedName(it) => it.set_node_id(node_id), + Self::JSXMemberExpression(it) => it.set_node_id(node_id), + Self::JSXExpressionContainer(it) => it.set_node_id(node_id), + Self::JSXEmptyExpression(it) => it.set_node_id(node_id), + Self::JSXAttribute(it) => it.set_node_id(node_id), + Self::JSXSpreadAttribute(it) => it.set_node_id(node_id), + Self::JSXIdentifier(it) => it.set_node_id(node_id), + Self::JSXSpreadChild(it) => it.set_node_id(node_id), + Self::JSXText(it) => it.set_node_id(node_id), + Self::TSThisParameter(it) => it.set_node_id(node_id), + Self::TSEnumDeclaration(it) => it.set_node_id(node_id), + Self::TSEnumBody(it) => it.set_node_id(node_id), + Self::TSEnumMember(it) => it.set_node_id(node_id), + Self::TSTypeAnnotation(it) => it.set_node_id(node_id), + Self::TSLiteralType(it) => it.set_node_id(node_id), + Self::TSConditionalType(it) => it.set_node_id(node_id), + Self::TSUnionType(it) => it.set_node_id(node_id), + Self::TSIntersectionType(it) => it.set_node_id(node_id), + Self::TSParenthesizedType(it) => it.set_node_id(node_id), + Self::TSTypeOperator(it) => it.set_node_id(node_id), + Self::TSArrayType(it) => it.set_node_id(node_id), + Self::TSIndexedAccessType(it) => it.set_node_id(node_id), + Self::TSTupleType(it) => it.set_node_id(node_id), + Self::TSNamedTupleMember(it) => it.set_node_id(node_id), + Self::TSOptionalType(it) => it.set_node_id(node_id), + Self::TSRestType(it) => it.set_node_id(node_id), + Self::TSAnyKeyword(it) => it.set_node_id(node_id), + Self::TSStringKeyword(it) => it.set_node_id(node_id), + Self::TSBooleanKeyword(it) => it.set_node_id(node_id), + Self::TSNumberKeyword(it) => it.set_node_id(node_id), + Self::TSNeverKeyword(it) => it.set_node_id(node_id), + Self::TSIntrinsicKeyword(it) => it.set_node_id(node_id), + Self::TSUnknownKeyword(it) => it.set_node_id(node_id), + Self::TSNullKeyword(it) => it.set_node_id(node_id), + Self::TSUndefinedKeyword(it) => it.set_node_id(node_id), + Self::TSVoidKeyword(it) => it.set_node_id(node_id), + Self::TSSymbolKeyword(it) => it.set_node_id(node_id), + Self::TSThisType(it) => it.set_node_id(node_id), + Self::TSObjectKeyword(it) => it.set_node_id(node_id), + Self::TSBigIntKeyword(it) => it.set_node_id(node_id), + Self::TSTypeReference(it) => it.set_node_id(node_id), + Self::TSQualifiedName(it) => it.set_node_id(node_id), + Self::TSTypeParameterInstantiation(it) => it.set_node_id(node_id), + Self::TSTypeParameter(it) => it.set_node_id(node_id), + Self::TSTypeParameterDeclaration(it) => it.set_node_id(node_id), + Self::TSTypeAliasDeclaration(it) => it.set_node_id(node_id), + Self::TSClassImplements(it) => it.set_node_id(node_id), + Self::TSInterfaceDeclaration(it) => it.set_node_id(node_id), + Self::TSInterfaceBody(it) => it.set_node_id(node_id), + Self::TSPropertySignature(it) => it.set_node_id(node_id), + Self::TSIndexSignature(it) => it.set_node_id(node_id), + Self::TSCallSignatureDeclaration(it) => it.set_node_id(node_id), + Self::TSMethodSignature(it) => it.set_node_id(node_id), + Self::TSConstructSignatureDeclaration(it) => it.set_node_id(node_id), + Self::TSIndexSignatureName(it) => it.set_node_id(node_id), + Self::TSInterfaceHeritage(it) => it.set_node_id(node_id), + Self::TSTypePredicate(it) => it.set_node_id(node_id), + Self::TSModuleDeclaration(it) => it.set_node_id(node_id), + Self::TSGlobalDeclaration(it) => it.set_node_id(node_id), + Self::TSModuleBlock(it) => it.set_node_id(node_id), + Self::TSTypeLiteral(it) => it.set_node_id(node_id), + Self::TSInferType(it) => it.set_node_id(node_id), + Self::TSTypeQuery(it) => it.set_node_id(node_id), + Self::TSImportType(it) => it.set_node_id(node_id), + Self::TSImportTypeQualifiedName(it) => it.set_node_id(node_id), + Self::TSFunctionType(it) => it.set_node_id(node_id), + Self::TSConstructorType(it) => it.set_node_id(node_id), + Self::TSMappedType(it) => it.set_node_id(node_id), + Self::TSTemplateLiteralType(it) => it.set_node_id(node_id), + Self::TSAsExpression(it) => it.set_node_id(node_id), + Self::TSSatisfiesExpression(it) => it.set_node_id(node_id), + Self::TSTypeAssertion(it) => it.set_node_id(node_id), + Self::TSImportEqualsDeclaration(it) => it.set_node_id(node_id), + Self::TSExternalModuleReference(it) => it.set_node_id(node_id), + Self::TSNonNullExpression(it) => it.set_node_id(node_id), + Self::Decorator(it) => it.set_node_id(node_id), + Self::TSExportAssignment(it) => it.set_node_id(node_id), + Self::TSNamespaceExportDeclaration(it) => it.set_node_id(node_id), + Self::TSInstantiationExpression(it) => it.set_node_id(node_id), + Self::JSDocNullableType(it) => it.set_node_id(node_id), + Self::JSDocNonNullableType(it) => it.set_node_id(node_id), + Self::JSDocUnknownType(it) => it.set_node_id(node_id), + } + } } impl GetSpan for AstKind<'_> { diff --git a/crates/oxc_semantic/src/node/nodes.rs b/crates/oxc_semantic/src/node/nodes.rs index bc9d0f112da5c..c3152ee287658 100644 --- a/crates/oxc_semantic/src/node/nodes.rs +++ b/crates/oxc_semantic/src/node/nodes.rs @@ -164,6 +164,7 @@ impl<'a> AstNodes<'a> { flags: NodeFlags, ) -> NodeId { let node_id = self.parent_ids.push(parent_node_id); + kind.set_node_id(node_id); let node = AstNode::new(kind, scope_id, node_id); self.nodes.push(node); self.flags.push(flags); @@ -191,6 +192,7 @@ impl<'a> AstNodes<'a> { matches!(kind, AstKind::Program(_)), "Program node must be of kind `AstKind::Program`" ); + kind.set_node_id(NodeId::ROOT); self.parent_ids.push(NodeId::ROOT); self.nodes.push(AstNode::new(kind, scope_id, NodeId::ROOT)); self.flags.push(flags); diff --git a/tasks/ast_tools/src/generators/ast_kind.rs b/tasks/ast_tools/src/generators/ast_kind.rs index c4f4a24e3f9f8..576927dec434d 100644 --- a/tasks/ast_tools/src/generators/ast_kind.rs +++ b/tasks/ast_tools/src/generators/ast_kind.rs @@ -76,6 +76,8 @@ impl Generator for AstKindGenerator { let mut kind_variants = quote!(); let mut span_match_arms = quote!(); let mut address_match_arms = quote!(); + let mut node_id_match_arms = quote!(); + let mut set_node_id_match_arms = quote!(); let mut as_methods = quote!(); let mut next_index = 0u16; @@ -106,6 +108,25 @@ impl Generator for AstKindGenerator { }; address_match_arms.extend(quote!( Self::#type_ident(it) => #get_address, )); + let set_node_id = match type_def { + TypeDef::Struct(struct_def) + if struct_def.fields.iter().any(|field| { + field.name() == "node_id" && field.type_def(schema).as_cell().is_some() + }) => + { + quote!(it.set_node_id(node_id)) + } + _ => quote!(), + }; + + if set_node_id.is_empty() { + node_id_match_arms.extend(quote!( Self::#type_ident(_) => NodeId::DUMMY, )); + set_node_id_match_arms.extend(quote!( Self::#type_ident(_) => {}, )); + } else { + node_id_match_arms.extend(quote!( Self::#type_ident(it) => it.node_id(), )); + set_node_id_match_arms.extend(quote!( Self::#type_ident(it) => #set_node_id, )); + } + let as_method_name = format_ident!("as_{}", type_def.snake_name()); as_methods.extend(quote! { ///@@line_break @@ -133,6 +154,7 @@ impl Generator for AstKindGenerator { ///@@line_break use oxc_allocator::{Address, GetAddress, UnstableAddress}; use oxc_span::{GetSpan, Span}; + use oxc_syntax::node::NodeId; ///@@line_break use crate::ast::*; @@ -167,6 +189,28 @@ impl Generator for AstKindGenerator { ///@ discriminants, so it's valid to read `AstKind`'s discriminant as `AstType`. unsafe { *ptr::from_ref(self).cast::().as_ref().unwrap_unchecked() } } + + ///@@line_break + /// Get [`NodeId`] of an [`AstKind`]. + #[inline] + pub fn node_id(&self) -> NodeId { + match self { + #node_id_match_arms + } + } + + ///@@line_break + /// Set [`NodeId`] of an [`AstKind`]. + #[expect( + clippy::inline_always, + reason = "enables compile-time match elimination in semantic builder" + )] + #[inline(always)] + pub fn set_node_id(&self, node_id: NodeId) { + match self { + #set_node_id_match_arms + } + } } ///@@line_break