diff --git a/crates/oxc_ast/src/ast_builder_impl.rs b/crates/oxc_ast/src/ast_builder_impl.rs index 86101045ceb4a..47d98436579ce 100644 --- a/crates/oxc_ast/src/ast_builder_impl.rs +++ b/crates/oxc_ast/src/ast_builder_impl.rs @@ -4,6 +4,7 @@ clippy::too_many_arguments, clippy::unused_self, )] +#![warn(missing_docs)] use std::mem; @@ -27,26 +28,33 @@ impl<'a, T> FromIn<'a, NONE> for Option> { } impl<'a> AstBuilder<'a> { + /// Create a new AST builder that will allocate nodes in the given allocator. #[inline] pub fn new(allocator: &'a Allocator) -> Self { Self { allocator } } + /// Move a value into the memory arena. #[inline] pub fn alloc(self, value: T) -> Box<'a, T> { Box::new_in(value, self.allocator) } + /// Create a new empty [`Vec`] that stores its elements in the memory arena. #[inline] pub fn vec(self) -> Vec<'a, T> { Vec::new_in(self.allocator) } + /// Create a new empty [`Vec`] that stores its elements in the memory arena. + /// Enough memory will be pre-allocated to store at least `capacity` + /// elements. #[inline] pub fn vec_with_capacity(self, capacity: usize) -> Vec<'a, T> { Vec::with_capacity_in(capacity, self.allocator) } + /// Create a new arena-allocated [`Vec`] initialized with a single element. #[inline] pub fn vec1(self, value: T) -> Vec<'a, T> { let mut vec = self.vec_with_capacity(1); @@ -54,16 +62,20 @@ impl<'a> AstBuilder<'a> { vec } + /// Collect an iterator into a new arena-allocated [`Vec`]. #[inline] pub fn vec_from_iter>(self, iter: I) -> Vec<'a, T> { Vec::from_iter_in(iter, self.allocator) } + /// Move a string slice into the memory arena, returning a reference to the slice + /// in the heap. #[inline] pub fn str(self, value: &str) -> &'a str { String::from_str_in(value, self.allocator).into_bump_str() } + /// Allocate an [`Atom`] from a string slice. #[inline] pub fn atom(self, value: &str) -> Atom<'a> { Atom::from(String::from_str_in(value, self.allocator).into_bump_str()) @@ -80,19 +92,24 @@ impl<'a> AstBuilder<'a> { unsafe { std::mem::transmute_copy(src) } } - /// Moves the expression out by replacing it with a null expression. + /// Moves the expression out by replacing it with a [null + /// expression](Expression::NullLiteral). #[inline] pub fn move_expression(self, expr: &mut Expression<'a>) -> Expression<'a> { let null_expr = self.expression_null_literal(expr.span()); mem::replace(expr, null_expr) } + /// Moves the statement out by replacing it with an [empty + /// statement](Statement::EmptyStatement). #[inline] pub fn move_statement(self, stmt: &mut Statement<'a>) -> Statement<'a> { let empty_stmt = self.empty_statement(stmt.span()); mem::replace(stmt, Statement::EmptyStatement(self.alloc(empty_stmt))) } + /// Moves the assignment target out by replacing it with a dummy target with + /// no name and an empty [`Span`]. #[inline] pub fn move_assignment_target(self, target: &mut AssignmentTarget<'a>) -> AssignmentTarget<'a> { let dummy = @@ -100,6 +117,8 @@ impl<'a> AstBuilder<'a> { mem::replace(target, dummy.into()) } + /// Move a declaration out by replacing it with an empty [variable + /// declaration](Declaration::VariableDeclaration). #[inline] pub fn move_declaration(self, decl: &mut Declaration<'a>) -> Declaration<'a> { let empty_decl = self.variable_declaration( @@ -112,6 +131,8 @@ impl<'a> AstBuilder<'a> { mem::replace(decl, empty_decl) } + /// Move a variable declaration out by replacing it with an empty [variable + /// declaration](VariableDeclaration). #[inline] pub fn move_variable_declaration( self, @@ -126,6 +147,8 @@ impl<'a> AstBuilder<'a> { mem::replace(decl, empty_decl) } + /// Move an array element out by replacing it with an + /// [elision](ArrayExpressionElement::Elision). pub fn move_array_expression_element( self, element: &mut ArrayExpressionElement<'a>, @@ -134,6 +157,8 @@ impl<'a> AstBuilder<'a> { mem::replace(element, empty_element) } + /// Take the contents of a arena-allocated [`Vec`], leaving an empty vec in + /// its place. This is akin to [`std::mem::take`]. #[inline] pub fn move_vec(self, vec: &mut Vec<'a, T>) -> Vec<'a, T> { mem::replace(vec, self.vec()) @@ -160,6 +185,8 @@ impl<'a> AstBuilder<'a> { /* ---------- Functions ---------- */ + /// Create a [`FormalParameter`] with no type annotations, modifiers, + /// decorators, or initializer. #[inline] pub fn plain_formal_parameter( self, @@ -169,6 +196,8 @@ impl<'a> AstBuilder<'a> { self.formal_parameter(span, self.vec(), pattern, None, false, false) } + /// Create a [`Function`] with no "extras", i.e. decorators, type + /// annotations, accessibility modifiers, etc. #[inline] pub fn plain_function( self, @@ -195,6 +224,7 @@ impl<'a> AstBuilder<'a> { /* ---------- Modules ---------- */ + /// Create an empty [`ExportNamedDeclaration`] with no modifiers #[inline] pub fn plain_export_named_declaration_declaration( self, @@ -211,6 +241,8 @@ impl<'a> AstBuilder<'a> { )) } + /// Create an [`ExportNamedDeclaration`] with no modifiers that contains a + /// set of [exported symbol names](ExportSpecifier). #[inline] pub fn plain_export_named_declaration( self, @@ -230,6 +262,8 @@ impl<'a> AstBuilder<'a> { /* ---------- TypeScript ---------- */ + /// Create a [`TSInterfaceHeritage`] that extends from the given list of + /// other interfaces. #[inline] pub fn ts_interface_heritages( self, @@ -245,11 +279,13 @@ impl<'a> AstBuilder<'a> { ) } + /// Create an [`JSXOpeningElement`]. #[inline] pub fn jsx_opening_fragment(self, span: Span) -> JSXOpeningFragment { JSXOpeningFragment { span } } + /// Create an [`JSXClosingElement`]. #[inline] pub fn jsx_closing_fragment(self, span: Span) -> JSXClosingFragment { JSXClosingFragment { span } diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index 1d7bc61edb260..c8391480b8b6f 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -1,3 +1,4 @@ +//! AST node factories // Auto-generated code, DO NOT EDIT DIRECTLY! // To edit this generated file you have to edit `tasks/ast_tools/src/generators/ast_builder.rs` @@ -6,6 +7,7 @@ clippy::too_many_arguments, clippy::fn_params_excessive_bools )] +#![warn(missing_docs)] use oxc_allocator::{Allocator, Box, IntoIn, Vec}; @@ -15,6 +17,7 @@ use crate::ast::*; /// AST builder for creating AST nodes #[derive(Clone, Copy)] pub struct AstBuilder<'a> { + /// The memory allocator used to allocate AST nodes in the arena. pub allocator: &'a Allocator, } @@ -1484,6 +1487,7 @@ impl<'a> AstBuilder<'a> { Expression::TSInstantiationExpression(inner.into_in(self.allocator)) } + /// Convert a [`MemberExpression`] into the corresponding variant of [`Expression`] without copying or re-allocating memory. #[inline] pub fn expression_member(self, inner: MemberExpression<'a>) -> Expression<'a> { Expression::from(inner) @@ -1725,6 +1729,7 @@ impl<'a> AstBuilder<'a> { ArrayExpressionElement::Elision(inner.into_in(self.allocator)) } + /// Convert a [`Expression`] into the corresponding variant of [`ArrayExpressionElement`] without copying or re-allocating memory. #[inline] pub fn array_expression_element_expression( self, @@ -1964,6 +1969,7 @@ impl<'a> AstBuilder<'a> { PropertyKey::PrivateIdentifier(inner.into_in(self.allocator)) } + /// Convert a [`Expression`] into the corresponding variant of [`PropertyKey`] without copying or re-allocating memory. #[inline] pub fn property_key_expression(self, inner: Expression<'a>) -> PropertyKey<'a> { PropertyKey::from(inner) @@ -2509,6 +2515,7 @@ impl<'a> AstBuilder<'a> { Argument::SpreadElement(inner.into_in(self.allocator)) } + /// Convert a [`Expression`] into the corresponding variant of [`Argument`] without copying or re-allocating memory. #[inline] pub fn argument_expression(self, inner: Expression<'a>) -> Argument<'a> { Argument::from(inner) @@ -2790,6 +2797,7 @@ impl<'a> AstBuilder<'a> { Box::new_in(self.assignment_expression(span, operator, left, right), self.allocator) } + /// Convert a [`SimpleAssignmentTarget`] into the corresponding variant of [`AssignmentTarget`] without copying or re-allocating memory. #[inline] pub fn assignment_target_simple( self, @@ -2798,6 +2806,7 @@ impl<'a> AstBuilder<'a> { AssignmentTarget::from(inner) } + /// Convert a [`AssignmentTargetPattern`] into the corresponding variant of [`AssignmentTarget`] without copying or re-allocating memory. #[inline] pub fn assignment_target_assignment_target_pattern( self, @@ -3006,6 +3015,7 @@ impl<'a> AstBuilder<'a> { SimpleAssignmentTarget::TSInstantiationExpression(inner.into_in(self.allocator)) } + /// Convert a [`MemberExpression`] into the corresponding variant of [`SimpleAssignmentTarget`] without copying or re-allocating memory. #[inline] pub fn simple_assignment_target_member_expression( self, @@ -3226,6 +3236,7 @@ impl<'a> AstBuilder<'a> { AssignmentTargetMaybeDefault::AssignmentTargetWithDefault(inner.into_in(self.allocator)) } + /// Convert a [`AssignmentTarget`] into the corresponding variant of [`AssignmentTargetMaybeDefault`] without copying or re-allocating memory. #[inline] pub fn assignment_target_maybe_default_assignment_target( self, @@ -3556,6 +3567,7 @@ impl<'a> AstBuilder<'a> { ChainElement::CallExpression(inner.into_in(self.allocator)) } + /// Convert a [`MemberExpression`] into the corresponding variant of [`ChainElement`] without copying or re-allocating memory. #[inline] pub fn chain_element_member_expression(self, inner: MemberExpression<'a>) -> ChainElement<'a> { ChainElement::from(inner) @@ -4054,11 +4066,13 @@ impl<'a> AstBuilder<'a> { Statement::WithStatement(inner.into_in(self.allocator)) } + /// Convert a [`Declaration`] into the corresponding variant of [`Statement`] without copying or re-allocating memory. #[inline] pub fn statement_declaration(self, inner: Declaration<'a>) -> Statement<'a> { Statement::from(inner) } + /// Convert a [`ModuleDeclaration`] into the corresponding variant of [`Statement`] without copying or re-allocating memory. #[inline] pub fn statement_module_declaration(self, inner: ModuleDeclaration<'a>) -> Statement<'a> { Statement::from(inner) @@ -4832,6 +4846,7 @@ impl<'a> AstBuilder<'a> { ForStatementInit::VariableDeclaration(inner.into_in(self.allocator)) } + /// Convert a [`Expression`] into the corresponding variant of [`ForStatementInit`] without copying or re-allocating memory. #[inline] pub fn for_statement_init_expression(self, inner: Expression<'a>) -> ForStatementInit<'a> { ForStatementInit::from(inner) @@ -4911,6 +4926,7 @@ impl<'a> AstBuilder<'a> { ForStatementLeft::VariableDeclaration(inner.into_in(self.allocator)) } + /// Convert a [`AssignmentTarget`] into the corresponding variant of [`ForStatementLeft`] without copying or re-allocating memory. #[inline] pub fn for_statement_left_assignment_target( self, @@ -7866,6 +7882,7 @@ impl<'a> AstBuilder<'a> { ExportDefaultDeclarationKind::TSInterfaceDeclaration(inner.into_in(self.allocator)) } + /// Convert a [`Expression`] into the corresponding variant of [`ExportDefaultDeclarationKind`] without copying or re-allocating memory. #[inline] pub fn export_default_declaration_kind_expression( self, @@ -8183,6 +8200,7 @@ impl<'a> AstBuilder<'a> { TSEnumMemberName::StaticNumericLiteral(inner.into_in(self.allocator)) } + /// Convert a [`Expression`] into the corresponding variant of [`TSEnumMemberName`] without copying or re-allocating memory. #[inline] pub fn ts_enum_member_name_expression(self, inner: Expression<'a>) -> TSEnumMemberName<'a> { TSEnumMemberName::from(inner) @@ -9879,6 +9897,7 @@ impl<'a> AstBuilder<'a> { TSTupleElement::TSRestType(inner.into_in(self.allocator)) } + /// Convert a [`TSType`] into the corresponding variant of [`TSTupleElement`] without copying or re-allocating memory. #[inline] pub fn ts_tuple_element_type(self, inner: TSType<'a>) -> TSTupleElement<'a> { TSTupleElement::from(inner) @@ -11755,6 +11774,7 @@ impl<'a> AstBuilder<'a> { TSTypeQueryExprName::TSImportType(inner.into_in(self.allocator)) } + /// Convert a [`TSTypeName`] into the corresponding variant of [`TSTypeQueryExprName`] without copying or re-allocating memory. #[inline] pub fn ts_type_query_expr_name_type_name( self, @@ -12383,6 +12403,7 @@ impl<'a> AstBuilder<'a> { TSModuleReference::ExternalModuleReference(inner.into_in(self.allocator)) } + /// Convert a [`TSTypeName`] into the corresponding variant of [`TSModuleReference`] without copying or re-allocating memory. #[inline] pub fn ts_module_reference_type_name(self, inner: TSTypeName<'a>) -> TSModuleReference<'a> { TSModuleReference::from(inner) @@ -13212,6 +13233,7 @@ impl<'a> AstBuilder<'a> { JSXExpression::EmptyExpression(inner.into_in(self.allocator)) } + /// Convert a [`Expression`] into the corresponding variant of [`JSXExpression`] without copying or re-allocating memory. #[inline] pub fn jsx_expression_expression(self, inner: Expression<'a>) -> JSXExpression<'a> { JSXExpression::from(inner) diff --git a/tasks/ast_tools/src/generators/ast_builder.rs b/tasks/ast_tools/src/generators/ast_builder.rs index bed05974b80a7..f90b51f1d81b7 100644 --- a/tasks/ast_tools/src/generators/ast_builder.rs +++ b/tasks/ast_tools/src/generators/ast_builder.rs @@ -37,6 +37,7 @@ impl Generator for AstBuilderGenerator { GeneratorOutput::Rust { path: output(crate::AST_CRATE, "ast_builder.rs"), tokens: quote! { + //! AST node factories #header #![allow( @@ -44,6 +45,7 @@ impl Generator for AstBuilderGenerator { clippy::too_many_arguments, clippy::fn_params_excessive_bools, )] + #![warn(missing_docs)] ///@@line_break use oxc_allocator::{Allocator, Box, IntoIn, Vec}; @@ -56,6 +58,7 @@ impl Generator for AstBuilderGenerator { /// AST builder for creating AST nodes #[derive(Clone, Copy)] pub struct AstBuilder<'a> { + /// The memory allocator used to allocate AST nodes in the arena. pub allocator: &'a Allocator, } @@ -121,8 +124,14 @@ fn generate_enum_inherit_builder_fn( let fn_name = enum_builder_name(enum_ident.to_string(), inherit.super_.name().inner_name().to_string()); + let docs = DocComment::new(format!( + "Convert a [`{}`] into the corresponding variant of [`{}`] without copying or re-allocating memory.", + inherit.super_.name(), + enum_ident + )); quote! { ///@@line_break + #docs #[inline] pub fn #fn_name(self, inner: #super_type) -> #enum_as_type { #enum_ident::from(inner) diff --git a/tasks/ast_tools/src/schema/mod.rs b/tasks/ast_tools/src/schema/mod.rs index fc7df13766558..802d26cfdfee2 100644 --- a/tasks/ast_tools/src/schema/mod.rs +++ b/tasks/ast_tools/src/schema/mod.rs @@ -1,3 +1,5 @@ +use std::fmt; + use quote::ToTokens; use rustc_hash::FxHashSet; use serde::Serialize; @@ -86,6 +88,18 @@ impl<'a> From> for TypeName { } } } +impl fmt::Display for TypeName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Ident(it) => write!(f, "{it}"), + Self::Vec(it) => write!(f, "Vec<{it}>"), + Self::Box(it) => write!(f, "Box<{it}>"), + Self::Opt(it) => write!(f, "Option<{it}>"), + Self::Ref(it) => write!(f, "&{it}"), + Self::Complex(it) => write!(f, "{it}"), + } + } +} #[derive(Debug, Default, serde::Serialize)] pub struct Schema {