Skip to content

Commit

Permalink
docs(ast_tools): update and reformat docs for #[ast] proc macro (#7436
Browse files Browse the repository at this point in the history
)

Docs for `#[ast]` macro were out of date.
  • Loading branch information
overlookmotel committed Nov 23, 2024
1 parent cf0b3bc commit bc0e8bc
Showing 1 changed file with 41 additions and 47 deletions.
88 changes: 41 additions & 47 deletions crates/oxc_ast_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,74 +4,68 @@ use syn::{parse_macro_input, Item};
mod ast;

/// This attribute serves two purposes.
/// First, it is a marker for our `ast_tools` to detect AST types.
/// First, it is a marker for `ast_tools`, to understand AST types.
/// Secondly, it generates the following code:
///
/// * Prepend `#[repr(C)]` to structs
/// * Prepend `#[repr(C, u8)]` to fieldful enums e.g. `enum E { X: u32, Y: u8 }`
/// * Prepend `#[repr(u8)]` to unit (fieldless) enums e.g. `enum E { X, Y, Z, }`
/// * Prepend `#[derive(oxc_ast_macros::Ast)]` to all structs and enums
/// * Prepend `#[repr(C)]` to structs.
/// * Prepend `#[repr(C, u8)]` to fieldful enums e.g. `enum E { X: u32, Y: u8 }`.
/// * Prepend `#[repr(u8)]` to unit (fieldless) enums e.g. `enum E { X, Y, Z, }`.
/// * Prepend `#[derive(oxc_ast_macros::Ast)]` to all structs and enums.
/// * Add assertions that traits used in `#[generate_derive(...)]` are in scope.
///
/// It also allows the usage of these helper attributes via deriving a "no-op" derive macro.
/// It allows the usage of these helper attributes via deriving the `Ast` no-op derive macro:
///
/// # Generator Attributes:
/// # Generator Attributes
///
/// ## `#[scope(...)]`:
/// ## `#[scope(...)]`
///
/// This attribute can be used in 2 places:
/// ### On `struct`/`enum` items:
///
/// ### On `struct`s / `enum`s
/// When this attribute comes before an AST type definition it accepts 3 optional arguments.
/// 1. `flags(expr)`: It accepts an expression that would evaluate to `ScopeFlags`. It is used to annotate scope flags of the AST type.
/// 1. `flags(expr)`: It accepts an expression that would evaluate to `ScopeFlags`.
/// It is used to annotate scope flags of the AST type.
/// 2. `if(expr)`: It accepts an expression that would evaluate to `bool` used for conditional scope creation.
/// 3. `strict_if(expr)`: It accepts an expression that would evaluate to `bool`, If this value is `true` the created scope would be `strict`.
///
/// NOTE: All these expressions can use `self` to access the current node they are getting executed on via an immutable reference.
///
/// ### On `struct` fields:
/// At this position this attribute can only have one shape: `#[scope(enter_before)]`.
/// It marks where `Visit::enter_scope` events should be fired for this AST type.
/// 3. `strict_if(expr)`: It accepts an expression that would evaluate to `bool`.
/// If this value is `true` the created scope would be `strict`.
///
/// ## `#[visit(...)]`:
/// NOTE: All these expressions can use `self` to access the current node they are getting executed on
/// via an immutable reference.
///
/// This attribute can only occur on `struct` fields, Or `enum` attributes.
/// It accepts 4 optional arguments.
/// 1. `as(ident)`: It accepts an identifier, our generators would treat the type of this field/variant as if they were called as the given identifier.
/// 2. `args(arg = expr)`: It accepts an argument name and an expression. Currently it only
/// accepts one argument.
/// a. `args(flags = expr)`: `expr` is an expression that would evaluate to `ScopeFlags`, This argument can only be used at places where the AST type is `Function`.
/// 3. `enter_before`: It marks where this AST type should fire `Visit::enter_node` events.
/// 4. `ignore`: It would ignore this field/variant in visits.
/// ### On `struct` fields
/// At this position this attribute can only have one shape: `#[scope(enter_before)]` / `#[scope(exit_before)]`.
/// It marks where `Visit::enter_scope` and `Visit::exit_scope` events should be fired for this AST type.
///
/// ## `#[span]`:
/// ## `#[visit(args(arg = expr))]`
/// This attribute can only occur on `struct` fields, or `enum` variants.
/// Accepts an argument name and an expression.
/// `expr` is an expression that would evaluate to `ScopeFlags`.
/// This argument can only be used at places where the AST type is `Function`.
///
/// This attribute can be used to hint to the `ast_tools` which field should be used to obtain the span of this AST type.
/// ## `#[span]`
/// This attribute can be used to hint to `ast_tools` which field should be used to obtain the span
/// of this AST type.
///
/// ## `#[generate_derive(...)]`
///
/// This attribute has the same spirit as the `#[derive(...)]` macro, It is used to derive traits for the types.
/// However, Instead of expanding the derive at compile-time, We do this process on PR submits via `ast_tools` code generation.
/// These derived implementations would be output in the `crates/oxc_ast/src/generated` directory.
///
/// ## `#[ts]`:
///
/// This attribute has the same purpose as Rust's `#[derive(...)]` macro.
/// It is used to derive traits for the types.
/// However, instead of expanding the derive at compile-time, we generate the derived code at build time
/// via `ast_tools` code generation.
/// These derived implementations are output as `src/generated/derive_*.rs` in the crate the type is
/// defined in.
///
/// ## `#[ts]`
/// Marks a struct field as only relevant for TypeScript ASTs.
///
/// # Derive Helper Attributes:
/// # Derive Helper Attributes
///
/// These are helper attributes that are only meaningful when their respective trait is derived via `generate_derive`.
/// These are helper attributes that are only meaningful when their respective trait is derived
/// via `generate_derive`.
///
/// ## `#[clone_in(default)]`
///
/// This attribute is only used by `CloneIn` derive.
/// `struct` fields marked with this attribute at cloning will use the `Default::default()` value instead of `CloneIn::clone_in` to initialize.
///
/// # Mocked attributes:
///
/// These are just here to remove the need for boilerplate `#[cfg_attr(...)]`. If their actual trait is derived they would consume these, Otherwise, Our mock attributes will prevent compile errors.
///
/// 1. `serde`
/// 2. `tsify`
/// `struct` fields marked with this attribute at cloning will use the `Default::default()` value
/// instead of `CloneIn::clone_in` to initialize.
#[proc_macro_attribute]
pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as Item);
Expand All @@ -82,7 +76,7 @@ pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {
/// Dummy derive macro for a non-existent trait `Ast`.
///
/// Does not generate any code.
/// The only purpose is to allow the occurrence of helper attributes used with the `tasks/ast_tools`.
/// Its only purpose is to allow the occurrence of helper attributes used in `tasks/ast_tools`.
///
/// Read [`macro@ast`] for further details.
#[proc_macro_derive(Ast, attributes(scope, visit, span, generate_derive, clone_in, estree, ts))]
Expand Down

0 comments on commit bc0e8bc

Please sign in to comment.