feat(ast_codegen, span): process SourceType through ast_codegen. (#4696)

This commit is contained in:
rzvxa 2024-08-06 17:42:12 +00:00
parent 3f3cb629af
commit 125c5fd8ed
12 changed files with 130 additions and 63 deletions

View file

@ -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
View file

@ -1755,6 +1755,7 @@ dependencies = [
"compact_str",
"miette",
"oxc_allocator",
"oxc_ast_macros",
"schemars",
"serde",
"tsify",

View file

@ -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")))]

View file

@ -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 }

View file

@ -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);

View 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,
}

View file

@ -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
}

View file

@ -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(

View file

@ -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

View file

@ -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 */ }
}

View file

@ -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)

View file

@ -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),