feat(ast): GetSpanMut trait (#4609)

Closes #4606.

Introduce `GetSpanMut` trait and implement it on all AST node types.

This has to be a separate trait, rather than adding `span_mut` method to `GetSpan` because `AstKind` implements `GetSpan`, and it only has an immutable `&` ref to AST node it contains.
This commit is contained in:
overlookmotel 2024-08-02 11:50:24 +00:00
parent f259df0d62
commit 54047e021c
4 changed files with 2231 additions and 11 deletions

File diff suppressed because it is too large Load diff

View file

@ -9,5 +9,5 @@ mod span;
pub use crate::{
atom::{Atom, CompactStr, MAX_INLINE_LEN as ATOM_MAX_INLINE_LEN},
source_type::{Language, LanguageVariant, ModuleKind, SourceType, VALID_EXTENSIONS},
span::{GetSpan, Span, SPAN},
span::{GetSpan, GetSpanMut, Span, SPAN},
};

View file

@ -352,12 +352,26 @@ impl From<Span> for LabeledSpan {
pub trait GetSpan {
fn span(&self) -> Span;
}
/// Get mutable ref to span for an AST node
pub trait GetSpanMut {
fn span_mut(&mut self) -> &mut Span;
}
impl GetSpan for Span {
#[inline]
fn span(&self) -> Span {
*self
}
}
impl GetSpanMut for Span {
#[inline]
fn span_mut(&mut self) -> &mut Span {
self
}
}
#[cfg(test)]
mod test {
use super::Span;

View file

@ -1,4 +1,3 @@
use itertools::Itertools;
use proc_macro2::TokenStream;
use quote::quote;
use syn::Variant;
@ -44,7 +43,7 @@ impl Generator for ImplGetSpanGenerator {
endl!();
use crate::ast::*;
use oxc_span::{GetSpan, Span};
use oxc_span::{GetSpan, GetSpanMut, Span};
#(#impls)*
},
@ -55,11 +54,13 @@ impl Generator for ImplGetSpanGenerator {
fn impl_enum(it @ REnum { item, .. }: &REnum) -> TokenStream {
let typ = it.as_type();
let generics = &item.generics;
let matches: Vec<TokenStream> = item
let (matches, matches_mut): (Vec<TokenStream>, Vec<TokenStream>) = item
.variants
.iter()
.map(|Variant { ident, .. }| quote!(Self :: #ident(it) => it.span()))
.collect_vec();
.map(|Variant { ident, .. }| {
(quote!(Self :: #ident(it) => it.span()), quote!(Self :: #ident(it) => it.span_mut()))
})
.unzip();
quote! {
endl!();
@ -70,6 +71,15 @@ fn impl_enum(it @ REnum { item, .. }: &REnum) -> TokenStream {
}
}
}
endl!();
impl #generics GetSpanMut for #typ {
fn span_mut(&mut self) -> &mut Span {
match self {
#(#matches_mut),*
}
}
}
}
}
@ -78,18 +88,26 @@ fn impl_struct(it @ RStruct { item, .. }: &RStruct) -> TokenStream {
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 (span, span_mut) = if let Some(span_field) = inner_span_hint {
let ident = span_field.ident.as_ref().unwrap();
quote!(#ident.span())
(quote!(self.#ident.span()), quote!(self.#ident.span_mut()))
} else {
quote!(span)
(quote!(self.span), quote!(&mut self.span))
};
quote! {
endl!();
impl #generics GetSpan for #typ {
#[inline]
fn span(&self) -> Span {
self.#span
#span
}
}
endl!();
impl #generics GetSpanMut for #typ {
#[inline]
fn span_mut(&mut self) -> &mut Span {
#span_mut
}
}
}