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
31 changes: 26 additions & 5 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use oxc_cfg::{
IterationInstructionKind, ReturnInstructionKind,
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_index::{index_vec, IndexVec};
use oxc_span::{CompactStr, SourceType, Span};
use oxc_syntax::{module_record::ModuleRecord, operator::AssignmentOperator};

Expand All @@ -22,7 +23,7 @@ use crate::{
module_record::ModuleRecordBuilder,
node::{AstNode, AstNodeId, AstNodes, NodeFlags},
reference::{Reference, ReferenceFlag, ReferenceId},
scope::{ScopeFlags, ScopeId, ScopeTree},
scope::{ScopeFlags, ScopeId, ScopeTree, UnresolvedReferences},
symbol::{SymbolFlags, SymbolId, SymbolTable},
JSDocFinder, Semantic,
};
Expand Down Expand Up @@ -65,6 +66,9 @@ pub struct SemanticBuilder<'a> {
pub nodes: AstNodes<'a>,
pub scope: ScopeTree,
pub symbols: SymbolTable,
/// NOTE(lucab): lazy vector, always access this through the
/// `unresolved_references_by_scope()` helper.
unresolved_references: IndexVec<ScopeId, UnresolvedReferences>,

pub(crate) module_record: Arc<ModuleRecord>,

Expand Down Expand Up @@ -108,6 +112,7 @@ impl<'a> SemanticBuilder<'a> {
nodes: AstNodes::default(),
scope,
symbols: SymbolTable::default(),
unresolved_references: index_vec![UnresolvedReferences::default()],
module_record: Arc::new(ModuleRecord::default()),
label_builder: LabelBuilder::default(),
build_jsdoc: false,
Expand Down Expand Up @@ -174,6 +179,8 @@ impl<'a> SemanticBuilder<'a> {
checker::check_module_record(&self);
}
}
self.scope.root_unresolved_references =
self.unresolved_references.swap_remove(self.scope.root_scope_id());

let jsdoc = if self.build_jsdoc { self.jsdoc.build() } else { JSDocFinder::default() };

Expand Down Expand Up @@ -317,7 +324,11 @@ impl<'a> SemanticBuilder<'a> {
pub fn declare_reference(&mut self, reference: Reference) -> ReferenceId {
let reference_name = reference.name().clone();
let reference_id = self.symbols.create_reference(reference);
self.scope.add_unresolved_reference(self.current_scope_id, reference_name, reference_id);

self.unresolved_references_by_scope(self.current_scope_id)
.entry(reference_name)
.or_default()
.push(reference_id);
reference_id
}

Expand All @@ -340,8 +351,7 @@ impl<'a> SemanticBuilder<'a> {

fn resolve_references_for_current_scope(&mut self) {
let all_references = self
.scope
.unresolved_references_mut(self.current_scope_id)
.unresolved_references_by_scope(self.current_scope_id)
.drain()
.collect::<Vec<(_, Vec<_>)>>();

Expand All @@ -360,7 +370,10 @@ impl<'a> SemanticBuilder<'a> {
}
self.symbols.resolved_references[symbol_id].extend(reference_ids);
} else {
self.scope.extend_unresolved_reference(parent_scope_id, name, reference_ids);
self.unresolved_references_by_scope(parent_scope_id)
.entry(name)
.or_default()
.extend(reference_ids);
}
}

Expand Down Expand Up @@ -392,6 +405,14 @@ impl<'a> SemanticBuilder<'a> {
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
}
}

fn unresolved_references_by_scope(&mut self, scope_id: ScopeId) -> &mut UnresolvedReferences {
let min_new_len = scope_id + 1;
if self.unresolved_references.len() < min_new_len {
self.unresolved_references.resize_with(min_new_len.into(), Default::default);
}
&mut self.unresolved_references[scope_id]
}
}

impl<'a> Visit<'a> for SemanticBuilder<'a> {
Expand Down
34 changes: 4 additions & 30 deletions crates/oxc_semantic/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{reference::ReferenceId, symbol::SymbolId, AstNodeId};
type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;

type Bindings = FxIndexMap<CompactStr, SymbolId>;
type UnresolvedReferences = FxHashMap<CompactStr, Vec<ReferenceId>>;
pub(crate) type UnresolvedReferences = FxHashMap<CompactStr, Vec<ReferenceId>>;

/// Scope Tree
///
Expand All @@ -27,7 +27,7 @@ pub struct ScopeTree {
node_ids: FxHashMap<ScopeId, AstNodeId>,
flags: IndexVec<ScopeId, ScopeFlags>,
bindings: IndexVec<ScopeId, Bindings>,
unresolved_references: IndexVec<ScopeId, UnresolvedReferences>,
pub(crate) root_unresolved_references: UnresolvedReferences,
}

impl ScopeTree {
Expand Down Expand Up @@ -88,7 +88,7 @@ impl ScopeTree {
}

pub fn root_unresolved_references(&self) -> &UnresolvedReferences {
&self.unresolved_references[self.root_scope_id()]
&self.root_unresolved_references
}

pub fn get_flags(&self, scope_id: ScopeId) -> ScopeFlags {
Expand Down Expand Up @@ -142,7 +142,7 @@ impl ScopeTree {
}

pub fn add_root_unresolved_reference(&mut self, name: CompactStr, reference_id: ReferenceId) {
self.add_unresolved_reference(self.root_scope_id(), name, reference_id);
self.root_unresolved_references.entry(name).or_default().push(reference_id);
}

pub fn has_binding(&self, scope_id: ScopeId, name: &str) -> bool {
Expand Down Expand Up @@ -184,7 +184,6 @@ impl ScopeTree {
let scope_id = self.parent_ids.push(parent_id);
_ = self.flags.push(flags);
_ = self.bindings.push(Bindings::default());
_ = self.unresolved_references.push(UnresolvedReferences::default());

if let Some(parent_id) = parent_id {
self.child_ids.entry(parent_id).or_default().push(scope_id);
Expand All @@ -204,29 +203,4 @@ impl ScopeTree {
pub fn remove_binding(&mut self, scope_id: ScopeId, name: &CompactStr) {
self.bindings[scope_id].shift_remove(name);
}

pub(crate) fn add_unresolved_reference(
&mut self,
scope_id: ScopeId,
name: CompactStr,
reference_id: ReferenceId,
) {
self.unresolved_references[scope_id].entry(name).or_default().push(reference_id);
}

pub(crate) fn extend_unresolved_reference(
&mut self,
scope_id: ScopeId,
name: CompactStr,
reference_ids: Vec<ReferenceId>,
) {
self.unresolved_references[scope_id].entry(name).or_default().extend(reference_ids);
}

pub(crate) fn unresolved_references_mut(
&mut self,
scope_id: ScopeId,
) -> &mut UnresolvedReferences {
&mut self.unresolved_references[scope_id]
}
}