mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(ast_tools): reduce macro usage (#6895)
1. Reduce the amount of code in `define_derive!` and `define_generator!` macros. This makes the code easier to read, and gives type hints in IDE. 2. Remove `generated_header!` macro and insert header as a blanket action, instead of repeated code in every generator.
This commit is contained in:
parent
5b21eb5455
commit
3e7507f9d0
14 changed files with 231 additions and 192 deletions
|
|
@ -1,7 +1,8 @@
|
||||||
//! AST node factories
|
|
||||||
// Auto-generated code, DO NOT EDIT DIRECTLY!
|
// Auto-generated code, DO NOT EDIT DIRECTLY!
|
||||||
// To edit this generated file you have to edit `tasks/ast_tools/src/generators/ast_builder.rs`
|
// To edit this generated file you have to edit `tasks/ast_tools/src/generators/ast_builder.rs`
|
||||||
|
|
||||||
|
//! AST node factories
|
||||||
|
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::default_trait_access,
|
clippy::default_trait_access,
|
||||||
clippy::too_many_arguments,
|
clippy::too_many_arguments,
|
||||||
|
|
|
||||||
|
|
@ -238,18 +238,20 @@ impl AstCodegen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implemented by `define_derive!` and `define_generator!` macros
|
||||||
|
pub trait CodegenBase {
|
||||||
|
fn file_path() -> &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a generated file warning + required information for a generated file.
|
/// Creates a generated file warning + required information for a generated file.
|
||||||
macro_rules! generated_header {
|
pub fn generate_header(file_path: &str) -> TokenStream {
|
||||||
() => {{
|
let file_path = file_path.replace('\\', "/");
|
||||||
let file = file!().replace("\\", "/");
|
|
||||||
// TODO add generation date, AST source hash, etc here.
|
// TODO: Add generation date, AST source hash, etc here.
|
||||||
let edit_comment = format!("@ To edit this generated file you have to edit `{file}`");
|
let edit_comment = format!("@ To edit this generated file you have to edit `{file_path}`");
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
//!@ Auto-generated code, DO NOT EDIT DIRECTLY!
|
//!@ Auto-generated code, DO NOT EDIT DIRECTLY!
|
||||||
#![doc = #edit_comment]
|
#![doc = #edit_comment]
|
||||||
//!@@line_break
|
//!@@line_break
|
||||||
}
|
}
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use generated_header;
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,16 @@ use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
|
|
||||||
use super::{define_derive, Derive, DeriveOutput};
|
use super::{define_derive, Derive};
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::LateCtx,
|
codegen::LateCtx,
|
||||||
markers::CloneInAttribute,
|
markers::CloneInAttribute,
|
||||||
schema::{EnumDef, GetIdent, StructDef, TypeDef},
|
schema::{EnumDef, GetIdent, StructDef, TypeDef},
|
||||||
};
|
};
|
||||||
|
|
||||||
define_derive! {
|
|
||||||
pub struct DeriveCloneIn;
|
pub struct DeriveCloneIn;
|
||||||
}
|
|
||||||
|
define_derive!(DeriveCloneIn);
|
||||||
|
|
||||||
impl Derive for DeriveCloneIn {
|
impl Derive for DeriveCloneIn {
|
||||||
fn trait_name() -> &'static str {
|
fn trait_name() -> &'static str {
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@ use itertools::Itertools;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
use super::{define_derive, Derive, DeriveOutput};
|
use super::{define_derive, Derive};
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::LateCtx,
|
codegen::LateCtx,
|
||||||
schema::{EnumDef, GetGenerics, StructDef, ToType, TypeDef},
|
schema::{EnumDef, GetGenerics, StructDef, ToType, TypeDef},
|
||||||
util::ToIdent,
|
util::ToIdent,
|
||||||
};
|
};
|
||||||
|
|
||||||
define_derive! {
|
|
||||||
pub struct DeriveContentEq;
|
pub struct DeriveContentEq;
|
||||||
}
|
|
||||||
|
define_derive!(DeriveContentEq);
|
||||||
|
|
||||||
const IGNORE_FIELDS: [(/* field name */ &str, /* field type */ &str); 6] = [
|
const IGNORE_FIELDS: [(/* field name */ &str, /* field type */ &str); 6] = [
|
||||||
("span", "Span"),
|
("span", "Span"),
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@ use itertools::Itertools;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
use super::{define_derive, Derive, DeriveOutput};
|
use super::{define_derive, Derive};
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::LateCtx,
|
codegen::LateCtx,
|
||||||
schema::{EnumDef, GetGenerics, StructDef, ToType, TypeDef},
|
schema::{EnumDef, GetGenerics, StructDef, ToType, TypeDef},
|
||||||
util::ToIdent,
|
util::ToIdent,
|
||||||
};
|
};
|
||||||
|
|
||||||
define_derive! {
|
|
||||||
pub struct DeriveContentHash;
|
pub struct DeriveContentHash;
|
||||||
}
|
|
||||||
|
define_derive!(DeriveContentHash);
|
||||||
|
|
||||||
const IGNORE_FIELD_TYPES: [/* type name */ &str; 4] = [
|
const IGNORE_FIELD_TYPES: [/* type name */ &str; 4] = [
|
||||||
"Span",
|
"Span",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
use super::{define_derive, Derive, DeriveOutput};
|
use super::{define_derive, Derive};
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::LateCtx,
|
codegen::LateCtx,
|
||||||
markers::ESTreeStructAttribute,
|
markers::ESTreeStructAttribute,
|
||||||
|
|
@ -12,9 +12,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
define_derive! {
|
|
||||||
pub struct DeriveESTree;
|
pub struct DeriveESTree;
|
||||||
}
|
|
||||||
|
define_derive!(DeriveESTree);
|
||||||
|
|
||||||
impl Derive for DeriveESTree {
|
impl Derive for DeriveESTree {
|
||||||
fn trait_name() -> &'static str {
|
fn trait_name() -> &'static str {
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@ use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
|
|
||||||
use super::{define_derive, Derive, DeriveOutput};
|
use super::{define_derive, Derive};
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::LateCtx,
|
codegen::LateCtx,
|
||||||
schema::{EnumDef, GetGenerics, StructDef, ToType, TypeDef},
|
schema::{EnumDef, GetGenerics, StructDef, ToType, TypeDef},
|
||||||
util::{ToIdent, TypeWrapper},
|
util::{ToIdent, TypeWrapper},
|
||||||
};
|
};
|
||||||
|
|
||||||
define_derive! {
|
|
||||||
pub struct DeriveGetSpan;
|
pub struct DeriveGetSpan;
|
||||||
}
|
|
||||||
|
define_derive!(DeriveGetSpan);
|
||||||
|
|
||||||
impl Derive for DeriveGetSpan {
|
impl Derive for DeriveGetSpan {
|
||||||
fn trait_name() -> &'static str {
|
fn trait_name() -> &'static str {
|
||||||
|
|
@ -47,9 +47,9 @@ impl Derive for DeriveGetSpan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
define_derive! {
|
|
||||||
pub struct DeriveGetSpanMut;
|
pub struct DeriveGetSpanMut;
|
||||||
}
|
|
||||||
|
define_derive!(DeriveGetSpanMut);
|
||||||
|
|
||||||
impl Derive for DeriveGetSpanMut {
|
impl Derive for DeriveGetSpanMut {
|
||||||
fn trait_name() -> &'static str {
|
fn trait_name() -> &'static str {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
|
use itertools::Itertools;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use crate::{codegen::LateCtx, schema::TypeDef};
|
use crate::{
|
||||||
|
codegen::{generate_header, CodegenBase, LateCtx},
|
||||||
|
schema::TypeDef,
|
||||||
|
Result,
|
||||||
|
};
|
||||||
|
|
||||||
mod clone_in;
|
mod clone_in;
|
||||||
mod content_eq;
|
mod content_eq;
|
||||||
|
|
@ -17,7 +23,12 @@ pub use content_hash::DeriveContentHash;
|
||||||
pub use estree::DeriveESTree;
|
pub use estree::DeriveESTree;
|
||||||
pub use get_span::{DeriveGetSpan, DeriveGetSpanMut};
|
pub use get_span::{DeriveGetSpan, DeriveGetSpanMut};
|
||||||
|
|
||||||
pub trait Derive {
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DeriveOutput(pub Vec<(PathBuf, TokenStream)>);
|
||||||
|
|
||||||
|
pub trait Derive: CodegenBase {
|
||||||
|
// Methods defined by implementer
|
||||||
|
|
||||||
fn trait_name() -> &'static str;
|
fn trait_name() -> &'static str;
|
||||||
|
|
||||||
fn snake_name() -> String {
|
fn snake_name() -> String {
|
||||||
|
|
@ -29,23 +40,11 @@ pub trait Derive {
|
||||||
fn prelude() -> TokenStream {
|
fn prelude() -> TokenStream {
|
||||||
TokenStream::default()
|
TokenStream::default()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DeriveTemplate: Derive {
|
// Standard methods
|
||||||
fn template(module_path: Vec<&str>, impls: TokenStream) -> TokenStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DeriveOutput(pub Vec<(PathBuf, TokenStream)>);
|
|
||||||
|
|
||||||
macro_rules! define_derive {
|
|
||||||
($vis:vis struct $ident:ident $($lifetime:lifetime)? $($rest:tt)*) => {
|
|
||||||
$vis struct $ident $($lifetime)? $($rest)*
|
|
||||||
|
|
||||||
impl $($lifetime)? $crate::derives::DeriveTemplate for $ident $($lifetime)? {
|
|
||||||
fn template(module_paths: Vec<&str>, impls: TokenStream) -> TokenStream {
|
fn template(module_paths: Vec<&str>, impls: TokenStream) -> TokenStream {
|
||||||
use itertools::Itertools;
|
let header = generate_header(Self::file_path());
|
||||||
let header = $crate::codegen::generated_header!();
|
|
||||||
let prelude = Self::prelude();
|
let prelude = Self::prelude();
|
||||||
|
|
||||||
// from `x::y::z` to `crate::y::z::*`
|
// from `x::y::z` to `crate::y::z::*`
|
||||||
|
|
@ -74,23 +73,8 @@ macro_rules! define_derive {
|
||||||
#impls
|
#impls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl $($lifetime)? $crate::codegen::Runner for $ident $($lifetime)? {
|
|
||||||
type Context = $crate::codegen::LateCtx;
|
|
||||||
type Output = $crate::derives::DeriveOutput;
|
|
||||||
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
stringify!($ident)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&mut self, ctx: &$crate::codegen::LateCtx) -> $crate::Result<Self::Output> {
|
|
||||||
use std::vec::Vec;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
|
||||||
|
|
||||||
use $crate::derives::DeriveTemplate;
|
|
||||||
|
|
||||||
|
fn output(&mut self, ctx: &LateCtx) -> Result<DeriveOutput> {
|
||||||
let trait_name = Self::trait_name();
|
let trait_name = Self::trait_name();
|
||||||
let filename = format!("derive_{}.rs", Self::snake_name());
|
let filename = format!("derive_{}.rs", Self::snake_name());
|
||||||
let output = ctx
|
let output = ctx
|
||||||
|
|
@ -98,7 +82,9 @@ macro_rules! define_derive {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|def| def.generates_derive(trait_name))
|
.filter(|def| def.generates_derive(trait_name))
|
||||||
.map(|def| (def, self.derive(def, ctx)))
|
.map(|def| (def, self.derive(def, ctx)))
|
||||||
.fold(FxHashMap::<&str, (FxHashSet<&str>, Vec<TokenStream>)>::default(), |mut acc, (def, stream)| {
|
.fold(
|
||||||
|
FxHashMap::<&str, (FxHashSet<&str>, Vec<TokenStream>)>::default(),
|
||||||
|
|mut acc, (def, stream)| {
|
||||||
let module_path = def.module_path();
|
let module_path = def.module_path();
|
||||||
let krate = module_path.split("::").next().unwrap();
|
let krate = module_path.split("::").next().unwrap();
|
||||||
if !acc.contains_key(krate) {
|
if !acc.contains_key(krate) {
|
||||||
|
|
@ -108,36 +94,64 @@ macro_rules! define_derive {
|
||||||
streams.0.insert(module_path);
|
streams.0.insert(module_path);
|
||||||
streams.1.push(stream);
|
streams.1.push(stream);
|
||||||
acc
|
acc
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.sorted_by(|lhs, rhs| lhs.0.cmp(rhs.0))
|
.sorted_by(|lhs, rhs| lhs.0.cmp(rhs.0))
|
||||||
.fold(Vec::new(), |mut acc, (path, (modules, streams))| {
|
.fold(Vec::new(), |mut acc, (path, (modules, streams))| {
|
||||||
let mut modules = Vec::from_iter(modules);
|
let mut modules = Vec::from_iter(modules);
|
||||||
modules.sort();
|
modules.sort_unstable();
|
||||||
|
|
||||||
acc.push((
|
acc.push((
|
||||||
$crate::output(
|
crate::output(
|
||||||
format!("crates/{}", path.split("::").next().unwrap()).as_str(),
|
format!("crates/{}", path.split("::").next().unwrap()).as_str(),
|
||||||
&filename,
|
&filename,
|
||||||
),
|
),
|
||||||
Self::template(
|
Self::template(
|
||||||
modules,
|
modules,
|
||||||
streams
|
streams.into_iter().fold(TokenStream::new(), |mut acc, it| {
|
||||||
.into_iter()
|
|
||||||
.fold(TokenStream::new(), |mut acc, it| {
|
|
||||||
acc.extend(quote::quote! {
|
acc.extend(quote::quote! {
|
||||||
///@@line_break
|
///@@line_break
|
||||||
});
|
});
|
||||||
acc.extend(it);
|
acc.extend(it);
|
||||||
acc
|
acc
|
||||||
})
|
}),
|
||||||
)
|
),
|
||||||
));
|
));
|
||||||
acc
|
acc
|
||||||
});
|
});
|
||||||
Ok(DeriveOutput(output))
|
Ok(DeriveOutput(output))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! define_derive {
|
||||||
|
($ident:ident $($lifetime:lifetime)?) => {
|
||||||
|
const _: () = {
|
||||||
|
use $crate::{
|
||||||
|
codegen::{CodegenBase, LateCtx, Runner},
|
||||||
|
derives::DeriveOutput,
|
||||||
|
Result,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl $($lifetime)? CodegenBase for $ident $($lifetime)? {
|
||||||
|
fn file_path() -> &'static str {
|
||||||
|
file!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $($lifetime)? Runner for $ident $($lifetime)? {
|
||||||
|
type Context = LateCtx;
|
||||||
|
type Output = DeriveOutput;
|
||||||
|
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
stringify!($ident)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&mut self, ctx: &LateCtx) -> Result<DeriveOutput> {
|
||||||
|
self.output(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub(crate) use define_derive;
|
pub(crate) use define_derive;
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@ use syn::Type;
|
||||||
|
|
||||||
use super::define_generator;
|
use super::define_generator;
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{generated_header, LateCtx},
|
codegen::LateCtx,
|
||||||
output,
|
output,
|
||||||
schema::{FieldDef, ToType, TypeDef},
|
schema::{FieldDef, ToType, TypeDef},
|
||||||
util::ToIdent,
|
util::ToIdent,
|
||||||
Generator, GeneratorOutput,
|
Generator, GeneratorOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
define_generator! {
|
|
||||||
pub struct AssertLayouts;
|
pub struct AssertLayouts;
|
||||||
}
|
|
||||||
|
define_generator!(AssertLayouts);
|
||||||
|
|
||||||
impl Generator for AssertLayouts {
|
impl Generator for AssertLayouts {
|
||||||
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
||||||
|
|
@ -26,13 +26,9 @@ impl Generator for AssertLayouts {
|
||||||
})
|
})
|
||||||
.collect::<(Vec<TokenStream>, Vec<TokenStream>)>();
|
.collect::<(Vec<TokenStream>, Vec<TokenStream>)>();
|
||||||
|
|
||||||
let header = generated_header!();
|
|
||||||
|
|
||||||
GeneratorOutput::Rust {
|
GeneratorOutput::Rust {
|
||||||
path: output(crate::AST_CRATE, "assert_layouts.rs"),
|
path: output(crate::AST_CRATE, "assert_layouts.rs"),
|
||||||
tokens: quote! {
|
tokens: quote! {
|
||||||
#header
|
|
||||||
|
|
||||||
use std::mem::{align_of, offset_of, size_of};
|
use std::mem::{align_of, offset_of, size_of};
|
||||||
|
|
||||||
///@@line_break
|
///@@line_break
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use syn::{parse_quote, Ident, Type};
|
||||||
|
|
||||||
use super::define_generator;
|
use super::define_generator;
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{generated_header, LateCtx},
|
codegen::LateCtx,
|
||||||
output,
|
output,
|
||||||
schema::{
|
schema::{
|
||||||
EnumDef, FieldDef, GetIdent, InheritDef, StructDef, ToType, TypeDef, TypeName, VariantDef,
|
EnumDef, FieldDef, GetIdent, InheritDef, StructDef, ToType, TypeDef, TypeName, VariantDef,
|
||||||
|
|
@ -19,9 +19,9 @@ use crate::{
|
||||||
Generator, GeneratorOutput,
|
Generator, GeneratorOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
define_generator! {
|
|
||||||
pub struct AstBuilderGenerator;
|
pub struct AstBuilderGenerator;
|
||||||
}
|
|
||||||
|
define_generator!(AstBuilderGenerator);
|
||||||
|
|
||||||
impl Generator for AstBuilderGenerator {
|
impl Generator for AstBuilderGenerator {
|
||||||
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
||||||
|
|
@ -32,14 +32,12 @@ impl Generator for AstBuilderGenerator {
|
||||||
.map(|it| generate_builder_fn(it, ctx))
|
.map(|it| generate_builder_fn(it, ctx))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
||||||
let header = generated_header!();
|
|
||||||
|
|
||||||
GeneratorOutput::Rust {
|
GeneratorOutput::Rust {
|
||||||
path: output(crate::AST_CRATE, "ast_builder.rs"),
|
path: output(crate::AST_CRATE, "ast_builder.rs"),
|
||||||
tokens: quote! {
|
tokens: quote! {
|
||||||
//! AST node factories
|
//! AST node factories
|
||||||
#header
|
|
||||||
|
|
||||||
|
//!@@line_break
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::default_trait_access,
|
clippy::default_trait_access,
|
||||||
clippy::too_many_arguments,
|
clippy::too_many_arguments,
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,15 @@ use syn::{parse_quote, Arm, ImplItemFn, Variant};
|
||||||
|
|
||||||
use super::define_generator;
|
use super::define_generator;
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{generated_header, LateCtx},
|
codegen::LateCtx,
|
||||||
output,
|
output,
|
||||||
schema::{GetIdent, ToType},
|
schema::{GetIdent, ToType},
|
||||||
Generator, GeneratorOutput,
|
Generator, GeneratorOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
define_generator! {
|
|
||||||
pub struct AstKindGenerator;
|
pub struct AstKindGenerator;
|
||||||
}
|
|
||||||
|
define_generator!(AstKindGenerator);
|
||||||
|
|
||||||
pub const BLACK_LIST: [&str; 61] = [
|
pub const BLACK_LIST: [&str; 61] = [
|
||||||
"Expression",
|
"Expression",
|
||||||
|
|
@ -125,15 +125,12 @@ impl Generator for AstKindGenerator {
|
||||||
})
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
||||||
let header = generated_header!();
|
|
||||||
|
|
||||||
GeneratorOutput::Rust {
|
GeneratorOutput::Rust {
|
||||||
path: output(crate::AST_CRATE, "ast_kind.rs"),
|
path: output(crate::AST_CRATE, "ast_kind.rs"),
|
||||||
tokens: quote! {
|
tokens: quote! {
|
||||||
#header
|
|
||||||
#![allow(missing_docs)] ///@ FIXME (in ast_tools/src/generators/ast_kind.rs)
|
#![allow(missing_docs)] ///@ FIXME (in ast_tools/src/generators/ast_kind.rs)
|
||||||
///@@line_break
|
|
||||||
|
|
||||||
|
///@@line_break
|
||||||
use oxc_span::{GetSpan, Span};
|
use oxc_span::{GetSpan, Span};
|
||||||
|
|
||||||
///@@line_break
|
///@@line_break
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
use crate::codegen::LateCtx;
|
use crate::{
|
||||||
|
codegen::{generate_header, CodegenBase, LateCtx},
|
||||||
|
Result,
|
||||||
|
};
|
||||||
|
|
||||||
mod assert_layouts;
|
mod assert_layouts;
|
||||||
mod ast_builder;
|
mod ast_builder;
|
||||||
|
|
@ -16,31 +20,62 @@ pub use ast_kind::AstKindGenerator;
|
||||||
pub use typescript::TypescriptGenerator;
|
pub use typescript::TypescriptGenerator;
|
||||||
pub use visit::{VisitGenerator, VisitMutGenerator};
|
pub use visit::{VisitGenerator, VisitMutGenerator};
|
||||||
|
|
||||||
pub trait Generator {
|
|
||||||
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum GeneratorOutput {
|
pub enum GeneratorOutput {
|
||||||
Rust { path: PathBuf, tokens: TokenStream },
|
Rust { path: PathBuf, tokens: TokenStream },
|
||||||
Text { path: PathBuf, content: String },
|
Text { path: PathBuf, content: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Generator: CodegenBase {
|
||||||
|
// Methods defined by implementer
|
||||||
|
|
||||||
|
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput;
|
||||||
|
|
||||||
|
// Standard methods
|
||||||
|
|
||||||
|
fn output(&mut self, ctx: &LateCtx) -> Result<GeneratorOutput> {
|
||||||
|
let mut output = self.generate(ctx);
|
||||||
|
|
||||||
|
if let GeneratorOutput::Rust { tokens, .. } = &mut output {
|
||||||
|
let header = generate_header(Self::file_path());
|
||||||
|
*tokens = quote! {
|
||||||
|
#header
|
||||||
|
#tokens
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! define_generator {
|
macro_rules! define_generator {
|
||||||
($vis:vis struct $ident:ident $($lifetime:lifetime)? $($rest:tt)*) => {
|
($ident:ident $($lifetime:lifetime)?) => {
|
||||||
$vis struct $ident $($lifetime)? $($rest)*
|
const _: () = {
|
||||||
impl $($lifetime)? $crate::codegen::Runner for $ident $($lifetime)? {
|
use $crate::{
|
||||||
type Context = $crate::codegen::LateCtx;
|
codegen::{CodegenBase, LateCtx, Runner},
|
||||||
type Output = $crate::GeneratorOutput;
|
generators::GeneratorOutput,
|
||||||
|
Result,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl $($lifetime)? CodegenBase for $ident $($lifetime)? {
|
||||||
|
fn file_path() -> &'static str {
|
||||||
|
file!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $($lifetime)? Runner for $ident $($lifetime)? {
|
||||||
|
type Context = LateCtx;
|
||||||
|
type Output = GeneratorOutput;
|
||||||
|
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
stringify!($ident)
|
stringify!($ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&mut self, ctx: &$crate::codegen::LateCtx) -> $crate::Result<Self::Output> {
|
fn run(&mut self, ctx: &LateCtx) -> Result<GeneratorOutput> {
|
||||||
Ok(self.generate(ctx))
|
self.output(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
pub(crate) use define_generator;
|
pub(crate) use define_generator;
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ use crate::{
|
||||||
|
|
||||||
const CUSTOM_TYPESCRIPT: &str = include_str!("../../../../crates/oxc_ast/src/ast/types.d.ts");
|
const CUSTOM_TYPESCRIPT: &str = include_str!("../../../../crates/oxc_ast/src/ast/types.d.ts");
|
||||||
|
|
||||||
define_generator! {
|
|
||||||
pub struct TypescriptGenerator;
|
pub struct TypescriptGenerator;
|
||||||
}
|
|
||||||
|
define_generator!(TypescriptGenerator);
|
||||||
|
|
||||||
impl Generator for TypescriptGenerator {
|
impl Generator for TypescriptGenerator {
|
||||||
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use syn::{parse_quote, Ident};
|
||||||
|
|
||||||
use super::define_generator;
|
use super::define_generator;
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{generated_header, LateCtx},
|
codegen::LateCtx,
|
||||||
generators::ast_kind::BLACK_LIST as KIND_BLACK_LIST,
|
generators::ast_kind::BLACK_LIST as KIND_BLACK_LIST,
|
||||||
markers::VisitArg,
|
markers::VisitArg,
|
||||||
output,
|
output,
|
||||||
|
|
@ -18,13 +18,9 @@ use crate::{
|
||||||
Generator, GeneratorOutput,
|
Generator, GeneratorOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
define_generator! {
|
|
||||||
pub struct VisitGenerator;
|
pub struct VisitGenerator;
|
||||||
}
|
|
||||||
|
|
||||||
define_generator! {
|
define_generator!(VisitGenerator);
|
||||||
pub struct VisitMutGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Generator for VisitGenerator {
|
impl Generator for VisitGenerator {
|
||||||
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
||||||
|
|
@ -35,6 +31,10 @@ impl Generator for VisitGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct VisitMutGenerator;
|
||||||
|
|
||||||
|
define_generator!(VisitMutGenerator);
|
||||||
|
|
||||||
impl Generator for VisitMutGenerator {
|
impl Generator for VisitMutGenerator {
|
||||||
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
|
||||||
GeneratorOutput::Rust {
|
GeneratorOutput::Rust {
|
||||||
|
|
@ -45,8 +45,6 @@ impl Generator for VisitMutGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_visit<const MUT: bool>(ctx: &LateCtx) -> TokenStream {
|
fn generate_visit<const MUT: bool>(ctx: &LateCtx) -> TokenStream {
|
||||||
let header = generated_header!();
|
|
||||||
|
|
||||||
let (visits, walks) = VisitBuilder::new(ctx, MUT).build();
|
let (visits, walks) = VisitBuilder::new(ctx, MUT).build();
|
||||||
|
|
||||||
let walk_mod = if MUT { quote!(walk_mut) } else { quote!(walk) };
|
let walk_mod = if MUT { quote!(walk_mut) } else { quote!(walk) };
|
||||||
|
|
@ -72,8 +70,6 @@ fn generate_visit<const MUT: bool>(ctx: &LateCtx) -> TokenStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#header
|
|
||||||
|
|
||||||
//! Visitor Pattern
|
//! Visitor Pattern
|
||||||
//!
|
//!
|
||||||
//! See:
|
//! See:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue