Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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