macro_rules! inherit_variants {
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit Expression
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
BooleanLiteral(Box<'a, BooleanLiteral>) = 0,
NullLiteral(Box<'a, NullLiteral>) = 1,
NumericLiteral(Box<'a, NumericLiteral<'a>>) = 2,
BigIntLiteral(Box<'a, BigIntLiteral<'a>>) = 3,
RegExpLiteral(Box<'a, RegExpLiteral<'a>>) = 4,
StringLiteral(Box<'a, StringLiteral<'a>>) = 5,
TemplateLiteral(Box<'a, TemplateLiteral<'a>>) = 6,
Identifier(Box<'a, IdentifierReference<'a>>) = 7,
MetaProperty(Box<'a, MetaProperty<'a>>) = 8,
Super(Box<'a, Super>) = 9,
ArrayExpression(Box<'a, ArrayExpression<'a>>) = 10,
ArrowFunctionExpression(Box<'a, ArrowFunctionExpression<'a>>) = 11,
AssignmentExpression(Box<'a, AssignmentExpression<'a>>) = 12,
AwaitExpression(Box<'a, AwaitExpression<'a>>) = 13,
BinaryExpression(Box<'a, BinaryExpression<'a>>) = 14,
CallExpression(Box<'a, CallExpression<'a>>) = 15,
ChainExpression(Box<'a, ChainExpression<'a>>) = 16,
ClassExpression(Box<'a, Class<'a>>) = 17,
ConditionalExpression(Box<'a, ConditionalExpression<'a>>) = 18,
FunctionExpression(Box<'a, Function<'a>>) = 19,
ImportExpression(Box<'a, ImportExpression<'a>>) = 20,
LogicalExpression(Box<'a, LogicalExpression<'a>>) = 21,
NewExpression(Box<'a, NewExpression<'a>>) = 22,
ObjectExpression(Box<'a, ObjectExpression<'a>>) = 23,
ParenthesizedExpression(Box<'a, ParenthesizedExpression<'a>>) = 24,
SequenceExpression(Box<'a, SequenceExpression<'a>>) = 25,
TaggedTemplateExpression(Box<'a, TaggedTemplateExpression<'a>>) = 26,
ThisExpression(Box<'a, ThisExpression>) = 27,
UnaryExpression(Box<'a, UnaryExpression<'a>>) = 28,
UpdateExpression(Box<'a, UpdateExpression<'a>>) = 29,
YieldExpression(Box<'a, YieldExpression<'a>>) = 30,
PrivateInExpression(Box<'a, PrivateInExpression<'a>>) = 31,
JSXElement(Box<'a, JSXElement<'a>>) = 32,
JSXFragment(Box<'a, JSXFragment<'a>>) = 33,
TSAsExpression(Box<'a, TSAsExpression<'a>>) = 34,
TSSatisfiesExpression(Box<'a, TSSatisfiesExpression<'a>>) = 35,
TSTypeAssertion(Box<'a, TSTypeAssertion<'a>>) = 36,
TSNonNullExpression(Box<'a, TSNonNullExpression<'a>>) = 37,
TSInstantiationExpression(Box<'a, TSInstantiationExpression<'a>>) = 38,
V8IntrinsicExpression(Box<'a, V8IntrinsicExpression<'a>>) = 39,
@inherit MemberExpression
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
Expression,
is_expression,
into_expression,
as_expression,
as_expression_mut,
to_expression,
to_expression_mut,
[
BooleanLiteral,
NullLiteral,
NumericLiteral,
BigIntLiteral,
RegExpLiteral,
StringLiteral,
TemplateLiteral,
Identifier,
MetaProperty,
Super,
ArrayExpression,
ArrowFunctionExpression,
AssignmentExpression,
AwaitExpression,
BinaryExpression,
CallExpression,
ChainExpression,
ClassExpression,
ConditionalExpression,
FunctionExpression,
ImportExpression,
LogicalExpression,
NewExpression,
ObjectExpression,
ParenthesizedExpression,
SequenceExpression,
TaggedTemplateExpression,
ThisExpression,
UnaryExpression,
UpdateExpression,
YieldExpression,
PrivateInExpression,
JSXElement,
JSXFragment,
TSAsExpression,
TSSatisfiesExpression,
TSTypeAssertion,
TSNonNullExpression,
TSInstantiationExpression,
V8IntrinsicExpression,
ComputedMemberExpression,
StaticMemberExpression,
PrivateFieldExpression,
]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit MemberExpression
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
ComputedMemberExpression(Box<'a, ComputedMemberExpression<'a>>) = 48,
StaticMemberExpression(Box<'a, StaticMemberExpression<'a>>) = 49,
PrivateFieldExpression(Box<'a, PrivateFieldExpression<'a>>) = 50,
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
MemberExpression,
is_member_expression,
into_member_expression,
as_member_expression,
as_member_expression_mut,
to_member_expression,
to_member_expression_mut,
[ComputedMemberExpression, StaticMemberExpression, PrivateFieldExpression]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit AssignmentTarget
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
@inherit SimpleAssignmentTarget
@inherit AssignmentTargetPattern
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
AssignmentTarget,
is_assignment_target,
into_assignment_target,
as_assignment_target,
as_assignment_target_mut,
to_assignment_target,
to_assignment_target_mut,
[
AssignmentTargetIdentifier,
ComputedMemberExpression,
StaticMemberExpression,
PrivateFieldExpression,
TSAsExpression,
TSSatisfiesExpression,
TSNonNullExpression,
TSTypeAssertion,
ArrayAssignmentTarget,
ObjectAssignmentTarget,
]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit SimpleAssignmentTarget
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
AssignmentTargetIdentifier(Box<'a, IdentifierReference<'a>>) = 0,
TSAsExpression(Box<'a, TSAsExpression<'a>>) = 1,
TSSatisfiesExpression(Box<'a, TSSatisfiesExpression<'a>>) = 2,
TSNonNullExpression(Box<'a, TSNonNullExpression<'a>>) = 3,
TSTypeAssertion(Box<'a, TSTypeAssertion<'a>>) = 4,
@inherit MemberExpression
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
SimpleAssignmentTarget,
is_simple_assignment_target,
into_simple_assignment_target,
as_simple_assignment_target,
as_simple_assignment_target_mut,
to_simple_assignment_target,
to_simple_assignment_target_mut,
[
AssignmentTargetIdentifier,
ComputedMemberExpression,
StaticMemberExpression,
PrivateFieldExpression,
TSAsExpression,
TSSatisfiesExpression,
TSNonNullExpression,
TSTypeAssertion,
]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit AssignmentTargetPattern
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
ArrayAssignmentTarget(Box<'a, ArrayAssignmentTarget<'a>>) = 8,
ObjectAssignmentTarget(Box<'a, ObjectAssignmentTarget<'a>>) = 9,
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
AssignmentTargetPattern,
is_assignment_target_pattern,
into_assignment_target_pattern,
as_assignment_target_pattern,
as_assignment_target_pattern_mut,
to_assignment_target_pattern,
to_assignment_target_pattern_mut,
[ArrayAssignmentTarget, ObjectAssignmentTarget]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit Declaration
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 32,
FunctionDeclaration(Box<'a, Function<'a>>) = 33,
ClassDeclaration(Box<'a, Class<'a>>) = 34,
TSTypeAliasDeclaration(Box<'a, TSTypeAliasDeclaration<'a>>) = 35,
TSInterfaceDeclaration(Box<'a, TSInterfaceDeclaration<'a>>) = 36,
TSEnumDeclaration(Box<'a, TSEnumDeclaration<'a>>) = 37,
TSModuleDeclaration(Box<'a, TSModuleDeclaration<'a>>) = 38,
TSGlobalDeclaration(Box<'a, TSGlobalDeclaration<'a>>) = 39,
TSImportEqualsDeclaration(Box<'a, TSImportEqualsDeclaration<'a>>) = 40,
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
Declaration,
is_declaration,
into_declaration,
as_declaration,
as_declaration_mut,
to_declaration,
to_declaration_mut,
[
VariableDeclaration,
FunctionDeclaration,
ClassDeclaration,
TSTypeAliasDeclaration,
TSInterfaceDeclaration,
TSEnumDeclaration,
TSModuleDeclaration,
TSGlobalDeclaration,
TSImportEqualsDeclaration,
]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit ModuleDeclaration
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
ImportDeclaration(Box<'a, ImportDeclaration<'a>>) = 64,
ExportAllDeclaration(Box<'a, ExportAllDeclaration<'a>>) = 65,
ExportDefaultDeclaration(Box<'a, ExportDefaultDeclaration<'a>>) = 66,
ExportNamedDeclaration(Box<'a, ExportNamedDeclaration<'a>>) = 67,
TSExportAssignment(Box<'a, TSExportAssignment<'a>>) = 68,
TSNamespaceExportDeclaration(Box<'a, TSNamespaceExportDeclaration<'a>>) = 69,
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
ModuleDeclaration,
is_module_declaration,
into_module_declaration,
as_module_declaration,
as_module_declaration_mut,
to_module_declaration,
to_module_declaration_mut,
[
ImportDeclaration,
ExportAllDeclaration,
ExportDefaultDeclaration,
ExportNamedDeclaration,
TSExportAssignment,
TSNamespaceExportDeclaration,
]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit TSType
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
TSAnyKeyword(Box<'a, TSAnyKeyword>) = 0,
TSBigIntKeyword(Box<'a, TSBigIntKeyword>) = 1,
TSBooleanKeyword(Box<'a, TSBooleanKeyword>) = 2,
TSIntrinsicKeyword(Box<'a, TSIntrinsicKeyword>) = 3,
TSNeverKeyword(Box<'a, TSNeverKeyword>) = 4,
TSNullKeyword(Box<'a, TSNullKeyword>) = 5,
TSNumberKeyword(Box<'a, TSNumberKeyword>) = 6,
TSObjectKeyword(Box<'a, TSObjectKeyword>) = 7,
TSStringKeyword(Box<'a, TSStringKeyword>) = 8,
TSSymbolKeyword(Box<'a, TSSymbolKeyword>) = 9,
TSThisType(Box<'a, TSThisType>) = 10,
TSUndefinedKeyword(Box<'a, TSUndefinedKeyword>) = 11,
TSUnknownKeyword(Box<'a, TSUnknownKeyword>) = 12,
TSVoidKeyword(Box<'a, TSVoidKeyword>) = 13,
TSArrayType(Box<'a, TSArrayType<'a>>) = 14,
TSConditionalType(Box<'a, TSConditionalType<'a>>) = 15,
TSConstructorType(Box<'a, TSConstructorType<'a>>) = 16,
TSFunctionType(Box<'a, TSFunctionType<'a>>) = 17,
TSImportType(Box<'a, TSImportType<'a>>) = 18,
TSIndexedAccessType(Box<'a, TSIndexedAccessType<'a>>) = 19,
TSInferType(Box<'a, TSInferType<'a>>) = 20,
TSIntersectionType(Box<'a, TSIntersectionType<'a>>) = 21,
TSLiteralType(Box<'a, TSLiteralType<'a>>) = 22,
TSMappedType(Box<'a, TSMappedType<'a>>) = 23,
TSNamedTupleMember(Box<'a, TSNamedTupleMember<'a>>) = 24,
TSTemplateLiteralType(Box<'a, TSTemplateLiteralType<'a>>) = 26,
TSTupleType(Box<'a, TSTupleType<'a>>) = 27,
TSTypeLiteral(Box<'a, TSTypeLiteral<'a>>) = 28,
TSTypeOperatorType(Box<'a, TSTypeOperator<'a>>) = 29,
TSTypePredicate(Box<'a, TSTypePredicate<'a>>) = 30,
TSTypeQuery(Box<'a, TSTypeQuery<'a>>) = 31,
TSTypeReference(Box<'a, TSTypeReference<'a>>) = 32,
TSUnionType(Box<'a, TSUnionType<'a>>) = 33,
TSParenthesizedType(Box<'a, TSParenthesizedType<'a>>) = 34,
JSDocNullableType(Box<'a, JSDocNullableType<'a>>) = 35,
JSDocNonNullableType(Box<'a, JSDocNonNullableType<'a>>) = 36,
JSDocUnknownType(Box<'a, JSDocUnknownType>) = 37,
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
TSType,
is_ts_type,
into_ts_type,
as_ts_type,
as_ts_type_mut,
to_ts_type,
to_ts_type_mut,
[
TSAnyKeyword,
TSBigIntKeyword,
TSBooleanKeyword,
TSIntrinsicKeyword,
TSNeverKeyword,
TSNullKeyword,
TSNumberKeyword,
TSObjectKeyword,
TSStringKeyword,
TSSymbolKeyword,
TSThisType,
TSUndefinedKeyword,
TSUnknownKeyword,
TSVoidKeyword,
TSArrayType,
TSConditionalType,
TSConstructorType,
TSFunctionType,
TSImportType,
TSIndexedAccessType,
TSInferType,
TSIntersectionType,
TSLiteralType,
TSMappedType,
TSNamedTupleMember,
TSTemplateLiteralType,
TSTupleType,
TSTypeLiteral,
TSTypeOperatorType,
TSTypePredicate,
TSTypeQuery,
TSTypeReference,
TSUnionType,
TSParenthesizedType,
JSDocNullableType,
JSDocNonNullableType,
JSDocUnknownType,
]
);
};
(
$(#[$attr:meta])*
pub enum $ty:ident<'a> {
$($(#[$variant_attr:meta])* $variant_name:ident($variant_type:ty) = $variant_discrim:literal,)*
@inherit TSTypeName
$($rest:tt)*
}
) => {
$crate::ast::macros::inherit_variants! {
$(#[$attr])*
pub enum $ty<'a> {
$($(#[$variant_attr])* $variant_name($variant_type) = $variant_discrim,)*
IdentifierReference(Box<'a, IdentifierReference<'a>>) = 0,
QualifiedName(Box<'a, TSQualifiedName<'a>>) = 1,
ThisExpression(Box<'a, ThisExpression>) = 2,
$($rest)*
}
}
$crate::ast::macros::shared_enum_variants!(
$ty,
TSTypeName,
is_ts_type_name,
into_ts_type_name,
as_ts_type_name,
as_ts_type_name_mut,
to_ts_type_name,
to_ts_type_name_mut,
[IdentifierReference, QualifiedName, ThisExpression]
);
};
($($rest:tt)*) => {$($rest)*};
}
pub(crate) use inherit_variants;
macro_rules! shared_enum_variants {
(
$parent:ident, $child:ident,
$is_child:ident,
$into_child:ident,
$as_child:ident, $as_child_mut:ident,
$to_child:ident, $to_child_mut:ident,
[$($variant:ident),+ $(,)?]
) => {
const _: () = {
$(
assert!(
$crate::ast::macros::discriminant!($parent::$variant)
== $crate::ast::macros::discriminant!($child::$variant),
concat!(
"Non-matching discriminants for `", stringify!($variant),
"` between `", stringify!($parent), "` and `", stringify!($child), "`"
)
);
)+
};
impl<'a> $parent<'a> {
#[doc = concat!("Return if a `", stringify!($parent), "` is a `", stringify!($child), "`.")]
#[inline]
pub fn $is_child(&self) -> bool {
matches!(
self,
$(Self::$variant(_))|+
)
}
#[doc = concat!("Convert `", stringify!($parent), "` to `", stringify!($child), "`.")]
#[doc = "# Panic"]
#[doc = "Panics if not convertible."]
#[inline]
pub fn $into_child(self) -> $child<'a> {
$child::try_from(self).unwrap()
}
#[doc = concat!("Convert `&", stringify!($parent), "` to `&", stringify!($child), "`.")]
#[inline]
pub fn $as_child(&self) -> Option<&$child<'a>> {
if self.$is_child() {
Some(unsafe { &*std::ptr::from_ref(self).cast::<$child>() })
} else {
None
}
}
#[doc = concat!("Convert `&mut ", stringify!($parent), "` to `&mut ", stringify!($child), "`.")]
#[inline]
pub fn $as_child_mut(&mut self) -> Option<&mut $child<'a>> {
if self.$is_child() {
Some(unsafe { &mut *std::ptr::from_mut(self).cast::<$child>() })
} else {
None
}
}
#[doc = concat!("Convert `&", stringify!($parent), "` to `&", stringify!($child), "`.")]
#[doc = "# Panic"]
#[doc = "Panics if not convertible."]
#[inline]
pub fn $to_child(&self) -> &$child<'a> {
self.$as_child().unwrap()
}
#[doc = concat!("Convert `&mut ", stringify!($parent), "` to `&mut ", stringify!($child), "`.")]
#[doc = "# Panic"]
#[doc = "Panics if not convertible."]
#[inline]
pub fn $to_child_mut(&mut self) -> &mut $child<'a> {
self.$as_child_mut().unwrap()
}
}
impl<'a> TryFrom<$parent<'a>> for $child<'a> {
type Error = ();
#[doc = concat!("Convert `", stringify!($parent), "` to `", stringify!($child), "`.")]
#[inline]
fn try_from(value: $parent<'a>) -> Result<Self, Self::Error> {
match value {
$($parent::$variant(o) => Ok($child::$variant(o)),)+
_ => Err(())
}
}
}
impl<'a> From<$child<'a>> for $parent<'a> {
#[doc = concat!("Convert `", stringify!($child), "` to `", stringify!($parent), "`.")]
#[inline]
fn from(value: $child<'a>) -> Self {
match value {
$($child::$variant(o) => $parent::$variant(o),)+
}
}
}
}
}
pub(crate) use shared_enum_variants;
macro_rules! discriminant {
($ty:ident :: $variant:ident) => {{
#[expect(clippy::undocumented_unsafe_blocks)]
unsafe {
let t = std::mem::ManuallyDrop::new($ty::$variant(oxc_allocator::Box::dangling()));
*(std::ptr::addr_of!(t).cast::<u8>())
}
}};
}
pub(crate) use discriminant;