diff --git a/Cargo.lock b/Cargo.lock index 0f6c6e48b424ff..05ecb6920d8015 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1755,6 +1755,7 @@ dependencies = [ "compact_str", "miette", "oxc_allocator", + "oxc_ast_macros", "schemars", "serde", "tsify", diff --git a/crates/oxc_ast/src/generated/assert_layouts.rs b/crates/oxc_ast/src/generated/assert_layouts.rs index 2482d310036fe8..aa95953acce6f2 100644 --- a/crates/oxc_ast/src/generated/assert_layouts.rs +++ b/crates/oxc_ast/src/generated/assert_layouts.rs @@ -4,6 +4,7 @@ use std::mem::{align_of, offset_of, size_of}; use crate::ast::*; +use oxc_span::*; use oxc_syntax::{number::*, operator::*}; #[cfg(target_pointer_width = "64")] @@ -1139,6 +1140,14 @@ const _: () = { assert!(align_of::() == 1usize); assert!(size_of::() == 1usize); assert!(align_of::() == 1usize); + assert!(size_of::() == 4usize); + assert!(align_of::() == 1usize); + assert!(size_of::() == 1usize); + assert!(align_of::() == 1usize); + assert!(size_of::() == 1usize); + assert!(align_of::() == 1usize); + assert!(size_of::() == 1usize); + assert!(align_of::() == 1usize); }; #[cfg(target_pointer_width = "32")] @@ -2274,6 +2283,14 @@ const _: () = { assert!(align_of::() == 1usize); assert!(size_of::() == 1usize); assert!(align_of::() == 1usize); + assert!(size_of::() == 4usize); + assert!(align_of::() == 1usize); + assert!(size_of::() == 1usize); + assert!(align_of::() == 1usize); + assert!(size_of::() == 1usize); + assert!(align_of::() == 1usize); + assert!(size_of::() == 1usize); + assert!(align_of::() == 1usize); }; #[cfg(not(any(target_pointer_width = "64", target_pointer_width = "32")))] diff --git a/crates/oxc_span/Cargo.toml b/crates/oxc_span/Cargo.toml index 24561de4e1b553..57fbc08b4b7268 100644 --- a/crates/oxc_span/Cargo.toml +++ b/crates/oxc_span/Cargo.toml @@ -20,7 +20,8 @@ workspace = true doctest = false [dependencies] -oxc_allocator = { workspace = true } +oxc_allocator = { workspace = true } +oxc_ast_macros = { workspace = true } miette = { workspace = true } compact_str = { workspace = true } diff --git a/crates/oxc_span/src/source_type.rs b/crates/oxc_span/src/source_type/mod.rs similarity index 72% rename from crates/oxc_span/src/source_type.rs rename to crates/oxc_span/src/source_type/mod.rs index 65284e1cb26691..c25af2e471a446 100644 --- a/crates/oxc_span/src/source_type.rs +++ b/crates/oxc_span/src/source_type/mod.rs @@ -1,60 +1,11 @@ // Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]` #![allow(non_snake_case)] -use std::path::Path; - -#[cfg(feature = "serialize")] -use serde::Serialize; -#[cfg(feature = "serialize")] -use tsify::Tsify; - -/// Source Type for JavaScript vs TypeScript / Script vs Module / JSX -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] -#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] -pub struct SourceType { - /// JavaScript or TypeScript, default JavaScript - language: Language, - - /// Script or Module, default Module - module_kind: ModuleKind, - - /// Support JSX for JavaScript and TypeScript? default without JSX - variant: LanguageVariant, - - /// Mark strict mode as always strict - /// See - always_strict: bool, -} - -/// JavaScript or TypeScript -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] -#[cfg_attr(feature = "serialize", serde(rename_all = "lowercase"))] -pub enum Language { - JavaScript, - TypeScript, - #[cfg_attr(feature = "serialize", serde(rename = "typescriptDefinition"))] - TypeScriptDefinition, -} +mod types; -/// Script or Module -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] -#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] -pub enum ModuleKind { - Script, - Module, -} +use std::path::Path; -/// JSX for JavaScript and TypeScript -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] -#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] -pub enum LanguageVariant { - Standard, - Jsx, -} +pub use types::*; #[derive(Debug)] pub struct UnknownExtension(pub String); diff --git a/crates/oxc_span/src/source_type/types.rs b/crates/oxc_span/src/source_type/types.rs new file mode 100644 index 00000000000000..44935f0c01ae82 --- /dev/null +++ b/crates/oxc_span/src/source_type/types.rs @@ -0,0 +1,55 @@ +use oxc_ast_macros::ast; +#[cfg(feature = "serialize")] +use ::{serde::Serialize, tsify::Tsify}; + +/// Source Type for JavaScript vs TypeScript / Script vs Module / JSX +#[ast] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] +#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] +pub struct SourceType { + /// JavaScript or TypeScript, default JavaScript + pub(super) language: Language, + + /// Script or Module, default Module + pub(super) module_kind: ModuleKind, + + /// Support JSX for JavaScript and TypeScript? default without JSX + pub(super) variant: LanguageVariant, + + /// Mark strict mode as always strict + /// See + pub(super) always_strict: bool, +} + +/// JavaScript or TypeScript +#[ast] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] +#[cfg_attr(feature = "serialize", serde(rename_all = "lowercase"))] +pub enum Language { + JavaScript = 0, + TypeScript = 1, + #[cfg_attr(feature = "serialize", serde(rename = "typescriptDefinition"))] + TypeScriptDefinition = 2, +} + +/// Script or Module +#[ast] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] +#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] +pub enum ModuleKind { + Script = 0, + Module = 1, +} + +/// JSX for JavaScript and TypeScript +#[ast] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] +#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] +pub enum LanguageVariant { + Standard = 0, + Jsx = 1, +} diff --git a/tasks/ast_codegen/src/generators/assert_layouts.rs b/tasks/ast_codegen/src/generators/assert_layouts.rs index 74ceb4fcb0f5e1..aa8bdfecc65753 100644 --- a/tasks/ast_codegen/src/generators/assert_layouts.rs +++ b/tasks/ast_codegen/src/generators/assert_layouts.rs @@ -42,6 +42,7 @@ impl Generator for AssertLayouts { endl!(); use crate::ast::*; + use oxc_span::*; use oxc_syntax::{number::*, operator::*}; @@ -100,12 +101,14 @@ fn with_offsets_assertion( ) -> TokenStream { let Some(offsets) = offsets else { return tk }; - let assertions = fields.iter().zip(offsets).map(|(field, offset)| { - let field = field.name.as_ref().map(|it| format_ident!("{it}")); - quote! { - assert!(offset_of!(#ty, #field) == #offset); - } - }); + let assertions = fields.iter().zip(offsets).filter(|(field, _)| field.vis.is_pub()).map( + |(field, offset)| { + let field = field.name.as_ref().map(|it| format_ident!("{it}")); + quote! { + assert!(offset_of!(#ty, #field) == #offset); + } + }, + ); tk.extend(assertions); tk } diff --git a/tasks/ast_codegen/src/main.rs b/tasks/ast_codegen/src/main.rs index 0a0f10432a4e19..6c60a7fc40a9fa 100644 --- a/tasks/ast_codegen/src/main.rs +++ b/tasks/ast_codegen/src/main.rs @@ -1,5 +1,6 @@ const AST_CRATE: &str = "crates/oxc_ast"; const AST_SYNTAX: &str = "crates/oxc_syntax"; +const AST_SPAN: &str = "crates/oxc_span"; #[allow(dead_code)] const AST_MACROS_CRATE: &str = "crates/oxc_ast_macros"; @@ -252,8 +253,20 @@ fn files() -> impl std::iter::Iterator { format!("{AST_SYNTAX}/src/{path}.rs") } - vec![ast("literal"), ast("js"), ast("ts"), ast("jsx"), syntax("number"), syntax("operator")] - .into_iter() + fn span(path: &str) -> String { + format!("{AST_SPAN}/src/{path}.rs") + } + + vec![ + ast("literal"), + ast("js"), + ast("ts"), + ast("jsx"), + syntax("number"), + syntax("operator"), + span("source_type/types"), + ] + .into_iter() } fn write_generated_streams( diff --git a/tasks/ast_codegen/src/passes/calc_layout.rs b/tasks/ast_codegen/src/passes/calc_layout.rs index dc0b68e67d1459..942079faf759ff 100644 --- a/tasks/ast_codegen/src/passes/calc_layout.rs +++ b/tasks/ast_codegen/src/passes/calc_layout.rs @@ -360,7 +360,6 @@ lazy_static! { Cell>: { _ => Layout::known(4, 4, 0), }, Cell>: { _ => Layout::known(4, 4, 0), }, Cell>: { _ => Layout::known(4, 4, 0), }, - SourceType: { _ => Layout::known(4, 1, 1), }, // Unsupported: this is a `bitflags` generated type, we don't expand macros ReferenceFlag: { _ => Layout::known(1, 1, 0), }, // Unsupported: this is a `bitflags` generated type, we don't expand macros diff --git a/tasks/ast_codegen/src/rust_ast.rs b/tasks/ast_codegen/src/rust_ast.rs index 6778cf0c88c295..a2fc83d0f90408 100644 --- a/tasks/ast_codegen/src/rust_ast.rs +++ b/tasks/ast_codegen/src/rust_ast.rs @@ -401,7 +401,7 @@ pub fn analyze(ast_ref: &AstRef) -> Result<()> { // AST without visit! ast_ref.borrow_mut().set_ast(true)?; } - Some(AstAttr::None) => return Err(String::from("All `enums` and `structs` defined in the source of truth should be marked with an `#[ast]` attribute!")), + Some(AstAttr::None) => return Err(format!("All `enums` and `structs` defined in the source of truth should be marked with an `#[ast]` attribute(missing `#[ast]` on '{:?}')", ast_ref.borrow().ident())), None => { /* unrelated items like `use`, `type` and `macro` definitions */ } } diff --git a/tasks/ast_codegen/src/schema/defs.rs b/tasks/ast_codegen/src/schema/defs.rs index 18588be6692870..989c2f12fca270 100644 --- a/tasks/ast_codegen/src/schema/defs.rs +++ b/tasks/ast_codegen/src/schema/defs.rs @@ -93,11 +93,36 @@ pub struct InheritDef { pub struct FieldDef { /// `None` if unnamed pub name: Option, + pub vis: Visibility, pub typ: TypeRef, pub markers: InnerMarkers, pub docs: Vec, } +#[derive(Debug, Serialize)] +pub enum Visibility { + None, + Pub, + /// rest of the restricted visibilities + Rest, +} + +impl Visibility { + pub fn is_pub(&self) -> bool { + matches!(self, Self::Pub) + } +} + +impl From<&syn::Visibility> for Visibility { + fn from(vis: &syn::Visibility) -> Self { + match vis { + syn::Visibility::Public(_) => Self::Pub, + syn::Visibility::Inherited => Self::None, + syn::Visibility::Restricted(_) => Self::Rest, + } + } +} + impl FieldDef { pub fn ident(&self) -> Option { self.name.as_ref().map(ToIdent::to_ident) diff --git a/tasks/ast_codegen/src/schema/mod.rs b/tasks/ast_codegen/src/schema/mod.rs index ed9cc60efcc9ea..264710d4f7557e 100644 --- a/tasks/ast_codegen/src/schema/mod.rs +++ b/tasks/ast_codegen/src/schema/mod.rs @@ -219,6 +219,7 @@ fn lower_inherit(inherit: &rust::Inherit, ctx: &crate::EarlyCtx) -> InheritDef { fn lower_field(field: &syn::Field, ctx: &crate::EarlyCtx) -> FieldDef { FieldDef { name: field.ident.as_ref().map(ToString::to_string), + vis: Visibility::from(&field.vis), typ: create_type_ref(&field.ty, ctx), markers: parse_inner_markers(&field.attrs).unwrap(), docs: get_docs(&field.attrs),