Skip to content

Commit

Permalink
refactor(ast_codegen): better visit marker parsing.
Browse files Browse the repository at this point in the history
  • Loading branch information
rzvxa committed Jul 20, 2024
1 parent 69ed7c5 commit 2d4d1e0
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 194 deletions.
24 changes: 12 additions & 12 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// NB: `#[span]`, `#[scope(...)]`, `#[visit(...)]`, `#[visit_as(...)]` and `#[visit_args(...)]` do
// not do anything to the code, They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in that crate.
// NB: `#[span]`, `#[scope(...)]` and `#[visit(...)]` do NOT do anything to the code,
// They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in those crates.

// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]
Expand Down Expand Up @@ -79,7 +79,7 @@ pub enum Expression<'a> {
ChainExpression(Box<'a, ChainExpression<'a>>) = 16,
ClassExpression(Box<'a, Class<'a>>) = 17,
ConditionalExpression(Box<'a, ConditionalExpression<'a>>) = 18,
#[visit_args(flags = ScopeFlags::Function)]
#[visit(args(flags = ScopeFlags::Function))]
FunctionExpression(Box<'a, Function<'a>>) = 19,
ImportExpression(Box<'a, ImportExpression<'a>>) = 20,
LogicalExpression(Box<'a, LogicalExpression<'a>>) = 21,
Expand Down Expand Up @@ -252,7 +252,7 @@ pub enum ArrayExpressionElement<'a> {
/// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas#arrays>
Elision(Elision) = 65,
// `Expression` variants added here by `inherit_variants!` macro
// TODO: support for attributes syntax here so we can use `#[visit_as(ExpressionArrayElement)]`
// TODO: support for attributes syntax here so we can use `#[visit(alias(ExpressionArrayElement))]`
@inherit Expression
}
}
Expand Down Expand Up @@ -972,7 +972,7 @@ pub struct BlockStatement<'a> {
#[cfg_attr(feature = "serialize", serde(untagged))]
pub enum Declaration<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 32,
#[visit_args(flags = ScopeFlags::Function)]
#[visit(args(flags = ScopeFlags::Function))]
FunctionDeclaration(Box<'a, Function<'a>>) = 33,
ClassDeclaration(Box<'a, Class<'a>>) = 34,
UsingDeclaration(Box<'a, UsingDeclaration<'a>>) = 35,
Expand Down Expand Up @@ -1298,7 +1298,7 @@ pub struct TryStatement<'a> {
pub span: Span,
pub block: Box<'a, BlockStatement<'a>>,
pub handler: Option<Box<'a, CatchClause<'a>>>,
#[visit_as(FinallyClause)]
#[visit(alias(FinallyClause))]
pub finalizer: Option<Box<'a, BlockStatement<'a>>>,
}

