diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 19f085a001d13..8f3917356875c 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -433,18 +433,21 @@ pub struct TemplateLiteral<'a> { pub expressions: Vec<'a, Expression<'a>>, } -/// `` foo`Hello, ${name}` `` in `` const foo = foo`Hello, ${name}` `` +/// `` tag`Hello, ${name}` `` in `` const foo = tag`Hello, ${name}`; ``. /// -/// Represents a tagged template expression, which can include a tag and a quasi. +/// Or with TS type arguments: +/// ```ts +/// const foo = tag`Hello, ${name}`; +/// ``` #[ast(visit)] #[derive(Debug)] #[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)] pub struct TaggedTemplateExpression<'a> { pub span: Span, pub tag: Expression<'a>, - pub quasi: TemplateLiteral<'a>, #[ts] pub type_arguments: Option>>, + pub quasi: TemplateLiteral<'a>, } /// `Hello, ` in `` `Hello, ${name}` `` diff --git a/crates/oxc_ast/src/generated/assert_layouts.rs b/crates/oxc_ast/src/generated/assert_layouts.rs index 697dfd9f2434a..b2fcb14677db9 100644 --- a/crates/oxc_ast/src/generated/assert_layouts.rs +++ b/crates/oxc_ast/src/generated/assert_layouts.rs @@ -95,8 +95,8 @@ const _: () = { assert!(align_of::() == 8); assert!(offset_of!(TaggedTemplateExpression, span) == 0); assert!(offset_of!(TaggedTemplateExpression, tag) == 8); - assert!(offset_of!(TaggedTemplateExpression, quasi) == 24); - assert!(offset_of!(TaggedTemplateExpression, type_arguments) == 96); + assert!(offset_of!(TaggedTemplateExpression, type_arguments) == 24); + assert!(offset_of!(TaggedTemplateExpression, quasi) == 32); assert!(size_of::() == 48); assert!(align_of::() == 8); @@ -1490,8 +1490,8 @@ const _: () = { assert!(align_of::() == 4); assert!(offset_of!(TaggedTemplateExpression, span) == 0); assert!(offset_of!(TaggedTemplateExpression, tag) == 8); - assert!(offset_of!(TaggedTemplateExpression, quasi) == 16); - assert!(offset_of!(TaggedTemplateExpression, type_arguments) == 56); + assert!(offset_of!(TaggedTemplateExpression, type_arguments) == 16); + assert!(offset_of!(TaggedTemplateExpression, quasi) == 20); assert!(size_of::() == 28); assert!(align_of::() == 4); diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index 089ed62c4d3ce..8e6a10dba3867 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -934,15 +934,15 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `tag` - /// * `quasi` /// * `type_arguments` + /// * `quasi` #[inline] pub fn expression_tagged_template( self, span: Span, tag: Expression<'a>, - quasi: TemplateLiteral<'a>, type_arguments: T1, + quasi: TemplateLiteral<'a>, ) -> Expression<'a> where T1: IntoIn<'a, Option>>>, @@ -950,8 +950,8 @@ impl<'a> AstBuilder<'a> { Expression::TaggedTemplateExpression(self.alloc_tagged_template_expression( span, tag, - quasi, type_arguments, + quasi, )) } @@ -1720,15 +1720,15 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `tag` - /// * `quasi` /// * `type_arguments` + /// * `quasi` #[inline] pub fn tagged_template_expression( self, span: Span, tag: Expression<'a>, - quasi: TemplateLiteral<'a>, type_arguments: T1, + quasi: TemplateLiteral<'a>, ) -> TaggedTemplateExpression<'a> where T1: IntoIn<'a, Option>>>, @@ -1736,8 +1736,8 @@ impl<'a> AstBuilder<'a> { TaggedTemplateExpression { span, tag, - quasi, type_arguments: type_arguments.into_in(self.allocator), + quasi, } } @@ -1749,21 +1749,21 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `tag` - /// * `quasi` /// * `type_arguments` + /// * `quasi` #[inline] pub fn alloc_tagged_template_expression( self, span: Span, tag: Expression<'a>, - quasi: TemplateLiteral<'a>, type_arguments: T1, + quasi: TemplateLiteral<'a>, ) -> Box<'a, TaggedTemplateExpression<'a>> where T1: IntoIn<'a, Option>>>, { Box::new_in( - self.tagged_template_expression(span, tag, quasi, type_arguments), + self.tagged_template_expression(span, tag, type_arguments, quasi), self.allocator, ) } diff --git a/crates/oxc_ast/src/generated/derive_clone_in.rs b/crates/oxc_ast/src/generated/derive_clone_in.rs index d577483f42702..5bfdbd7890d7c 100644 --- a/crates/oxc_ast/src/generated/derive_clone_in.rs +++ b/crates/oxc_ast/src/generated/derive_clone_in.rs @@ -1070,8 +1070,8 @@ impl<'new_alloc> CloneIn<'new_alloc> for TaggedTemplateExpression<'_> { TaggedTemplateExpression { span: CloneIn::clone_in(&self.span, allocator), tag: CloneIn::clone_in(&self.tag, allocator), - quasi: CloneIn::clone_in(&self.quasi, allocator), type_arguments: CloneIn::clone_in(&self.type_arguments, allocator), + quasi: CloneIn::clone_in(&self.quasi, allocator), } } @@ -1079,8 +1079,8 @@ impl<'new_alloc> CloneIn<'new_alloc> for TaggedTemplateExpression<'_> { TaggedTemplateExpression { span: CloneIn::clone_in_with_semantic_ids(&self.span, allocator), tag: CloneIn::clone_in_with_semantic_ids(&self.tag, allocator), - quasi: CloneIn::clone_in_with_semantic_ids(&self.quasi, allocator), type_arguments: CloneIn::clone_in_with_semantic_ids(&self.type_arguments, allocator), + quasi: CloneIn::clone_in_with_semantic_ids(&self.quasi, allocator), } } } diff --git a/crates/oxc_ast/src/generated/derive_content_eq.rs b/crates/oxc_ast/src/generated/derive_content_eq.rs index c5878f5c6f84d..3f4c59803bfa4 100644 --- a/crates/oxc_ast/src/generated/derive_content_eq.rs +++ b/crates/oxc_ast/src/generated/derive_content_eq.rs @@ -282,8 +282,8 @@ impl ContentEq for TemplateLiteral<'_> { impl ContentEq for TaggedTemplateExpression<'_> { fn content_eq(&self, other: &Self) -> bool { ContentEq::content_eq(&self.tag, &other.tag) - && ContentEq::content_eq(&self.quasi, &other.quasi) && ContentEq::content_eq(&self.type_arguments, &other.type_arguments) + && ContentEq::content_eq(&self.quasi, &other.quasi) } } diff --git a/crates/oxc_ast/src/generated/derive_dummy.rs b/crates/oxc_ast/src/generated/derive_dummy.rs index 12b32852045c0..33facf19a3dd7 100644 --- a/crates/oxc_ast/src/generated/derive_dummy.rs +++ b/crates/oxc_ast/src/generated/derive_dummy.rs @@ -192,8 +192,8 @@ impl<'a> Dummy<'a> for TaggedTemplateExpression<'a> { Self { span: Dummy::dummy(allocator), tag: Dummy::dummy(allocator), - quasi: Dummy::dummy(allocator), type_arguments: Dummy::dummy(allocator), + quasi: Dummy::dummy(allocator), } } } diff --git a/crates/oxc_ast_visit/src/generated/visit.rs b/crates/oxc_ast_visit/src/generated/visit.rs index 6db5dae046738..40d3d2fbc9c3b 100644 --- a/crates/oxc_ast_visit/src/generated/visit.rs +++ b/crates/oxc_ast_visit/src/generated/visit.rs @@ -1554,10 +1554,10 @@ pub mod walk { visitor.enter_node(kind); visitor.visit_span(&it.span); visitor.visit_expression(&it.tag); - visitor.visit_template_literal(&it.quasi); if let Some(type_arguments) = &it.type_arguments { visitor.visit_ts_type_parameter_instantiation(type_arguments); } + visitor.visit_template_literal(&it.quasi); visitor.leave_node(kind); } diff --git a/crates/oxc_ast_visit/src/generated/visit_mut.rs b/crates/oxc_ast_visit/src/generated/visit_mut.rs index 5d7d80867d62d..8efd49b58bfa9 100644 --- a/crates/oxc_ast_visit/src/generated/visit_mut.rs +++ b/crates/oxc_ast_visit/src/generated/visit_mut.rs @@ -1564,10 +1564,10 @@ pub mod walk_mut { visitor.enter_node(kind); visitor.visit_span(&mut it.span); visitor.visit_expression(&mut it.tag); - visitor.visit_template_literal(&mut it.quasi); if let Some(type_arguments) = &mut it.type_arguments { visitor.visit_ts_type_parameter_instantiation(type_arguments); } + visitor.visit_template_literal(&mut it.quasi); visitor.leave_node(kind); } diff --git a/crates/oxc_parser/src/js/expression.rs b/crates/oxc_parser/src/js/expression.rs index 26df454c71dae..e927f9515a93a 100644 --- a/crates/oxc_parser/src/js/expression.rs +++ b/crates/oxc_parser/src/js/expression.rs @@ -513,7 +513,7 @@ impl<'a> ParserImpl<'a> { span: u32, lhs: Expression<'a>, in_optional_chain: bool, - type_parameters: Option>>, + type_arguments: Option>>, ) -> Expression<'a> { let quasi = self.parse_template_literal(true); let span = self.end_span(span); @@ -525,7 +525,7 @@ impl<'a> ParserImpl<'a> { if in_optional_chain { self.error(diagnostics::optional_chain_tagged_template(quasi.span)); } - self.ast.expression_tagged_template(span, lhs, quasi, type_parameters) + self.ast.expression_tagged_template(span, lhs, type_arguments, quasi) } pub(crate) fn parse_template_element(&mut self, tagged: bool) -> TemplateElement<'a> { @@ -761,7 +761,7 @@ impl<'a> ParserImpl<'a> { } if self.cur_kind().is_template_start_of_tagged_template() { - let (expr, type_parameters) = + let (expr, type_arguments) = if let Expression::TSInstantiationExpression(instantiation_expr) = lhs { let expr = instantiation_expr.unbox(); (expr.expression, Some(expr.type_arguments)) @@ -769,7 +769,7 @@ impl<'a> ParserImpl<'a> { (lhs, None) }; lhs = - self.parse_tagged_template(lhs_span, expr, *in_optional_chain, type_parameters); + self.parse_tagged_template(lhs_span, expr, *in_optional_chain, type_arguments); continue; } diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/type-parameters/tagged-template.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/type-parameters/tagged-template.snap index dbd75f4af1066..377b94eaf6b15 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/type-parameters/tagged-template.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/type-parameters/tagged-template.snap @@ -49,7 +49,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "flags": "ReferenceFlags(Type)", "id": 1, "name": "StyledPaymentProps", - "node_id": 31 + "node_id": 30 } ] }, diff --git a/crates/oxc_traverse/src/generated/ancestor.rs b/crates/oxc_traverse/src/generated/ancestor.rs index e92774dd3d496..e0cd80b55dc6b 100644 --- a/crates/oxc_traverse/src/generated/ancestor.rs +++ b/crates/oxc_traverse/src/generated/ancestor.rs @@ -31,8 +31,8 @@ pub(crate) enum AncestorType { TemplateLiteralQuasis = 8, TemplateLiteralExpressions = 9, TaggedTemplateExpressionTag = 10, - TaggedTemplateExpressionQuasi = 11, - TaggedTemplateExpressionTypeArguments = 12, + TaggedTemplateExpressionTypeArguments = 11, + TaggedTemplateExpressionQuasi = 12, ComputedMemberExpressionObject = 13, ComputedMemberExpressionExpression = 14, StaticMemberExpressionObject = 15, @@ -355,10 +355,10 @@ pub enum Ancestor<'a, 't> { AncestorType::TemplateLiteralExpressions as u16, TaggedTemplateExpressionTag(TaggedTemplateExpressionWithoutTag<'a, 't>) = AncestorType::TaggedTemplateExpressionTag as u16, - TaggedTemplateExpressionQuasi(TaggedTemplateExpressionWithoutQuasi<'a, 't>) = - AncestorType::TaggedTemplateExpressionQuasi as u16, TaggedTemplateExpressionTypeArguments(TaggedTemplateExpressionWithoutTypeArguments<'a, 't>) = AncestorType::TaggedTemplateExpressionTypeArguments as u16, + TaggedTemplateExpressionQuasi(TaggedTemplateExpressionWithoutQuasi<'a, 't>) = + AncestorType::TaggedTemplateExpressionQuasi as u16, ComputedMemberExpressionObject(ComputedMemberExpressionWithoutObject<'a, 't>) = AncestorType::ComputedMemberExpressionObject as u16, ComputedMemberExpressionExpression(ComputedMemberExpressionWithoutExpression<'a, 't>) = @@ -919,8 +919,8 @@ impl<'a, 't> Ancestor<'a, 't> { matches!( self, Self::TaggedTemplateExpressionTag(_) - | Self::TaggedTemplateExpressionQuasi(_) | Self::TaggedTemplateExpressionTypeArguments(_) + | Self::TaggedTemplateExpressionQuasi(_) ) } @@ -2208,8 +2208,8 @@ impl<'a, 't> GetAddress for Ancestor<'a, 't> { Self::TemplateLiteralQuasis(a) => a.address(), Self::TemplateLiteralExpressions(a) => a.address(), Self::TaggedTemplateExpressionTag(a) => a.address(), - Self::TaggedTemplateExpressionQuasi(a) => a.address(), Self::TaggedTemplateExpressionTypeArguments(a) => a.address(), + Self::TaggedTemplateExpressionQuasi(a) => a.address(), Self::ComputedMemberExpressionObject(a) => a.address(), Self::ComputedMemberExpressionExpression(a) => a.address(), Self::StaticMemberExpressionObject(a) => a.address(), @@ -2898,10 +2898,10 @@ pub(crate) const OFFSET_TAGGED_TEMPLATE_EXPRESSION_SPAN: usize = offset_of!(TaggedTemplateExpression, span); pub(crate) const OFFSET_TAGGED_TEMPLATE_EXPRESSION_TAG: usize = offset_of!(TaggedTemplateExpression, tag); -pub(crate) const OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI: usize = - offset_of!(TaggedTemplateExpression, quasi); pub(crate) const OFFSET_TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS: usize = offset_of!(TaggedTemplateExpression, type_arguments); +pub(crate) const OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI: usize = + offset_of!(TaggedTemplateExpression, quasi); #[repr(transparent)] #[derive(Clone, Copy, Debug)] @@ -2919,18 +2919,18 @@ impl<'a, 't> TaggedTemplateExpressionWithoutTag<'a, 't> { } #[inline] - pub fn quasi(self) -> &'t TemplateLiteral<'a> { + pub fn type_arguments(self) -> &'t Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI) - as *const TemplateLiteral<'a>) + &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS) + as *const Option>>) } } #[inline] - pub fn type_arguments(self) -> &'t Option>> { + pub fn quasi(self) -> &'t TemplateLiteral<'a> { unsafe { - &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI) + as *const TemplateLiteral<'a>) } } } @@ -2944,12 +2944,12 @@ impl<'a, 't> GetAddress for TaggedTemplateExpressionWithoutTag<'a, 't> { #[repr(transparent)] #[derive(Clone, Copy, Debug)] -pub struct TaggedTemplateExpressionWithoutQuasi<'a, 't>( +pub struct TaggedTemplateExpressionWithoutTypeArguments<'a, 't>( pub(crate) *const TaggedTemplateExpression<'a>, pub(crate) PhantomData<&'t ()>, ); -impl<'a, 't> TaggedTemplateExpressionWithoutQuasi<'a, 't> { +impl<'a, 't> TaggedTemplateExpressionWithoutTypeArguments<'a, 't> { #[inline] pub fn span(self) -> &'t Span { unsafe { @@ -2966,15 +2966,15 @@ impl<'a, 't> TaggedTemplateExpressionWithoutQuasi<'a, 't> { } #[inline] - pub fn type_arguments(self) -> &'t Option>> { + pub fn quasi(self) -> &'t TemplateLiteral<'a> { unsafe { - &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI) + as *const TemplateLiteral<'a>) } } } -impl<'a, 't> GetAddress for TaggedTemplateExpressionWithoutQuasi<'a, 't> { +impl<'a, 't> GetAddress for TaggedTemplateExpressionWithoutTypeArguments<'a, 't> { #[inline] fn address(&self) -> Address { Address::from_ptr(self.0) @@ -2983,12 +2983,12 @@ impl<'a, 't> GetAddress for TaggedTemplateExpressionWithoutQuasi<'a, 't> { #[repr(transparent)] #[derive(Clone, Copy, Debug)] -pub struct TaggedTemplateExpressionWithoutTypeArguments<'a, 't>( +pub struct TaggedTemplateExpressionWithoutQuasi<'a, 't>( pub(crate) *const TaggedTemplateExpression<'a>, pub(crate) PhantomData<&'t ()>, ); -impl<'a, 't> TaggedTemplateExpressionWithoutTypeArguments<'a, 't> { +impl<'a, 't> TaggedTemplateExpressionWithoutQuasi<'a, 't> { #[inline] pub fn span(self) -> &'t Span { unsafe { @@ -3005,15 +3005,15 @@ impl<'a, 't> TaggedTemplateExpressionWithoutTypeArguments<'a, 't> { } #[inline] - pub fn quasi(self) -> &'t TemplateLiteral<'a> { + pub fn type_arguments(self) -> &'t Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI) - as *const TemplateLiteral<'a>) + &*((self.0 as *const u8).add(OFFSET_TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS) + as *const Option>>) } } } -impl<'a, 't> GetAddress for TaggedTemplateExpressionWithoutTypeArguments<'a, 't> { +impl<'a, 't> GetAddress for TaggedTemplateExpressionWithoutQuasi<'a, 't> { #[inline] fn address(&self) -> Address { Address::from_ptr(self.0) diff --git a/crates/oxc_traverse/src/generated/scopes_collector.rs b/crates/oxc_traverse/src/generated/scopes_collector.rs index 2dd934237d162..a639c073673ba 100644 --- a/crates/oxc_traverse/src/generated/scopes_collector.rs +++ b/crates/oxc_traverse/src/generated/scopes_collector.rs @@ -285,10 +285,10 @@ impl<'a> Visit<'a> for ChildScopeCollector { #[inline] fn visit_tagged_template_expression(&mut self, it: &TaggedTemplateExpression<'a>) { self.visit_expression(&it.tag); - self.visit_template_literal(&it.quasi); if let Some(type_arguments) = &it.type_arguments { self.visit_ts_type_parameter_instantiation(type_arguments); } + self.visit_template_literal(&it.quasi); } #[inline(always)] diff --git a/crates/oxc_traverse/src/generated/walk.rs b/crates/oxc_traverse/src/generated/walk.rs index 27313596fdfe7..a08ac36a45a13 100644 --- a/crates/oxc_traverse/src/generated/walk.rs +++ b/crates/oxc_traverse/src/generated/walk.rs @@ -495,13 +495,6 @@ unsafe fn walk_tagged_template_expression<'a, Tr: Traverse<'a>>( (node as *mut u8).add(ancestor::OFFSET_TAGGED_TEMPLATE_EXPRESSION_TAG) as *mut Expression, ctx, ); - ctx.retag_stack(AncestorType::TaggedTemplateExpressionQuasi); - walk_template_literal( - traverser, - (node as *mut u8).add(ancestor::OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI) - as *mut TemplateLiteral, - ctx, - ); if let Some(field) = &mut *((node as *mut u8) .add(ancestor::OFFSET_TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS) as *mut Option>) @@ -509,6 +502,13 @@ unsafe fn walk_tagged_template_expression<'a, Tr: Traverse<'a>>( ctx.retag_stack(AncestorType::TaggedTemplateExpressionTypeArguments); walk_ts_type_parameter_instantiation(traverser, (&mut **field) as *mut _, ctx); } + ctx.retag_stack(AncestorType::TaggedTemplateExpressionQuasi); + walk_template_literal( + traverser, + (node as *mut u8).add(ancestor::OFFSET_TAGGED_TEMPLATE_EXPRESSION_QUASI) + as *mut TemplateLiteral, + ctx, + ); ctx.pop_stack(pop_token); traverser.exit_tagged_template_expression(&mut *node, ctx); } diff --git a/napi/parser/generated/deserialize/js.js b/napi/parser/generated/deserialize/js.js index 259b916ebd929..232d79e844cc6 100644 --- a/napi/parser/generated/deserialize/js.js +++ b/napi/parser/generated/deserialize/js.js @@ -148,7 +148,7 @@ function deserializeTaggedTemplateExpression(pos) { start: deserializeU32(pos), end: deserializeU32(pos + 4), tag: deserializeExpression(pos + 8), - quasi: deserializeTemplateLiteral(pos + 24), + quasi: deserializeTemplateLiteral(pos + 32), }; } diff --git a/napi/parser/generated/deserialize/ts.js b/napi/parser/generated/deserialize/ts.js index f3b77e6413650..ab4f3954abeb5 100644 --- a/napi/parser/generated/deserialize/ts.js +++ b/napi/parser/generated/deserialize/ts.js @@ -177,8 +177,8 @@ function deserializeTaggedTemplateExpression(pos) { start: deserializeU32(pos), end: deserializeU32(pos + 4), tag: deserializeExpression(pos + 8), - quasi: deserializeTemplateLiteral(pos + 24), - typeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 96), + quasi: deserializeTemplateLiteral(pos + 32), + typeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 24), }; }