refactor(traverse): move generate_binding to TraverseScoping (#6831)

Follow-up after #6830.

Now that `generate_binding` doesn't need access to `AstBuilder`, it can move into `TraverseScoping`.

Occasionally this is helpful when you need to borrows 2 parts of `TraverseCtx` simultaneously. e.g.:

```rs
// This fails to compile because we try to mutably borrow `TraverseCtx`
// while it's already borrowed
if let Ancestor::ProgramBody(body) = ctx.parent() {
    //                               ^^^ immutable borrow
    let binding = ctx.generate_binding(name, scope_id, flags);
    //            ^^^ mutable borrow
}

// Borrow-checker allows this because we borrow fields of `TraverseCtx` separately
if let Ancestor::ProgramBody(body) = ctx.ancestry.parent() {
    let binding = ctx.scoping.generate_binding(name, scope_id, flags);
}
```
This commit is contained in:
overlookmotel 2024-10-24 06:19:39 +00:00
parent 3a56d59dce
commit 3b99fe6d59
2 changed files with 39 additions and 17 deletions

View file

@ -304,36 +304,28 @@ impl<'a> TraverseCtx<'a> {
/// Generate binding.
///
/// Creates a symbol with the provided name and flags and adds it to the specified scope.
///
/// This is a shortcut for `ctx.scoping.generate_binding`.
pub fn generate_binding(
&mut self,
name: Atom<'a>,
scope_id: ScopeId,
flags: SymbolFlags,
) -> BoundIdentifier<'a> {
let owned_name = name.to_compact_str();
// Add binding to scope
let symbol_id = self.symbols_mut().create_symbol(
SPAN,
owned_name.clone(),
flags,
scope_id,
NodeId::DUMMY,
);
self.scopes_mut().add_binding(scope_id, owned_name, symbol_id);
BoundIdentifier::new(name, symbol_id)
self.scoping.generate_binding(name, scope_id, flags)
}
/// Generate binding in current scope.
///
/// Creates a symbol with the provided name and flags and adds it to the current scope.
///
/// This is a shortcut for `ctx.scoping.generate_in_current_scope`.
pub fn generate_in_current_scope(
&mut self,
name: Atom<'a>,
flags: SymbolFlags,
) -> BoundIdentifier<'a> {
self.generate_binding(name, self.current_scope_id(), flags)
self.scoping.generate_in_current_scope(name, flags)
}
/// Generate UID var name.

View file

@ -7,14 +7,14 @@ use rustc_hash::FxHashSet;
#[allow(clippy::wildcard_imports)]
use oxc_ast::{ast::*, visit::Visit};
use oxc_semantic::{NodeId, Reference, ScopeTree, SymbolTable};
use oxc_span::CompactStr;
use oxc_span::{CompactStr, SPAN};
use oxc_syntax::{
reference::{ReferenceFlags, ReferenceId},
scope::{ScopeFlags, ScopeId},
symbol::SymbolId,
symbol::{SymbolFlags, SymbolId},
};
use crate::scopes_collector::ChildScopeCollector;
use crate::{scopes_collector::ChildScopeCollector, BoundIdentifier};
/// Traverse scope context.
///
@ -165,6 +165,36 @@ impl TraverseScoping {
self.scopes.delete_scope(scope_id);
}
/// Generate binding.
///
/// Creates a symbol with the provided name and flags and adds it to the specified scope.
pub fn generate_binding<'a>(
&mut self,
name: Atom<'a>,
scope_id: ScopeId,
flags: SymbolFlags,
) -> BoundIdentifier<'a> {
let owned_name = name.to_compact_str();
// Add binding to scope
let symbol_id =
self.symbols.create_symbol(SPAN, owned_name.clone(), flags, scope_id, NodeId::DUMMY);
self.scopes.add_binding(scope_id, owned_name, symbol_id);
BoundIdentifier::new(name, symbol_id)
}
/// Generate binding in current scope.
///
/// Creates a symbol with the provided name and flags and adds it to the current scope.
pub fn generate_in_current_scope<'a>(
&mut self,
name: Atom<'a>,
flags: SymbolFlags,
) -> BoundIdentifier<'a> {
self.generate_binding(name, self.current_scope_id, flags)
}
/// Generate UID var name.
///
/// Finds a unique variable name which does clash with any other variables used in the program.