feat(ast_codegen): introduce the #[span] hint. (#4012)

closes #3904
This commit is contained in:
rzvxa 2024-07-02 10:18:58 +00:00
parent 71e9286fa6
commit 1854a52bd7
4 changed files with 18 additions and 31 deletions

View file

@ -1344,6 +1344,7 @@ pub struct BindingPattern<'a> {
feature = "serialize", feature = "serialize",
tsify(type = "(BindingIdentifier | ObjectPattern | ArrayPattern | AssignmentPattern)") tsify(type = "(BindingIdentifier | ObjectPattern | ArrayPattern | AssignmentPattern)")
)] )]
#[span]
pub kind: BindingPatternKind<'a>, pub kind: BindingPatternKind<'a>,
pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>, pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>,
pub optional: bool, pub optional: bool,

View file

@ -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> { impl<'a> GetSpan for BindingPatternKind<'a> {
fn span(&self) -> Span { fn span(&self) -> Span {
match self { match self {
@ -2185,9 +2192,3 @@ impl<'a> GetSpan for JSXText<'a> {
self.span self.span
} }
} }
impl<'a> GetSpan for BindingPattern<'a> {
fn span(&self) -> Span {
self.kind.span()
}
}

View file

@ -22,7 +22,7 @@ pub fn visited_node(_args: TokenStream, input: TokenStream) -> TokenStream {
/// Dummy derive macro for a non-existent trait `VisitedNode`. /// 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. /// 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 { pub fn visited_node_derive(_item: TokenStream) -> TokenStream {
TokenStream::new() TokenStream::new()
} }

View file

@ -15,23 +15,6 @@ use super::generated_header;
pub struct ImplGetSpanGenerator; pub struct ImplGetSpanGenerator;
const EDGE_CASES: [&str; 1] = ["BindingPattern"];
fn edge_case(it: &std::cell::Ref<RType>) -> 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 { impl Generator for ImplGetSpanGenerator {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"ImplGetSpanGenerator" "ImplGetSpanGenerator"
@ -44,7 +27,6 @@ impl Generator for ImplGetSpanGenerator {
.map(|it| it.borrow()) .map(|it| it.borrow())
.filter(|it| it.visitable()) .filter(|it| it.visitable())
.filter(|it| matches!(&**it, RType::Enum(_) | RType::Struct(_))) .filter(|it| matches!(&**it, RType::Enum(_) | RType::Struct(_)))
.filter(edge_case)
.map(|kind| match &*kind { .map(|kind| match &*kind {
RType::Enum(it) => impl_enum(it), RType::Enum(it) => impl_enum(it),
RType::Struct(it) => impl_struct(it), RType::Struct(it) => impl_struct(it),
@ -52,8 +34,6 @@ impl Generator for ImplGetSpanGenerator {
}) })
.collect(); .collect();
let edge_impls = edge_case_impls();
let header = generated_header!(); let header = generated_header!();
GeneratorOutput::One(quote! { GeneratorOutput::One(quote! {
@ -65,9 +45,6 @@ impl Generator for ImplGetSpanGenerator {
use oxc_span::{GetSpan, Span}; use oxc_span::{GetSpan, Span};
#(#impls)* #(#impls)*
#edge_impls
}) })
} }
} }
@ -96,12 +73,20 @@ fn impl_enum(it @ REnum { item, .. }: &REnum) -> TokenStream {
fn impl_struct(it @ RStruct { item, .. }: &RStruct) -> TokenStream { fn impl_struct(it @ RStruct { item, .. }: &RStruct) -> TokenStream {
let typ = it.as_type(); let typ = it.as_type();
let generics = &item.generics; 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! { quote! {
endl!(); endl!();
impl #generics GetSpan for #typ { impl #generics GetSpan for #typ {
#[inline] #[inline]
fn span(&self) -> Span { fn span(&self) -> Span {
self.span self.#span
} }
} }
} }