Skip to content

Commit

Permalink
docs(ast, ast_macros, ast_tools): better documentation for Ast help…
Browse files Browse the repository at this point in the history
…er attributes. (#4856)
  • Loading branch information
rzvxa committed Aug 15, 2024
1 parent 90d0b2b commit 47c9552
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 19 deletions.
6 changes: 3 additions & 3 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(...)]` and `#[visit(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in
// `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// NB: `#[span]`, `#[scope(...)]`,`#[visit(...)]` and `#[generate_derive(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// Read [`macro@oxc_ast_macros::ast`] for more information.

// 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/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(...)]` and `#[visit(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in
// `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// NB: `#[span]`, `#[scope(...)]`,`#[visit(...)]` and `#[generate_derive(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// Read [`macro@oxc_ast_macros::ast`] for more information.

// 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(...)]` and `#[visit(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in
// `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// NB: `#[span]`, `#[scope(...)]`,`#[visit(...)]` and `#[generate_derive(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// Read [`macro@oxc_ast_macros::ast`] for more information.

// 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(...)]` and `#[visit(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in
// `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// NB: `#[span]`, `#[scope(...)]`,`#[visit(...)]` and `#[generate_derive(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
// Read [`macro@oxc_ast_macros::ast`] for more information.

// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]
Expand Down
67 changes: 62 additions & 5 deletions crates/oxc_ast_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn assert_generated_derives(attrs: &[syn::Attribute]) -> TokenStream2 {
}

// NOTE: At this level we don't care if a trait is derived multiple times, It is the
// responsibility of the codegen to raise errors for those.
// responsibility of the `ast_tools` to raise errors for those.
let assertion =
attrs.iter().filter(|attr| attr.path().is_ident("generate_derive")).flat_map(parse).map(
|derive| {
Expand All @@ -70,14 +70,70 @@ fn assert_generated_derives(attrs: &[syn::Attribute]) -> TokenStream2 {
}

/// This attribute serves two purposes.
/// First, it is a marker for our codegen to detect AST types.
/// First, it is a marker for our `ast_tools` to detect 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
/// * 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.
///
/// # Generator Attributes:
///
/// ## `#[scope(...)]`:
///
/// This attribute can be used in 2 places:
/// ### On `struct`/`enum` items:
/// 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.
/// 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.
///
/// ## `#[visit(...)]`:
///
/// 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.
///
/// ## `#[span]`:
///
/// This attribute can be used to hint to the `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.
///
/// # Derive Helper Attributes:
///
/// 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`
#[proc_macro_attribute]
#[allow(clippy::missing_panics_doc)]
pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {
Expand All @@ -104,9 +160,10 @@ 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]`, `#[visit]`, and other attrs in the AST node type defs.
/// These "marker" attributes are used in codegen.
#[proc_macro_derive(Ast, attributes(scope, visit, span, serde, tsify, generate_derive, clone_in))]
/// The only purpose is to allow the occurrence of helper attributes used with the `tasks/ast_tools`.
///
/// Read [`macro@ast`] for further details.
#[proc_macro_derive(Ast, attributes(scope, visit, span, generate_derive, clone_in, serde, tsify))]
pub fn ast_derive(_item: TokenStream) -> TokenStream {
TokenStream::new()
}
Expand Down
4 changes: 2 additions & 2 deletions tasks/ast_tools/src/markers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ pub struct ScopeMarkers {
pub enter_before: bool,
}

/// A struct representing the `#[scope(...)]` attribute.
/// A struct representing all the helper attributes that might be used with `#[generate_derive(...)]`
#[derive(Debug, Default, Serialize)]
pub struct DeriveAttributes {
pub clone_in: CloneInAttribute,
}

/// A enum representing the value passed in `#[clone_in(...)]` derive attribute.
/// A enum representing the value passed in `#[clone_in(...)]` derive helper attribute.
#[derive(Debug, Default, Serialize)]
pub enum CloneInAttribute {
#[default]
Expand Down

0 comments on commit 47c9552

Please sign in to comment.