From 47c9552ecf26b8502cbd53bc221076c2f1a2d51d Mon Sep 17 00:00:00 2001 From: rzvxa <3788964+rzvxa@users.noreply.github.com> Date: Thu, 15 Aug 2024 11:32:35 +0000 Subject: [PATCH] docs(ast, ast_macros, ast_tools): better documentation for `Ast` helper attributes. (#4856) --- crates/oxc_ast/src/ast/js.rs | 6 +-- crates/oxc_ast/src/ast/jsx.rs | 6 +-- crates/oxc_ast/src/ast/literal.rs | 6 +-- crates/oxc_ast/src/ast/ts.rs | 6 +-- crates/oxc_ast_macros/src/lib.rs | 67 ++++++++++++++++++++++++++++--- tasks/ast_tools/src/markers.rs | 4 +- 6 files changed, 76 insertions(+), 19 deletions(-) diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index f7a58a56ec196..d0687258cddb7 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -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)] diff --git a/crates/oxc_ast/src/ast/jsx.rs b/crates/oxc_ast/src/ast/jsx.rs index 87d31509c8ce7..e4e82d8bc2e4c 100644 --- a/crates/oxc_ast/src/ast/jsx.rs +++ b/crates/oxc_ast/src/ast/jsx.rs @@ -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)] diff --git a/crates/oxc_ast/src/ast/literal.rs b/crates/oxc_ast/src/ast/literal.rs index 5ee834378aabe..5678461b51c18 100644 --- a/crates/oxc_ast/src/ast/literal.rs +++ b/crates/oxc_ast/src/ast/literal.rs @@ -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)] diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index 52f9e5815f6cd..b50cdb93ceba6 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -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)] diff --git a/crates/oxc_ast_macros/src/lib.rs b/crates/oxc_ast_macros/src/lib.rs index e1d9a9234fb93..6a711592cf435 100644 --- a/crates/oxc_ast_macros/src/lib.rs +++ b/crates/oxc_ast_macros/src/lib.rs @@ -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| { @@ -70,7 +70,7 @@ 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 @@ -78,6 +78,62 @@ fn assert_generated_derives(attrs: &[syn::Attribute]) -> TokenStream2 { /// * 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 { @@ -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() } diff --git a/tasks/ast_tools/src/markers.rs b/tasks/ast_tools/src/markers.rs index 584d40934095b..12bcd23723971 100644 --- a/tasks/ast_tools/src/markers.rs +++ b/tasks/ast_tools/src/markers.rs @@ -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]