mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(ast_codegen, span): process SourceType through ast_codegen. (#4696)
This commit is contained in:
parent
3f3cb629af
commit
125c5fd8ed
12 changed files with 130 additions and 63 deletions
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
|
|
@ -280,6 +280,7 @@ jobs:
|
|||
- 'crates/oxc_ast/src/generated/**' # to potentially cause CI error if generated files are edited manually
|
||||
- 'crates/oxc_syntax/src/number.rs'
|
||||
- 'crates/oxc_syntax/src/operator.rs'
|
||||
- 'crates/oxc_span/src/source_type/types.rs'
|
||||
- 'tasks/ast_codegen/src/**'
|
||||
|
||||
- uses: Boshen/setup-rust@main
|
||||
|
|
|
|||
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1755,6 +1755,7 @@ dependencies = [
|
|||
"compact_str",
|
||||
"miette",
|
||||
"oxc_allocator",
|
||||
"oxc_ast_macros",
|
||||
"schemars",
|
||||
"serde",
|
||||
"tsify",
|
||||
|
|
|
|||
|
|
@ -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::<UnaryOperator>() == 1usize);
|
||||
assert!(size_of::<UpdateOperator>() == 1usize);
|
||||
assert!(align_of::<UpdateOperator>() == 1usize);
|
||||
assert!(size_of::<SourceType>() == 4usize);
|
||||
assert!(align_of::<SourceType>() == 1usize);
|
||||
assert!(size_of::<Language>() == 1usize);
|
||||
assert!(align_of::<Language>() == 1usize);
|
||||
assert!(size_of::<ModuleKind>() == 1usize);
|
||||
assert!(align_of::<ModuleKind>() == 1usize);
|
||||
assert!(size_of::<LanguageVariant>() == 1usize);
|
||||
assert!(align_of::<LanguageVariant>() == 1usize);
|
||||
};
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
|
|
@ -2274,6 +2283,14 @@ const _: () = {
|
|||
assert!(align_of::<UnaryOperator>() == 1usize);
|
||||
assert!(size_of::<UpdateOperator>() == 1usize);
|
||||
assert!(align_of::<UpdateOperator>() == 1usize);
|
||||
assert!(size_of::<SourceType>() == 4usize);
|
||||
assert!(align_of::<SourceType>() == 1usize);
|
||||
assert!(size_of::<Language>() == 1usize);
|
||||
assert!(align_of::<Language>() == 1usize);
|
||||
assert!(size_of::<ModuleKind>() == 1usize);
|
||||
assert!(align_of::<ModuleKind>() == 1usize);
|
||||
assert!(size_of::<LanguageVariant>() == 1usize);
|
||||
assert!(align_of::<LanguageVariant>() == 1usize);
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_pointer_width = "64", target_pointer_width = "32")))]
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -1,60 +1,11 @@
|
|||
// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
mod types;
|
||||
|
||||
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 <https://github.com/tc39/test262/blob/main/INTERPRETING.md#strict-mode>
|
||||
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,
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
/// 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);
|
||||
55
crates/oxc_span/src/source_type/types.rs
Normal file
55
crates/oxc_span/src/source_type/types.rs
Normal file
|
|
@ -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 <https://github.com/tc39/test262/blob/main/INTERPRETING.md#strict-mode>
|
||||
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,
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Item = String> {
|
|||
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(
|
||||
|
|
|
|||
|
|
@ -360,7 +360,6 @@ lazy_static! {
|
|||
Cell<Option<ScopeId>>: { _ => Layout::known(4, 4, 0), },
|
||||
Cell<Option<SymbolId>>: { _ => Layout::known(4, 4, 0), },
|
||||
Cell<Option<ReferenceId>>: { _ => 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
|
||||
|
|
|
|||
|
|
@ -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 */ }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,11 +93,36 @@ pub struct InheritDef {
|
|||
pub struct FieldDef {
|
||||
/// `None` if unnamed
|
||||
pub name: Option<String>,
|
||||
pub vis: Visibility,
|
||||
pub typ: TypeRef,
|
||||
pub markers: InnerMarkers,
|
||||
pub docs: Vec<String>,
|
||||
}
|
||||
|
||||
#[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<syn::Ident> {
|
||||
self.name.as_ref().map(ToIdent::to_ident)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
Loading…
Reference in a new issue