diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 5def04414cae0..dcbb06be853ef 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -40,7 +40,6 @@ pub struct Program<'a> { pub hashbang: Option>, pub directives: Vec<'a, Directive<'a>>, pub body: Vec<'a, Statement<'a>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -225,7 +224,6 @@ pub struct IdentifierReference<'a> { /// Identifies what identifier this refers to, and how it is used. This is /// set in the bind step of semantic analysis, and will always be [`None`] /// immediately after parsing. - #[estree(skip)] pub reference_id: Cell>, } @@ -248,7 +246,6 @@ pub struct BindingIdentifier<'a> { /// you choose to skip semantic analysis, this will always be [`None`]. /// /// [`semantic analysis`]: - #[estree(skip)] pub symbol_id: Cell>, } @@ -1039,7 +1036,6 @@ pub struct Hashbang<'a> { pub struct BlockStatement<'a> { pub span: Span, pub body: Vec<'a, Statement<'a>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1182,7 +1178,6 @@ pub struct ForStatement<'a> { pub test: Option>, pub update: Option>, pub body: Statement<'a>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1212,7 +1207,6 @@ pub struct ForInStatement<'a> { pub left: ForStatementLeft<'a>, pub right: Expression<'a>, pub body: Statement<'a>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1242,7 +1236,6 @@ pub struct ForOfStatement<'a> { pub left: ForStatementLeft<'a>, pub right: Expression<'a>, pub body: Statement<'a>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1293,7 +1286,6 @@ pub struct SwitchStatement<'a> { pub discriminant: Expression<'a>, #[scope(enter_before)] pub cases: Vec<'a, SwitchCase<'a>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1382,7 +1374,6 @@ pub struct CatchClause<'a> { pub param: Option>, /// The statements run when an error is caught pub body: Box<'a, BlockStatement<'a>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1615,7 +1606,6 @@ pub struct Function<'a> { /// } /// ``` pub body: Option>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1706,7 +1696,6 @@ pub struct ArrowFunctionExpression<'a> { pub return_type: Option>>, /// See `expression` for whether this arrow expression returns an expression. pub body: Box<'a, FunctionBody<'a>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1792,7 +1781,6 @@ pub struct Class<'a> { pub declare: bool, /// Id of the scope created by the [`Class`], including type parameters and /// statements within the [`ClassBody`]. - #[estree(skip)] pub scope_id: Cell>, } @@ -2043,7 +2031,6 @@ pub struct PrivateIdentifier<'a> { pub struct StaticBlock<'a> { pub span: Span, pub body: Vec<'a, Statement<'a>>, - #[estree(skip)] pub scope_id: Cell>, } diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index a56d50de56436..21cc75e01faad 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -71,7 +71,6 @@ pub struct TSEnumDeclaration<'a> { /// `true` for const enums pub r#const: bool, pub declare: bool, - #[estree(skip)] pub scope_id: Cell>, } @@ -302,7 +301,6 @@ pub struct TSConditionalType<'a> { /// The type evaluated to if the test is false. #[scope(exit_before)] pub false_type: TSType<'a>, - #[estree(skip)] pub scope_id: Cell>, } @@ -834,7 +832,6 @@ pub struct TSTypeAliasDeclaration<'a> { pub type_parameters: Option>>, pub type_annotation: TSType<'a>, pub declare: bool, - #[estree(skip)] pub scope_id: Cell>, } @@ -897,7 +894,6 @@ pub struct TSInterfaceDeclaration<'a> { pub body: Box<'a, TSInterfaceBody<'a>>, /// `true` for `declare interface Foo {}` pub declare: bool, - #[estree(skip)] pub scope_id: Cell>, } @@ -1015,7 +1011,6 @@ pub struct TSMethodSignature<'a> { pub this_param: Option>>, pub params: Box<'a, FormalParameters<'a>>, pub return_type: Option>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1029,7 +1024,6 @@ pub struct TSConstructSignatureDeclaration<'a> { pub type_parameters: Option>>, pub params: Box<'a, FormalParameters<'a>>, pub return_type: Option>>, - #[estree(skip)] pub scope_id: Cell>, } @@ -1153,7 +1147,6 @@ pub struct TSModuleDeclaration<'a> { /// ``` pub kind: TSModuleDeclarationKind, pub declare: bool, - #[estree(skip)] pub scope_id: Cell>, } @@ -1423,7 +1416,6 @@ pub struct TSMappedType<'a> { /// type Qux = { [P in keyof T]: T[P] } // None /// ``` pub readonly: TSMappedTypeModifierOperator, - #[estree(skip)] pub scope_id: Cell>, } diff --git a/crates/oxc_syntax/src/reference.rs b/crates/oxc_syntax/src/reference.rs index 4e7df9960a89c..eb718abc32e92 100644 --- a/crates/oxc_syntax/src/reference.rs +++ b/crates/oxc_syntax/src/reference.rs @@ -15,6 +15,7 @@ use oxc_ast_macros::ast; #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[clone_in(default)] #[content_eq(skip)] +#[estree(skip)] pub struct ReferenceId(NonMaxU32); impl Idx for ReferenceId { diff --git a/crates/oxc_syntax/src/scope.rs b/crates/oxc_syntax/src/scope.rs index 1744a3ffb6865..dc5439158f333 100644 --- a/crates/oxc_syntax/src/scope.rs +++ b/crates/oxc_syntax/src/scope.rs @@ -11,6 +11,7 @@ use oxc_ast_macros::ast; #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[clone_in(default)] #[content_eq(skip)] +#[estree(skip)] pub struct ScopeId(NonMaxU32); impl ScopeId { diff --git a/crates/oxc_syntax/src/symbol.rs b/crates/oxc_syntax/src/symbol.rs index 3e8f6cddb3682..4784e80af68a5 100644 --- a/crates/oxc_syntax/src/symbol.rs +++ b/crates/oxc_syntax/src/symbol.rs @@ -11,6 +11,7 @@ use oxc_ast_macros::ast; #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[clone_in(default)] #[content_eq(skip)] +#[estree(skip)] pub struct SymbolId(NonMaxU32); impl SymbolId { diff --git a/tasks/ast_tools/src/derives/estree.rs b/tasks/ast_tools/src/derives/estree.rs index 89ca84914849b..a066cdb3db464 100644 --- a/tasks/ast_tools/src/derives/estree.rs +++ b/tasks/ast_tools/src/derives/estree.rs @@ -35,8 +35,12 @@ impl Derive for DeriveESTree { } /// Register that accept `#[estree]` attr on structs, enums, struct fields, or enum variants. + /// Allow attr on structs and enums which don't derive this trait. fn attrs(&self) -> &[(&'static str, AttrPositions)] { - &[("estree", attr_positions!(Struct | Enum | StructField | EnumVariant))] + &[( + "estree", + attr_positions!(StructMaybeDerived | EnumMaybeDerived | StructField | EnumVariant), + )] } /// Parse `#[estree]` attr. @@ -84,6 +88,7 @@ fn parse_estree_attr(location: AttrLocation, part: AttrPart) -> Result<()> { match location { // `#[estree]` attr on struct AttrLocation::Struct(struct_def) => match part { + AttrPart::Tag("skip") => struct_def.estree.skip = true, AttrPart::Tag("flatten") => struct_def.estree.flatten = true, AttrPart::Tag("no_type") => struct_def.estree.no_type = true, AttrPart::Tag("custom_serialize") => struct_def.estree.custom_serialize = true, @@ -94,6 +99,7 @@ fn parse_estree_attr(location: AttrLocation, part: AttrPart) -> Result<()> { }, // `#[estree]` attr on enum AttrLocation::Enum(enum_def) => match part { + AttrPart::Tag("skip") => enum_def.estree.skip = true, AttrPart::Tag("no_rename_variants") => enum_def.estree.no_rename_variants = true, AttrPart::Tag("custom_ts_def") => enum_def.estree.custom_ts_def = true, _ => return Err(()), @@ -164,7 +170,7 @@ fn generate_body_for_struct(struct_def: &StructDef, schema: &Schema) -> TokenStr } for field in &struct_def.fields { - if !field.estree.skip { + if !should_skip_field(field, schema) { stmts.extend(generate_stmt_for_struct_field(field, struct_def, schema)); } } @@ -263,6 +269,25 @@ pub fn should_add_type_field_to_struct(struct_def: &StructDef) -> bool { } } +/// Get if a struct field should be skipped when serializing. +/// +/// Returns `true` if either the field has an `#[estree(skip)]` attr on it, +/// or the type that the field contains has an `#[estree(skip)]` attr. +/// +/// This function also used by Typescript generator. +pub fn should_skip_field(field: &FieldDef, schema: &Schema) -> bool { + if field.estree.skip { + true + } else { + let innermost_type = field.type_def(schema).innermost_type(schema); + match innermost_type { + TypeDef::Struct(struct_def) => struct_def.estree.skip, + TypeDef::Enum(enum_def) => enum_def.estree.skip, + _ => false, + } + } +} + /// Get if should flatten a struct field. /// /// Returns `true` if either the field has an `#[estree(flatten)]` attr on it, diff --git a/tasks/ast_tools/src/generators/typescript.rs b/tasks/ast_tools/src/generators/typescript.rs index eb2bf6a88d5f9..7c0ef46698688 100644 --- a/tasks/ast_tools/src/generators/typescript.rs +++ b/tasks/ast_tools/src/generators/typescript.rs @@ -7,7 +7,7 @@ use itertools::Itertools; use crate::{ derives::estree::{ get_fieldless_variant_value, get_struct_field_name, should_add_type_field_to_struct, - should_flatten_field, + should_flatten_field, should_skip_field, }, output::Output, schema::{Def, EnumDef, FieldDef, Schema, StructDef, TypeDef}, @@ -93,7 +93,7 @@ fn generate_ts_type_def_for_struct(struct_def: &StructDef, schema: &Schema) -> S let mut output_as_type = false; for field in &struct_def.fields { - if field.estree.skip { + if should_skip_field(field, schema) { continue; } diff --git a/tasks/ast_tools/src/schema/extensions/estree.rs b/tasks/ast_tools/src/schema/extensions/estree.rs index ea681e424df2a..1dfdcc28b755e 100644 --- a/tasks/ast_tools/src/schema/extensions/estree.rs +++ b/tasks/ast_tools/src/schema/extensions/estree.rs @@ -4,6 +4,7 @@ pub struct ESTreeStruct { pub rename: Option, pub via: Option, pub add_ts: Option, + pub skip: bool, pub flatten: bool, pub no_type: bool, pub custom_serialize: bool, @@ -12,6 +13,7 @@ pub struct ESTreeStruct { /// Configuration for ESTree generator on an enum. #[derive(Default, Debug)] pub struct ESTreeEnum { + pub skip: bool, pub no_rename_variants: bool, pub custom_ts_def: bool, }