From 72a37fc02a387bedd1726e0651c70e49f7eac000 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:02:47 +0000 Subject: [PATCH] feat(traverse): support `clone_identifier_reference` method in `TraverseCtx` (#4880) related: #4804 needs from: #4876 The `clone_identifier_reference` method is used to clone an `IdentifierReference` and create a `Reference` and insert it to `SymbolTable`'s `resolved_references`. The reason we need this is because we need to make sure that `IdentifierReference`'s `reference_id` is unique --- crates/oxc_traverse/src/context/mod.rs | 15 +++++++++++++++ crates/oxc_traverse/src/context/scoping.rs | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/crates/oxc_traverse/src/context/mod.rs b/crates/oxc_traverse/src/context/mod.rs index f99e57bb1..e629a442f 100644 --- a/crates/oxc_traverse/src/context/mod.rs +++ b/crates/oxc_traverse/src/context/mod.rs @@ -379,6 +379,21 @@ impl<'a> TraverseCtx<'a> { ) -> ReferenceId { self.scoping.create_reference_in_current_scope(name, flag) } + + /// Clone `IdentifierReference` based on the original reference's `SymbolId` and name. + /// + /// This method makes a lookup of the `SymbolId` for the reference. If you need to create multiple + /// `IdentifierReference`s for the same binding, it is better to look up the `SymbolId` only once, + /// and generate `IdentifierReference`s with `TraverseCtx::create_reference_id`. + /// + /// This is a shortcut for `ctx.scoping.clone_identifier_reference`. + pub fn clone_identifier_reference( + &mut self, + ident: &IdentifierReference<'a>, + flag: ReferenceFlag, + ) -> IdentifierReference<'a> { + self.scoping.clone_identifier_reference(ident, flag) + } } // Methods used internally within crate diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index 4a4d2ef80..b4ecbfe2a 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -326,6 +326,24 @@ impl TraverseScoping { let symbol_id = self.scopes.find_binding(self.current_scope_id, name.as_str()); self.create_reference(name, symbol_id, flag) } + + /// Clone `IdentifierReference` based on the original reference's `SymbolId` and name. + /// + /// This method makes a lookup of the `SymbolId` for the reference. If you need to create multiple + /// `IdentifierReference`s for the same binding, it is better to look up the `SymbolId` only once, + /// and generate `IdentifierReference`s with `TraverseScoping::create_reference_id`. + pub fn clone_identifier_reference<'a>( + &mut self, + ident: &IdentifierReference<'a>, + flag: ReferenceFlag, + ) -> IdentifierReference<'a> { + let reference = + self.symbols().get_reference(ident.reference_id.get().unwrap_or_else(|| { + unreachable!("IdentifierReference must have a reference_id"); + })); + let symbol_id = reference.symbol_id(); + self.create_reference_id(ident.span, ident.name.clone(), symbol_id, flag) + } } // Methods used internally within crate