diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 097295d5d..734266e0b 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -44,6 +44,7 @@ pub struct Program<'a> { pub hashbang: Option>, pub directives: Vec<'a, Directive<'a>>, pub body: Vec<'a, Statement<'a>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -235,12 +236,14 @@ pub struct IdentifierReference<'a> { /// set in the bind step of semantic analysis, and will always be [`None`] /// immediately after parsing. #[serde(skip)] + #[clone_in(default)] pub reference_id: Cell>, /// Flags indicating how the reference is used. /// /// This gets set in the bind step of semantic analysis, and will always be /// [`ReferenceFlag::None`] immediately after parsing. #[serde(skip)] + #[clone_in(default)] pub reference_flag: ReferenceFlag, } @@ -266,6 +269,7 @@ pub struct BindingIdentifier<'a> { /// /// [`semantic analysis`]: #[serde(skip)] + #[clone_in(default)] pub symbol_id: Cell>, } @@ -1183,6 +1187,7 @@ pub struct BlockStatement<'a> { #[serde(flatten)] pub span: Span, pub body: Vec<'a, Statement<'a>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1357,6 +1362,7 @@ pub struct ForStatement<'a> { pub test: Option>, pub update: Option>, pub body: Statement<'a>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1392,6 +1398,7 @@ pub struct ForInStatement<'a> { pub left: ForStatementLeft<'a>, pub right: Expression<'a>, pub body: Statement<'a>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1427,6 +1434,7 @@ pub struct ForOfStatement<'a> { pub left: ForStatementLeft<'a>, pub right: Expression<'a>, pub body: Statement<'a>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1492,6 +1500,7 @@ pub struct SwitchStatement<'a> { pub discriminant: Expression<'a>, #[scope(enter_before)] pub cases: Vec<'a, SwitchCase<'a>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1558,6 +1567,7 @@ pub struct CatchClause<'a> { pub span: Span, pub param: Option>, pub body: Box<'a, BlockStatement<'a>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1725,6 +1735,7 @@ pub struct Function<'a> { pub params: Box<'a, FormalParameters<'a>>, pub return_type: Option>>, pub body: Option>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1821,6 +1832,7 @@ pub struct ArrowFunctionExpression<'a> { pub return_type: Option>>, /// See `expression` for whether this arrow expression returns an expression. pub body: Box<'a, FunctionBody<'a>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1907,6 +1919,7 @@ pub struct Class<'a> { pub declare: bool, /// Id of the scope created by the [`Class`], including type parameters and /// statements within the [`ClassBody`]. + #[clone_in(default)] pub scope_id: Cell>, } @@ -2163,6 +2176,7 @@ pub struct StaticBlock<'a> { #[serde(flatten)] pub span: Span, pub body: Vec<'a, Statement<'a>>, + #[clone_in(default)] pub scope_id: Cell>, } diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index bb486fc4e..78d55a748 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -76,6 +76,7 @@ pub struct TSEnumDeclaration<'a> { pub members: Vec<'a, TSEnumMember<'a>>, pub r#const: bool, pub declare: bool, + #[clone_in(default)] pub scope_id: Cell>, } @@ -313,6 +314,7 @@ pub struct TSConditionalType<'a> { pub extends_type: TSType<'a>, pub true_type: TSType<'a>, pub false_type: TSType<'a>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -757,6 +759,7 @@ pub struct TSTypeAliasDeclaration<'a> { pub type_parameters: Option>>, pub type_annotation: TSType<'a>, pub declare: bool, + #[clone_in(default)] pub scope_id: Cell>, } @@ -802,6 +805,7 @@ pub struct TSInterfaceDeclaration<'a> { pub type_parameters: Option>>, pub body: Box<'a, TSInterfaceBody<'a>>, pub declare: bool, + #[clone_in(default)] pub scope_id: Cell>, } @@ -910,6 +914,7 @@ pub struct TSMethodSignature<'a> { pub params: Box<'a, FormalParameters<'a>>, pub return_type: Option>>, pub type_parameters: Option>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -925,6 +930,7 @@ pub struct TSConstructSignatureDeclaration<'a> { pub params: Box<'a, FormalParameters<'a>>, pub return_type: Option>>, pub type_parameters: Option>>, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1001,6 +1007,7 @@ pub struct TSModuleDeclaration<'a> { /// ``` pub kind: TSModuleDeclarationKind, pub declare: bool, + #[clone_in(default)] pub scope_id: Cell>, } @@ -1198,6 +1205,7 @@ pub struct TSMappedType<'a> { pub type_annotation: Option>, pub optional: TSMappedTypeModifierOperator, pub readonly: TSMappedTypeModifierOperator, + #[clone_in(default)] pub scope_id: Cell>, } diff --git a/crates/oxc_ast/src/generated/derive_clone_in.rs b/crates/oxc_ast/src/generated/derive_clone_in.rs index 4f396074b..f90a8b53e 100644 --- a/crates/oxc_ast/src/generated/derive_clone_in.rs +++ b/crates/oxc_ast/src/generated/derive_clone_in.rs @@ -1,6 +1,7 @@ // Auto-generated code, DO NOT EDIT DIRECTLY! // To edit this generated file you have to edit `tasks/ast_codegen/src/generators/derive_clone_in.rs` +#![allow(clippy::default_trait_access)] use oxc_allocator::{Allocator, CloneIn}; #[allow(clippy::wildcard_imports)] @@ -84,7 +85,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for Program<'old_alloc> { hashbang: self.hashbang.clone_in(alloc), directives: self.directives.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -170,8 +171,8 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for IdentifierReference<'old_al IdentifierReference { span: self.span.clone_in(alloc), name: self.name.clone_in(alloc), - reference_id: self.reference_id.clone_in(alloc), - reference_flag: self.reference_flag.clone_in(alloc), + reference_id: Default::default(), + reference_flag: Default::default(), } } } @@ -182,7 +183,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for BindingIdentifier<'old_allo BindingIdentifier { span: self.span.clone_in(alloc), name: self.name.clone_in(alloc), - symbol_id: self.symbol_id.clone_in(alloc), + symbol_id: Default::default(), } } } @@ -1077,7 +1078,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for BlockStatement<'old_alloc> BlockStatement { span: self.span.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1212,7 +1213,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for ForStatement<'old_alloc> { test: self.test.clone_in(alloc), update: self.update.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1307,7 +1308,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for ForInStatement<'old_alloc> left: self.left.clone_in(alloc), right: self.right.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1362,7 +1363,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for ForOfStatement<'old_alloc> left: self.left.clone_in(alloc), right: self.right.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1406,7 +1407,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for SwitchStatement<'old_alloc> span: self.span.clone_in(alloc), discriminant: self.discriminant.clone_in(alloc), cases: self.cases.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1459,7 +1460,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for CatchClause<'old_alloc> { span: self.span.clone_in(alloc), param: self.param.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1576,7 +1577,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for Function<'old_alloc> { params: self.params.clone_in(alloc), return_type: self.return_type.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1653,7 +1654,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for ArrowFunctionExpression<'ol params: self.params.clone_in(alloc), return_type: self.return_type.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1684,7 +1685,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for Class<'old_alloc> { body: self.body.clone_in(alloc), r#abstract: self.r#abstract.clone_in(alloc), declare: self.declare.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -1807,7 +1808,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for StaticBlock<'old_alloc> { StaticBlock { span: self.span.clone_in(alloc), body: self.body.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -2182,7 +2183,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSEnumDeclaration<'old_allo members: self.members.clone_in(alloc), r#const: self.r#const.clone_in(alloc), declare: self.declare.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -2374,7 +2375,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSConditionalType<'old_allo extends_type: self.extends_type.clone_in(alloc), true_type: self.true_type.clone_in(alloc), false_type: self.false_type.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -2718,7 +2719,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSTypeAliasDeclaration<'old type_parameters: self.type_parameters.clone_in(alloc), type_annotation: self.type_annotation.clone_in(alloc), declare: self.declare.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -2755,7 +2756,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSInterfaceDeclaration<'old type_parameters: self.type_parameters.clone_in(alloc), body: self.body.clone_in(alloc), declare: self.declare.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -2847,7 +2848,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSMethodSignature<'old_allo params: self.params.clone_in(alloc), return_type: self.return_type.clone_in(alloc), type_parameters: self.type_parameters.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -2860,7 +2861,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSConstructSignatureDeclara params: self.params.clone_in(alloc), return_type: self.return_type.clone_in(alloc), type_parameters: self.type_parameters.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -2918,7 +2919,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSModuleDeclaration<'old_al body: self.body.clone_in(alloc), kind: self.kind.clone_in(alloc), declare: self.declare.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } @@ -3090,7 +3091,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for TSMappedType<'old_alloc> { type_annotation: self.type_annotation.clone_in(alloc), optional: self.optional.clone_in(alloc), readonly: self.readonly.clone_in(alloc), - scope_id: self.scope_id.clone_in(alloc), + scope_id: Default::default(), } } } diff --git a/crates/oxc_ast_macros/src/lib.rs b/crates/oxc_ast_macros/src/lib.rs index dcdb9f9bd..e1d9a9234 100644 --- a/crates/oxc_ast_macros/src/lib.rs +++ b/crates/oxc_ast_macros/src/lib.rs @@ -106,7 +106,7 @@ pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream { /// Does not generate any code. /// Only purpose is to allow using `#[scope]`, `#[visit]`, and other attrs in the AST node type defs. /// These "marker" attributes are used in codegen. -#[proc_macro_derive(Ast, attributes(scope, visit, span, serde, tsify, generate_derive))] +#[proc_macro_derive(Ast, attributes(scope, visit, span, serde, tsify, generate_derive, clone_in))] pub fn ast_derive(_item: TokenStream) -> TokenStream { TokenStream::new() } diff --git a/tasks/ast_codegen/src/generators/derive_clone_in.rs b/tasks/ast_codegen/src/generators/derive_clone_in.rs index 7e2d2c9ae..732a44e6d 100644 --- a/tasks/ast_codegen/src/generators/derive_clone_in.rs +++ b/tasks/ast_codegen/src/generators/derive_clone_in.rs @@ -5,6 +5,7 @@ use syn::Ident; use crate::{ codegen::LateCtx, + markers::CloneInAttribute, output, schema::{EnumDef, GetIdent, StructDef, TypeDef}, GeneratorOutput, @@ -35,6 +36,8 @@ impl Generator for DeriveCloneIn { quote! { #header + #![allow(clippy::default_trait_access)] + use oxc_allocator::{Allocator, CloneIn}; ///@@line_break @@ -83,7 +86,10 @@ fn derive_struct(def: &StructDef) -> TokenStream { } else { let fields = def.fields.iter().map(|field| { let ident = field.ident(); - quote!(#ident: self.#ident.clone_in(alloc)) + match field.markers.derive_attributes.clone_in { + CloneInAttribute::Default => quote!(#ident: Default::default()), + CloneInAttribute::None => quote!(#ident: self.#ident.clone_in(alloc)), + } }); (format_ident!("alloc"), quote!(#ty_ident { #(#fields),* })) }; diff --git a/tasks/ast_codegen/src/markers.rs b/tasks/ast_codegen/src/markers.rs index fb3c383de..584d40934 100644 --- a/tasks/ast_codegen/src/markers.rs +++ b/tasks/ast_codegen/src/markers.rs @@ -1,4 +1,5 @@ use proc_macro2::TokenStream; +use serde::Serialize; use syn::{ ext::IdentExt, parenthesized, @@ -65,6 +66,30 @@ pub struct ScopeMarkers { pub enter_before: bool, } +/// A struct representing the `#[scope(...)]` attribute. +#[derive(Debug, Default, Serialize)] +pub struct DeriveAttributes { + pub clone_in: CloneInAttribute, +} + +/// A enum representing the value passed in `#[clone_in(...)]` derive attribute. +#[derive(Debug, Default, Serialize)] +pub enum CloneInAttribute { + #[default] + None, + Default, +} + +impl From<&Ident> for CloneInAttribute { + fn from(ident: &Ident) -> Self { + if ident == "default" { + Self::Default + } else { + panic!("Invalid argument used in `#[clone_in(...)]` attribute."); + } + } +} + /// A struct representing the `#[scope(...)]` attribute. #[derive(Debug, Default)] pub struct ScopeAttribute { @@ -186,6 +211,27 @@ where ) } +pub fn get_derive_attributes<'a, I>(attrs: I) -> crate::Result +where + I: IntoIterator, +{ + fn try_parse_clone_in(attr: &Attribute) -> crate::Result> { + if attr.path().is_ident("clone_in") { + let arg = attr.parse_args_with(Ident::parse).normalize()?; + Ok(Some(CloneInAttribute::from(&arg))) + } else { + Ok(None) + } + } + let mut clone_in = None; + for attr in attrs { + if let Some(attr) = try_parse_clone_in(attr)? { + assert!(clone_in.replace(attr).is_none(), "Duplicate `#[clone_in(...)]` attribute."); + } + } + Ok(DeriveAttributes { clone_in: clone_in.unwrap_or_default() }) +} + pub fn get_scope_attribute<'a, I>(attrs: I) -> Option> where I: IntoIterator, diff --git a/tasks/ast_codegen/src/schema/defs.rs b/tasks/ast_codegen/src/schema/defs.rs index f6e146348..cfa9bc169 100644 --- a/tasks/ast_codegen/src/schema/defs.rs +++ b/tasks/ast_codegen/src/schema/defs.rs @@ -1,7 +1,7 @@ use serde::Serialize; use crate::{ - markers::{ScopeAttribute, ScopeMarkers, VisitMarkers}, + markers::{DeriveAttributes, ScopeAttribute, ScopeMarkers, VisitMarkers}, util::{ToIdent, TypeAnalysis, TypeWrapper}, TypeId, }; @@ -227,6 +227,7 @@ pub struct OuterMarkers { pub struct InnerMarkers { /// marker that hints to fold span in here pub span: bool, + pub derive_attributes: DeriveAttributes, #[serde(skip)] pub visit: VisitMarkers, #[serde(skip)] diff --git a/tasks/ast_codegen/src/schema/mod.rs b/tasks/ast_codegen/src/schema/mod.rs index a74bfcdb7..bb8791fb4 100644 --- a/tasks/ast_codegen/src/schema/mod.rs +++ b/tasks/ast_codegen/src/schema/mod.rs @@ -4,7 +4,7 @@ use serde::Serialize; use crate::{ codegen, layout::KnownLayout, - markers::{get_scope_attribute, get_scope_markers, get_visit_markers}, + markers::{get_derive_attributes, get_scope_attribute, get_scope_markers, get_visit_markers}, rust_ast as rust, util::{unexpanded_macro_err, TypeExt}, Result, TypeId, @@ -111,6 +111,7 @@ fn parse_inner_markers(attrs: &Vec) -> Result { span: attrs.iter().any(|a| a.path().is_ident("span")), visit: get_visit_markers(attrs)?, scope: get_scope_markers(attrs)?, + derive_attributes: get_derive_attributes(attrs)?, }) }