diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 1d4f95314dbce..99cbfdec5ea3c 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1344,6 +1344,7 @@ pub struct BindingPattern<'a> { feature = "serialize", tsify(type = "(BindingIdentifier | ObjectPattern | ArrayPattern | AssignmentPattern)") )] + #[span] pub kind: BindingPatternKind<'a>, pub type_annotation: Option>>, pub optional: bool, diff --git a/crates/oxc_ast/src/generated/span.rs b/crates/oxc_ast/src/generated/span.rs index 8bcf4ffe4d468..cdbe455736662 100644 --- a/crates/oxc_ast/src/generated/span.rs +++ b/crates/oxc_ast/src/generated/span.rs @@ -925,6 +925,13 @@ impl GetSpan for DebuggerStatement { } } +impl<'a> GetSpan for BindingPattern<'a> { + #[inline] + fn span(&self) -> Span { + self.kind.span() + } +} + impl<'a> GetSpan for BindingPatternKind<'a> { fn span(&self) -> Span { match self { @@ -2185,9 +2192,3 @@ impl<'a> GetSpan for JSXText<'a> { self.span } } - -impl<'a> GetSpan for BindingPattern<'a> { - fn span(&self) -> Span { - self.kind.span() - } -} diff --git a/crates/oxc_ast_macros/src/lib.rs b/crates/oxc_ast_macros/src/lib.rs index 5f4f54d1be27f..5b3dae9d0496f 100644 --- a/crates/oxc_ast_macros/src/lib.rs +++ b/crates/oxc_ast_macros/src/lib.rs @@ -22,7 +22,7 @@ pub fn visited_node(_args: TokenStream, input: TokenStream) -> TokenStream { /// Dummy derive macro for a non-existent trait `VisitedNode`. /// /// Does not generate any code, only purpose is to allow using `#[scope]` attr in the type def. -#[proc_macro_derive(VisitedNode, attributes(scope, visit, visit_as, visit_args))] +#[proc_macro_derive(VisitedNode, attributes(span, scope, visit, visit_as, visit_args))] pub fn visited_node_derive(_item: TokenStream) -> TokenStream { TokenStream::new() } diff --git a/tasks/ast_codegen/src/generators/impl_get_span.rs b/tasks/ast_codegen/src/generators/impl_get_span.rs index 312f9020ac9a7..adf83229cf47e 100644 --- a/tasks/ast_codegen/src/generators/impl_get_span.rs +++ b/tasks/ast_codegen/src/generators/impl_get_span.rs @@ -15,23 +15,6 @@ use super::generated_header; pub struct ImplGetSpanGenerator; -const EDGE_CASES: [&str; 1] = ["BindingPattern"]; - -fn edge_case(it: &std::cell::Ref) -> bool { - !it.ident().is_some_and(|it| EDGE_CASES.contains(&it.to_string().as_str())) -} - -fn edge_case_impls() -> TokenStream { - quote! { - endl!(); - impl<'a> GetSpan for BindingPattern<'a> { - fn span(&self) -> Span { - self.kind.span() - } - } - } -} - impl Generator for ImplGetSpanGenerator { fn name(&self) -> &'static str { "ImplGetSpanGenerator" @@ -44,7 +27,6 @@ impl Generator for ImplGetSpanGenerator { .map(|it| it.borrow()) .filter(|it| it.visitable()) .filter(|it| matches!(&**it, RType::Enum(_) | RType::Struct(_))) - .filter(edge_case) .map(|kind| match &*kind { RType::Enum(it) => impl_enum(it), RType::Struct(it) => impl_struct(it), @@ -52,8 +34,6 @@ impl Generator for ImplGetSpanGenerator { }) .collect(); - let edge_impls = edge_case_impls(); - let header = generated_header!(); GeneratorOutput::One(quote! { @@ -65,9 +45,6 @@ impl Generator for ImplGetSpanGenerator { use oxc_span::{GetSpan, Span}; #(#impls)* - - #edge_impls - }) } } @@ -96,12 +73,20 @@ fn impl_enum(it @ REnum { item, .. }: &REnum) -> TokenStream { fn impl_struct(it @ RStruct { item, .. }: &RStruct) -> TokenStream { let typ = it.as_type(); let generics = &item.generics; + let inner_span_hint = + item.fields.iter().find(|it| it.attrs.iter().any(|a| a.path().is_ident("span"))); + let span = if let Some(span_field) = inner_span_hint { + let ident = span_field.ident.as_ref().unwrap(); + quote!(#ident.span()) + } else { + quote!(span) + }; quote! { endl!(); impl #generics GetSpan for #typ { #[inline] fn span(&self) -> Span { - self.span + self.#span } } }