diff --git a/crates/oxc_traverse/scripts/lib/ancestor.mjs b/crates/oxc_traverse/scripts/lib/ancestor.mjs index fb9929c56bdacb..98f817703a9b88 100644 --- a/crates/oxc_traverse/scripts/lib/ancestor.mjs +++ b/crates/oxc_traverse/scripts/lib/ancestor.mjs @@ -32,16 +32,16 @@ export default function generateAncestorsCode(types) { if (otherField === field) continue; methodsCode += ` - #[inline] - pub fn ${otherField.rawName}(self) -> &'t ${otherField.rawTypeName} { - unsafe { - &*( - (self.0 as *const u8).add(${otherField.offsetVarName}) - as *const ${otherField.rawTypeName} - ) - } - } - `; + #[inline] + pub fn ${otherField.rawName}(self) -> &'t ${otherField.rawTypeName} { + unsafe { + &*( + (self.0 as *const u8).add(${otherField.offsetVarName}) + as *const ${otherField.rawTypeName} + ) + } + } + `; } const fieldNameCamel = snakeToCamel(field.name), @@ -49,17 +49,17 @@ export default function generateAncestorsCode(types) { structName = `${type.name}Without${fieldNameCamel}${lifetimes}`; thisAncestorTypes += ` - #[repr(transparent)] - #[derive(Clone, Copy, Debug)] - pub struct ${structName}( - pub(crate) *const ${type.rawName}, - pub(crate) PhantomData<&'t ()>, - ); - - impl${lifetimes} ${structName} { - ${methodsCode} - } - `; + #[repr(transparent)] + #[derive(Clone, Copy, Debug)] + pub struct ${structName}( + pub(crate) *const ${type.rawName}, + pub(crate) PhantomData<&'t ()>, + ); + + impl${lifetimes} ${structName} { + ${methodsCode} + } + `; const variantName = `${type.name}${fieldNameCamel}`; variantNames.push(variantName); @@ -76,85 +76,85 @@ export default function generateAncestorsCode(types) { if (variantNames.length > 0) { ancestorTypes += ` - ${offsetCode} - ${thisAncestorTypes} - `; + ${offsetCode} + ${thisAncestorTypes} + `; isFunctions += ` - #[inline] - pub fn is_${typeSnakeName}(self) -> bool { - matches!(self, ${variantNames.map(name => `Self::${name}(_)`).join(' | ')}) - } - `; + #[inline] + pub fn is_${typeSnakeName}(self) -> bool { + matches!(self, ${variantNames.map(name => `Self::${name}(_)`).join(' | ')}) + } + `; } } for (const [typeName, variantNames] of Object.entries(variantNamesForEnums)) { isFunctions += ` - #[inline] - pub fn is_via_${camelToSnake(typeName)}(self) -> bool { - matches!(self, ${variantNames.map(name => `Self::${name}(_)`).join(' | ')}) - } - `; + #[inline] + pub fn is_via_${camelToSnake(typeName)}(self) -> bool { + matches!(self, ${variantNames.map(name => `Self::${name}(_)`).join(' | ')}) + } + `; } return ` - #![allow( - unsafe_code, - clippy::missing_safety_doc, - clippy::ptr_as_ptr, - clippy::undocumented_unsafe_blocks, - clippy::cast_ptr_alignment - )] - - use std::{cell::Cell, marker::PhantomData}; - - use memoffset::offset_of; - - use oxc_allocator::{Box, Vec}; - #[allow(clippy::wildcard_imports)] - use oxc_ast::ast::*; - use oxc_syntax::scope::ScopeId; - - /// Type of [\`Ancestor\`]. - /// Used in [\`crate::TraverseCtx::retag_stack\`]. - #[repr(u16)] - #[derive(Clone, Copy)] - #[allow(dead_code)] - pub(crate) enum AncestorType { - None = 0, - ${ancestorTypeEnumVariants} - } + #![allow( + unsafe_code, + clippy::missing_safety_doc, + clippy::ptr_as_ptr, + clippy::undocumented_unsafe_blocks, + clippy::cast_ptr_alignment + )] + + use std::{cell::Cell, marker::PhantomData}; + + use memoffset::offset_of; + + use oxc_allocator::{Box, Vec}; + #[allow(clippy::wildcard_imports)] + use oxc_ast::ast::*; + use oxc_syntax::scope::ScopeId; + + /// Type of [\`Ancestor\`]. + /// Used in [\`crate::TraverseCtx::retag_stack\`]. + #[repr(u16)] + #[derive(Clone, Copy)] + #[allow(dead_code)] + pub(crate) enum AncestorType { + None = 0, + ${ancestorTypeEnumVariants} + } - /// Ancestor type used in AST traversal. - /// - /// Encodes both the type of the parent, and child's location in the parent. - /// i.e. variants for \`BinaryExpressionLeft\` and \`BinaryExpressionRight\`, not just \`BinaryExpression\`. - /// - /// \`'a\` is lifetime of AST nodes. - /// \`'t\` is lifetime of the \`Ancestor\` (which inherits lifetime from \`&'t TraverseCtx'\`). - /// i.e. \`Ancestor\`s can only exist within the body of \`enter_*\` and \`exit_*\` methods - /// and cannot "escape" from them. - // - // SAFETY: - // * This type must be \`#[repr(u16)]\`. - // * Variant discriminants must correspond to those in \`AncestorType\`. - // - // These invariants make it possible to set the discriminant of an \`Ancestor\` without altering - // the "payload" pointer with: - // \`*(ancestor as *mut _ as *mut AncestorType) = AncestorType::Program\`. - // \`TraverseCtx::retag_stack\` uses this technique. - #[repr(C, u16)] - #[derive(Clone, Copy, Debug)] - pub enum Ancestor<'a, 't> { - None = AncestorType::None as u16, - ${ancestorEnumVariants} - } + /// Ancestor type used in AST traversal. + /// + /// Encodes both the type of the parent, and child's location in the parent. + /// i.e. variants for \`BinaryExpressionLeft\` and \`BinaryExpressionRight\`, not just \`BinaryExpression\`. + /// + /// \`'a\` is lifetime of AST nodes. + /// \`'t\` is lifetime of the \`Ancestor\` (which inherits lifetime from \`&'t TraverseCtx'\`). + /// i.e. \`Ancestor\`s can only exist within the body of \`enter_*\` and \`exit_*\` methods + /// and cannot "escape" from them. + // + // SAFETY: + // * This type must be \`#[repr(u16)]\`. + // * Variant discriminants must correspond to those in \`AncestorType\`. + // + // These invariants make it possible to set the discriminant of an \`Ancestor\` without altering + // the "payload" pointer with: + // \`*(ancestor as *mut _ as *mut AncestorType) = AncestorType::Program\`. + // \`TraverseCtx::retag_stack\` uses this technique. + #[repr(C, u16)] + #[derive(Clone, Copy, Debug)] + pub enum Ancestor<'a, 't> { + None = AncestorType::None as u16, + ${ancestorEnumVariants} + } - impl<'a, 't> Ancestor<'a, 't> { - ${isFunctions} - } + impl<'a, 't> Ancestor<'a, 't> { + ${isFunctions} + } - ${ancestorTypes} - `; + ${ancestorTypes} + `; } diff --git a/crates/oxc_traverse/scripts/lib/scopes_collector.mjs b/crates/oxc_traverse/scripts/lib/scopes_collector.mjs index 8798e5cc9704db..3813674a06f214 100644 --- a/crates/oxc_traverse/scripts/lib/scopes_collector.mjs +++ b/crates/oxc_traverse/scripts/lib/scopes_collector.mjs @@ -7,44 +7,44 @@ export default function generateScopesCollectorCode(types) { const extraParams = type.scopeArgs.flags === 'flags' ? ', _flags: ScopeFlags' : ''; methods += ` - #[inline] - fn visit_${camelToSnake(type.name)}(&mut self, it: &${type.rawName}${extraParams}) { - self.add_scope(&it.scope_id); - } - `; + #[inline] + fn visit_${camelToSnake(type.name)}(&mut self, it: &${type.rawName}${extraParams}) { + self.add_scope(&it.scope_id); + } + `; } return ` - use std::cell::Cell; - - #[allow(clippy::wildcard_imports)] - use oxc_ast::{ast::*, visit::Visit}; - use oxc_syntax::scope::{ScopeFlags, ScopeId}; - - /// Visitor that locates all child scopes. - /// NB: Child scopes only, not grandchild scopes. - /// Does not do full traversal - stops each time it hits a node with a scope. - pub(crate) struct ChildScopeCollector { - pub(crate) scope_ids: Vec, - } - - impl ChildScopeCollector { - pub(crate) fn new() -> Self { - Self { scope_ids: vec![] } - } - - pub(crate) fn add_scope(&mut self, scope_id: &Cell>) { - self.scope_ids.push(scope_id.get().unwrap()); - } - } - - impl<'a> Visit<'a> for ChildScopeCollector { - ${methods} - - #[inline] - fn visit_finally_clause(&mut self, it: &BlockStatement<'a>) { - self.add_scope(&it.scope_id); - } - } - `; + use std::cell::Cell; + + #[allow(clippy::wildcard_imports)] + use oxc_ast::{ast::*, visit::Visit}; + use oxc_syntax::scope::{ScopeFlags, ScopeId}; + + /// Visitor that locates all child scopes. + /// NB: Child scopes only, not grandchild scopes. + /// Does not do full traversal - stops each time it hits a node with a scope. + pub(crate) struct ChildScopeCollector { + pub(crate) scope_ids: Vec, + } + + impl ChildScopeCollector { + pub(crate) fn new() -> Self { + Self { scope_ids: vec![] } + } + + pub(crate) fn add_scope(&mut self, scope_id: &Cell>) { + self.scope_ids.push(scope_id.get().unwrap()); + } + } + + impl<'a> Visit<'a> for ChildScopeCollector { + ${methods} + + #[inline] + fn visit_finally_clause(&mut self, it: &BlockStatement<'a>) { + self.add_scope(&it.scope_id); + } + } + `; } diff --git a/crates/oxc_traverse/scripts/lib/traverse.mjs b/crates/oxc_traverse/scripts/lib/traverse.mjs index 088846d5c5805d..f82c4d24965966 100644 --- a/crates/oxc_traverse/scripts/lib/traverse.mjs +++ b/crates/oxc_traverse/scripts/lib/traverse.mjs @@ -8,23 +8,23 @@ export default function generateTraverseTraitCode(types) { for (const type of typesArr) { const snakeName = camelToSnake(type.name); traverseMethods += ` - #[inline] - fn enter_${snakeName}(&mut self, node: &mut ${type.rawName}, ctx: &mut TraverseCtx<'a>) {} - #[inline] - fn exit_${snakeName}(&mut self, node: &mut ${type.rawName}, ctx: &mut TraverseCtx<'a>) {} - `; + #[inline] + fn enter_${snakeName}(&mut self, node: &mut ${type.rawName}, ctx: &mut TraverseCtx<'a>) {} + #[inline] + fn exit_${snakeName}(&mut self, node: &mut ${type.rawName}, ctx: &mut TraverseCtx<'a>) {} + `; } return ` - use oxc_allocator::Vec; - #[allow(clippy::wildcard_imports)] - use oxc_ast::ast::*; + use oxc_allocator::Vec; + #[allow(clippy::wildcard_imports)] + use oxc_ast::ast::*; - use crate::TraverseCtx; + use crate::TraverseCtx; - #[allow(unused_variables)] - pub trait Traverse<'a> { - ${traverseMethods} - } - `; + #[allow(unused_variables)] + pub trait Traverse<'a> { + ${traverseMethods} + } + `; } diff --git a/crates/oxc_traverse/scripts/lib/walk.mjs b/crates/oxc_traverse/scripts/lib/walk.mjs index fadc0be1447d4e..e3f72126546fc7 100644 --- a/crates/oxc_traverse/scripts/lib/walk.mjs +++ b/crates/oxc_traverse/scripts/lib/walk.mjs @@ -12,38 +12,38 @@ export default function generateWalkFunctionsCode(types) { } return ` - #![allow( - unsafe_code, - clippy::missing_safety_doc, - clippy::missing_panics_doc, - clippy::undocumented_unsafe_blocks, - clippy::semicolon_if_nothing_returned, - clippy::cast_ptr_alignment - )] + #![allow( + unsafe_code, + clippy::missing_safety_doc, + clippy::missing_panics_doc, + clippy::undocumented_unsafe_blocks, + clippy::semicolon_if_nothing_returned, + clippy::cast_ptr_alignment + )] - use std::{cell::Cell, marker::PhantomData}; + use std::{cell::Cell, marker::PhantomData}; - use oxc_allocator::Vec; - #[allow(clippy::wildcard_imports)] - use oxc_ast::ast::*; - use oxc_syntax::scope::ScopeId; + use oxc_allocator::Vec; + #[allow(clippy::wildcard_imports)] + use oxc_ast::ast::*; + use oxc_syntax::scope::ScopeId; - use crate::{ancestor::{self, AncestorType}, Ancestor, Traverse, TraverseCtx}; + use crate::{ancestor::{self, AncestorType}, Ancestor, Traverse, TraverseCtx}; - ${walkMethods} + ${walkMethods} - pub(crate) unsafe fn walk_statements<'a, Tr: Traverse<'a>>( - traverser: &mut Tr, - stmts: *mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a> - ) { - traverser.enter_statements(&mut *stmts, ctx); - for stmt in (*stmts).iter_mut() { - walk_statement(traverser, stmt, ctx); - } - traverser.exit_statements(&mut *stmts, ctx); - } - `; + pub(crate) unsafe fn walk_statements<'a, Tr: Traverse<'a>>( + traverser: &mut Tr, + stmts: *mut Vec<'a, Statement<'a>>, + ctx: &mut TraverseCtx<'a> + ) { + traverser.enter_statements(&mut *stmts, ctx); + for stmt in (*stmts).iter_mut() { + walk_statement(traverser, stmt, ctx); + } + traverser.exit_statements(&mut *stmts, ctx); + } + `; } function generateWalkForStruct(type, types) { @@ -77,9 +77,9 @@ function generateWalkForStruct(type, types) { // Visitor should not do that though, so maybe it's OK. // In final version, we should not make `scope_id` fields `Cell`s to prevent this. enterScopeCode = ` - let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id((*(${makeFieldCode(scopeIdField)})).get().unwrap()); - `; + let previous_scope_id = ctx.current_scope_id(); + ctx.set_current_scope_id((*(${makeFieldCode(scopeIdField)})).get().unwrap()); + `; exitScopeCode = `ctx.set_current_scope_id(previous_scope_id);`; } @@ -91,12 +91,12 @@ function generateWalkForStruct(type, types) { let tagCode = '', retagCode = ''; if (index === 0) { tagCode = ` - let pop_token = ctx.push_stack( - Ancestor::${type.name}${fieldCamelName}( - ancestor::${type.name}Without${fieldCamelName}(node, PhantomData) - ) - ); - `; + let pop_token = ctx.push_stack( + Ancestor::${type.name}${fieldCamelName}( + ancestor::${type.name}Without${fieldCamelName}(node, PhantomData) + ) + ); + `; } else { retagCode = `ctx.retag_stack(AncestorType::${type.name}${fieldCamelName});`; } @@ -111,10 +111,10 @@ function generateWalkForStruct(type, types) { walkCode = `walk_statements(traverser, std::ptr::from_mut(field), ctx);`; } else { walkCode = ` - for item in field.iter_mut() { - ${fieldWalkName}(traverser, std::ptr::from_mut(item), ctx); - } - `.trim(); + for item in field.iter_mut() { + ${fieldWalkName}(traverser, std::ptr::from_mut(item), ctx); + } + `.trim(); } } else if (field.wrappers.length === 2 && field.wrappers[1] === 'Box') { walkCode = `${fieldWalkName}(traverser, std::ptr::from_mut(&mut **field), ctx);`; @@ -124,13 +124,13 @@ function generateWalkForStruct(type, types) { } return ` - ${scopeCode} - ${tagCode} - if let Some(field) = &mut *(${fieldCode}) { - ${retagCode} - ${walkCode} - } - `; + ${scopeCode} + ${tagCode} + if let Some(field) = &mut *(${fieldCode}) { + ${retagCode} + ${walkCode} + } + `; } if (field.wrappers[0] === 'Vec') { @@ -150,51 +150,51 @@ function generateWalkForStruct(type, types) { ); } walkVecCode = ` - for item in (*(${fieldCode})).iter_mut()${iterModifier} { - ${walkCode} - } - `.trim(); + for item in (*(${fieldCode})).iter_mut()${iterModifier} { + ${walkCode} + } + `.trim(); } return ` - ${scopeCode} - ${tagCode || retagCode} - ${walkVecCode} - `; + ${scopeCode} + ${tagCode || retagCode} + ${walkVecCode} + `; } if (field.wrappers.length === 1 && field.wrappers[0] === 'Box') { return ` - ${scopeCode} - ${tagCode || retagCode} - ${fieldWalkName}(traverser, std::ptr::from_mut(&mut **(${fieldCode})), ctx); - `; + ${scopeCode} + ${tagCode || retagCode} + ${fieldWalkName}(traverser, std::ptr::from_mut(&mut **(${fieldCode})), ctx); + `; } assert(field.wrappers.length === 0, `Cannot handle struct field with type: ${field.type}`); return ` - ${scopeCode} - ${tagCode || retagCode} - ${fieldWalkName}(traverser, ${fieldCode}, ctx); - `; + ${scopeCode} + ${tagCode || retagCode} + ${fieldWalkName}(traverser, ${fieldCode}, ctx); + `; }); if (visitedFields.length > 0) fieldsCodes.push('ctx.pop_stack(pop_token);'); const typeSnakeName = camelToSnake(type.name); return ` - pub(crate) unsafe fn walk_${typeSnakeName}<'a, Tr: Traverse<'a>>( - traverser: &mut Tr, - node: *mut ${type.rawName}, - ctx: &mut TraverseCtx<'a> - ) { - traverser.enter_${typeSnakeName}(&mut *node, ctx); - ${fieldsCodes.join('\n')} - ${exitScopeCode} - traverser.exit_${typeSnakeName}(&mut *node, ctx); - } - `.replace(/\n\s*\n+/g, '\n'); + pub(crate) unsafe fn walk_${typeSnakeName}<'a, Tr: Traverse<'a>>( + traverser: &mut Tr, + node: *mut ${type.rawName}, + ctx: &mut TraverseCtx<'a> + ) { + traverser.enter_${typeSnakeName}(&mut *node, ctx); + ${fieldsCodes.join('\n')} + ${exitScopeCode} + traverser.exit_${typeSnakeName}(&mut *node, ctx); + } + `.replace(/\n\s*\n+/g, '\n'); } function makeFieldCode(field) { @@ -245,16 +245,16 @@ function generateWalkForEnum(type, types) { const typeSnakeName = camelToSnake(type.name); return ` - pub(crate) unsafe fn walk_${typeSnakeName}<'a, Tr: Traverse<'a>>( - traverser: &mut Tr, - node: *mut ${type.rawName}, - ctx: &mut TraverseCtx<'a> - ) { - traverser.enter_${typeSnakeName}(&mut *node, ctx); - match &mut *node { - ${variantCodes.join('\n')} - } - traverser.exit_${typeSnakeName}(&mut *node, ctx); - } - `; + pub(crate) unsafe fn walk_${typeSnakeName}<'a, Tr: Traverse<'a>>( + traverser: &mut Tr, + node: *mut ${type.rawName}, + ctx: &mut TraverseCtx<'a> + ) { + traverser.enter_${typeSnakeName}(&mut *node, ctx); + match &mut *node { + ${variantCodes.join('\n')} + } + traverser.exit_${typeSnakeName}(&mut *node, ctx); + } + `; }