Expand Down Expand Up @@ -1440,7 +1440,7 @@ pub struct BindingRestElement<'a> {
/// Function Definitions
#[ast(visit)]
#[scope(
// `flags` passed in to visitor via parameter defined by `#[visit_args(flags = ...)]` on parents
// `flags` passed in to visitor via parameter defined by `#[visit(args(flags = ...))]` on parents
flags(flags),
strict_if(self.is_strict()),
)]
Expand Down Expand Up @@ -1597,7 +1597,7 @@ pub struct Class<'a> {
pub id: Option<BindingIdentifier<'a>>,
#[scope(enter_before)]
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
#[visit_as(ClassHeritage)]
#[visit(alias(ClassHeritage))]
pub super_class: Option<Expression<'a>>,
pub super_type_parameters: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
pub implements: Option<Vec<'a, TSClassImplements<'a>>>,
Expand Down Expand Up @@ -1647,12 +1647,12 @@ pub struct MethodDefinition<'a> {
pub span: Span,
pub decorators: Vec<'a, Decorator<'a>>,
pub key: PropertyKey<'a>,
#[visit_args(flags = match self.kind {
#[visit(args(flags = match self.kind {
MethodDefinitionKind::Get => ScopeFlags::Function | ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::Function | ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Function | ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::Function,
})]
}))]
pub value: Box<'a, Function<'a>>, // FunctionExpression
pub kind: MethodDefinitionKind,
pub computed: bool,
Expand Down Expand Up @@ -1968,7 +1968,7 @@ inherit_variants! {
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(untagged))]
pub enum ExportDefaultDeclarationKind<'a> {
#[visit_args(flags = ScopeFlags::Function)]
#[visit(args(flags = ScopeFlags::Function))]
FunctionDeclaration(Box<'a, Function<'a>>) = 64,
ClassDeclaration(Box<'a, Class<'a>>) = 65,

Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_ast/src/ast/jsx.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! [JSX](https://facebook.github.io/jsx)
// NB: `#[span]`, `#[scope(...)]`, `#[visit(...)]`, `#[visit_as(...)]` and `#[visit_args(...)]` do
// not do anything to the code, They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in that crate.
// NB: `#[span]`, `#[scope(...)]` and `#[visit(...)]` do NOT do anything to the code,
// They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in those crates.

// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_ast/src/ast/literal.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Literals
// NB: `#[span]`, `#[scope(...)]`, `#[visit(...)]`, `#[visit_as(...)]` and `#[visit_args(...)]` do
// not do anything to the code, They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in that crate.
// NB: `#[span]`, `#[scope(...)]` and `#[visit(...)]` do NOT do anything to the code,
// They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in those crates.

// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
//! [AST Spec](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/ast-spec)
//! [Archived TypeScript spec](https://github.com/microsoft/TypeScript/blob/3c99d50da5a579d9fa92d02664b1b66d4ff55944/doc/spec-ARCHIVED.md)
// NB: `#[span]`, `#[scope(...)]`, `#[visit(...)]`, `#[visit_as(...)]` and `#[visit_args(...)]` do
// not do anything to the code, They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in that crate.
// NB: `#[span]`, `#[scope(...)]` and `#[visit(...)]` do NOT do anything to the code,
// They are purely markers for codegen used in
// `tasts/ast_codegen` and `crates/oxc_traverse/scripts`. See docs in those crates.

// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_ast_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::str::FromStr;
/// Macro does not generate any code - it's purely a means to communicate information to the codegen.
///
/// Only thing macro does is add `#[derive(Ast)]` to the item.
/// Deriving `Ast` does nothing, but supports the `#[scope]` attr on struct fields.
/// Deriving `Ast` does nothing, but supports the `#[scope]` and `#[visit]` attrs on struct fields.
/// This is a workaround for Rust not supporting helper attributes for `proc_macro_attribute` macros,
/// so we need to use a derive macro to get that support.
///
Expand All @@ -21,8 +21,8 @@ pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {

/// Dummy derive macro for a non-existent trait `Ast`.
///
/// Does not generate any code, only purpose is to allow using `#[scope]` attr in the type def.
#[proc_macro_derive(Ast, attributes(span, scope, visit, visit_as, visit_args))]
/// Does not generate any code, only purpose is to allow using `#[scope]` and `#[visit]` attrs in the type def.
#[proc_macro_derive(Ast, attributes(span, scope, visit))]
pub fn ast_derive(_item: TokenStream) -> TokenStream {
TokenStream::new()
}
43 changes: 19 additions & 24 deletions tasks/ast_codegen/src/generators/ast_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use itertools::Itertools;
use quote::quote;
use syn::{parse_quote, Arm, Ident, Type, Variant};

use crate::{schema::RType, util::TypeExt, CodegenCtx, Generator, GeneratorOutput, TypeRef};
use crate::{
markers::get_visit_markers, schema::RType, util::TypeExt, CodegenCtx, Generator,
GeneratorOutput, TypeRef,
};

use super::generated_header;

Expand Down Expand Up @@ -91,35 +94,27 @@ pub fn process_types(ty: &TypeRef) -> Vec<(Ident, Type)> {
.item
.variants
.iter()
.filter_map(|it| {
it.attrs
.iter()
.find(|it| it.path().is_ident("visit_as"))
.map(|attr| (it, attr))
.map(|(it, attr)| {
assert!(
it.fields.len() == 1,
"visit_as only supports single argument fields."
);
let field = it.fields.iter().next().unwrap();
let type_name = field.ty.get_ident().inner_ident();
(attr.parse_args().unwrap(), parse_quote!(#type_name<'a>))
})
.map(|it| (it, get_visit_markers(&it.attrs).transpose().unwrap()))
.filter(|(_, markers)| markers.as_ref().is_some_and(|mk| mk.visit_as.is_some()))
.filter_map(|(it, markers)| {
markers.map(|markers| {
let field = it.fields.iter().next().unwrap();
let type_name = field.ty.get_ident().inner_ident();
(markers.visit_as.expect("Already checked"), parse_quote!(#type_name<'a>))
})
})
.collect_vec(),
RType::Struct(struct_) => struct_
.item
.fields
.iter()
.filter_map(|it| {
it.attrs
.iter()
.find(|it| it.path().is_ident("visit_as"))
.map(|attr| (it, attr))
.map(|(field, attr)| {
let type_name = field.ty.get_ident().inner_ident();
(attr.parse_args().unwrap(), parse_quote!(#type_name<'a>))
})
.map(|it| (it, get_visit_markers(&it.attrs).transpose().unwrap()))
.filter(|(_, markers)| markers.as_ref().is_some_and(|mk| mk.visit_as.is_some()))
.filter_map(|(field, markers)| {
markers.map(|markers| {
let type_name = field.ty.get_ident().inner_ident();
(markers.visit_as.expect("Already checked"), parse_quote!(#type_name<'a>))
})
})
.collect_vec(),
_ => panic!(),
Expand Down
Loading

0 comments on commit 2d4d1e0

Please sign in to comment.