diff --git a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs index 128edf9260e81..d527266ed2d98 100644 --- a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs @@ -35,13 +35,14 @@ declare_oxc_lint!( impl Rule for NoClassAssign { fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) { - let symbol_table = ctx.semantic().symbols(); + let semantic = &**ctx.semantic(); + let symbol_table = semantic.symbols(); if symbol_table.get_flag(symbol_id).is_class() { for reference in symbol_table.get_resolved_references(symbol_id) { if reference.is_write() { ctx.diagnostic(no_class_assign_diagnostic( symbol_table.get_name(symbol_id), - symbol_table.get_span(symbol_id), + semantic.symbol_span(symbol_id), ctx.semantic().reference_span(reference), )); } diff --git a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs index 627a575ba1f43..f67bfa1759506 100644 --- a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs @@ -34,13 +34,14 @@ declare_oxc_lint!( impl Rule for NoConstAssign { fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) { - let symbol_table = ctx.semantic().symbols(); + let semantic = &**ctx.semantic(); + let symbol_table = semantic.symbols(); if symbol_table.get_flag(symbol_id).is_const_variable() { for reference in symbol_table.get_resolved_references(symbol_id) { if reference.is_write() { ctx.diagnostic(no_const_assign_diagnostic( symbol_table.get_name(symbol_id), - symbol_table.get_span(symbol_id), + semantic.symbol_span(symbol_id), ctx.semantic().reference_span(reference), )); } diff --git a/crates/oxc_linter/src/rules/eslint/no_label_var.rs b/crates/oxc_linter/src/rules/eslint/no_label_var.rs index 304338a6b2f29..40384ad02efeb 100644 --- a/crates/oxc_linter/src/rules/eslint/no_label_var.rs +++ b/crates/oxc_linter/src/rules/eslint/no_label_var.rs @@ -47,7 +47,7 @@ impl Rule for NoLabelVar { if let Some(symbol_id) = ctx.scopes().find_binding(node.scope_id(), &labeled_stmt.label.name) { - let decl_span = ctx.symbols().get_span(symbol_id); + let decl_span = ctx.semantic().symbol_span(symbol_id); let label_decl = labeled_stmt.span.start; ctx.diagnostic(no_label_var_diagnostic( &labeled_stmt.label.name, diff --git a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs index 6218dd5ec0035..1e7b56852ac4b 100644 --- a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs +++ b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs @@ -60,7 +60,7 @@ impl Rule for NoShadowRestrictedNames { } } - let span = ctx.symbols().get_span(symbol_id); + let span = ctx.semantic().symbol_span(symbol_id); ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, span)); for &span in ctx.symbols().get_redeclarations(symbol_id) { diff --git a/crates/oxc_linter/src/rules/import/namespace.rs b/crates/oxc_linter/src/rules/import/namespace.rs index 9209b11b20d44..42d9227d06a7e 100644 --- a/crates/oxc_linter/src/rules/import/namespace.rs +++ b/crates/oxc_linter/src/rules/import/namespace.rs @@ -98,8 +98,7 @@ impl Rule for Namespace { return; } - let Some(symbol_id) = - ctx.semantic().symbols().get_symbol_id_from_span(entry.local_name.span()) + let Some(symbol_id) = ctx.semantic().get_symbol_id_from_span(entry.local_name.span()) else { return; }; diff --git a/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs b/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs index 57819e2b9ea97..fd34808ea104e 100644 --- a/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs +++ b/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs @@ -71,7 +71,7 @@ impl Rule for NoNamedAsDefaultMember { if !remote_module_record_ref.exported_bindings.is_empty() { has_members_map.insert( - ctx.symbols().get_symbol_id_from_span(import_entry.local_name.span()).unwrap(), + ctx.semantic().get_symbol_id_from_span(import_entry.local_name.span()).unwrap(), (remote_module_record_ref, import_entry.module_request.name().clone()), ); } diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index cba1854af9aa0..6aa814a588f65 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -254,8 +254,7 @@ impl<'a> Binder<'a> for CatchParameter<'a> { // unless CatchParameter is CatchParameter : BindingIdentifier if let BindingPatternKind::BindingIdentifier(ident) = &self.pattern.kind { let includes = SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable; - let symbol_id = - builder.declare_shadow_symbol(&ident.name, ident.span, current_scope_id, includes); + let symbol_id = builder.declare_shadow_symbol(&ident.name, current_scope_id, includes); ident.symbol_id.set(Some(symbol_id)); } else { self.pattern.bound_names(&mut |ident| { diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 80c742c1eb901..e8eab2419e04e 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -13,7 +13,7 @@ use oxc_cfg::{ IterationInstructionKind, ReturnInstructionKind, }; use oxc_diagnostics::OxcDiagnostic; -use oxc_span::{Atom, CompactStr, SourceType, Span}; +use oxc_span::{Atom, CompactStr, GetSpan, SourceType, Span}; use oxc_syntax::{module_record::ModuleRecord, operator::AssignmentOperator}; use rustc_hash::FxHashMap; @@ -343,13 +343,8 @@ impl<'a> SemanticBuilder<'a> { let includes = includes | self.current_symbol_flags; let name = CompactStr::new(name); - let symbol_id = self.symbols.create_symbol( - span, - name.clone(), - includes, - scope_id, - self.current_node_id, - ); + let symbol_id = + self.symbols.create_symbol(name.clone(), includes, scope_id, self.current_node_id); self.scope.add_binding(scope_id, name, symbol_id); symbol_id } @@ -376,7 +371,8 @@ impl<'a> SemanticBuilder<'a> { self.hoisting_variables.get(&scope_id).and_then(|symbols| symbols.get(name).copied()) })?; if report_error && self.symbols.get_flag(symbol_id).intersects(excludes) { - let symbol_span = self.symbols.get_span(symbol_id); + let declaration_node_id = self.symbols.get_declaration(symbol_id); + let symbol_span = self.nodes.kind(declaration_node_id).span(); self.error(redeclaration(name, symbol_span, span)); } Some(symbol_id) @@ -401,14 +397,12 @@ impl<'a> SemanticBuilder<'a> { pub fn declare_shadow_symbol( &mut self, name: &str, - span: Span, scope_id: ScopeId, includes: SymbolFlags, ) -> SymbolId { let includes = includes | self.current_symbol_flags; let name = CompactStr::new(name); let symbol_id = self.symbols.create_symbol( - span, name.clone(), includes, self.current_scope_id, diff --git a/crates/oxc_semantic/src/lib.rs b/crates/oxc_semantic/src/lib.rs index e17b02f0ced3c..cd398f750c029 100644 --- a/crates/oxc_semantic/src/lib.rs +++ b/crates/oxc_semantic/src/lib.rs @@ -136,6 +136,10 @@ impl<'a> Semantic<'a> { self.nodes.get_node(self.symbols.get_declaration(symbol_id)) } + pub fn symbol_span(&self, symbol_id: SymbolId) -> Span { + self.symbol_declaration(symbol_id).kind().span() + } + pub fn is_reference_to_global_variable(&self, ident: &IdentifierReference) -> bool { self.scopes().root_unresolved_references().contains_key(ident.name.as_str()) } @@ -153,6 +157,21 @@ impl<'a> Semantic<'a> { let node = self.nodes.get_node(reference.node_id()); node.kind().span() } + + pub fn get_symbol_id_from_span(&self, span: Span) -> Option { + self.symbols.declarations.iter_enumerated().find_map(|(symbol_id, &node_id)| { + let inner_span = self.nodes.kind(node_id).span(); + if inner_span == span { + Some(symbol_id) + } else { + None + } + }) + } + + pub fn get_scope_id_from_span(&self, span: Span) -> Option { + self.get_symbol_id_from_span(span).map(|symbol_id| self.symbols.get_scope_id(symbol_id)) + } } #[cfg(test)] diff --git a/crates/oxc_semantic/src/symbol.rs b/crates/oxc_semantic/src/symbol.rs index eb5cd57885e9b..d861af0494ae4 100644 --- a/crates/oxc_semantic/src/symbol.rs +++ b/crates/oxc_semantic/src/symbol.rs @@ -33,7 +33,6 @@ export type IndexVec = Array; #[derive(Debug, Default)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify), serde(rename_all = "camelCase"))] pub struct SymbolTable { - pub spans: IndexVec, pub names: IndexVec, pub flags: IndexVec, pub scope_ids: IndexVec, @@ -49,7 +48,7 @@ pub struct SymbolTable { impl SymbolTable { pub fn len(&self) -> usize { - self.spans.len() + self.names.len() } pub fn is_empty(&self) -> bool { @@ -57,17 +56,11 @@ impl SymbolTable { } pub fn iter(&self) -> impl Iterator + '_ { - self.spans.iter_enumerated().map(|(symbol_id, _)| symbol_id) + self.flags.iter_enumerated().map(|(symbol_id, _)| symbol_id) } pub fn iter_rev(&self) -> impl Iterator + '_ { - self.spans.iter_enumerated().rev().map(|(symbol_id, _)| symbol_id) - } - - pub fn get_symbol_id_from_span(&self, span: Span) -> Option { - self.spans - .iter_enumerated() - .find_map(|(symbol, &inner_span)| if inner_span == span { Some(symbol) } else { None }) + self.flags.iter_enumerated().rev().map(|(symbol_id, _)| symbol_id) } pub fn get_symbol_id_from_name(&self, name: &str) -> Option { @@ -80,10 +73,6 @@ impl SymbolTable { }) } - pub fn get_span(&self, symbol_id: SymbolId) -> Span { - self.spans[symbol_id] - } - pub fn get_name(&self, symbol_id: SymbolId) -> &str { &self.names[symbol_id] } @@ -113,10 +102,6 @@ impl SymbolTable { self.scope_ids[symbol_id] } - pub fn get_scope_id_from_span(&self, span: Span) -> Option { - self.get_symbol_id_from_span(span).map(|symbol_id| self.get_scope_id(symbol_id)) - } - pub fn get_scope_id_from_name(&self, name: &str) -> Option { self.get_symbol_id_from_name(name).map(|symbol_id| self.get_scope_id(symbol_id)) } @@ -127,13 +112,11 @@ impl SymbolTable { pub fn create_symbol( &mut self, - span: Span, name: CompactStr, flag: SymbolFlags, scope_id: ScopeId, node_id: AstNodeId, ) -> SymbolId { - self.spans.push(span); self.names.push(name); self.flags.push(flag); self.scope_ids.push(scope_id); @@ -210,7 +193,6 @@ impl SymbolTable { } pub fn reserve(&mut self, additional_symbols: usize, additional_references: usize) { - self.spans.reserve(additional_symbols); self.names.reserve(additional_symbols); self.flags.reserve(additional_symbols); self.scope_ids.reserve(additional_symbols); diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index ef5d421c19e1b..db47fe9a77356 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -76,7 +76,6 @@ impl<'a> TypeScriptEnum<'a> { let enum_name = decl.id.name.clone(); let func_scope_id = decl.scope_id.get().unwrap(); let param_symbol_id = ctx.symbols_mut().create_symbol( - decl.id.span, enum_name.to_compact_str(), SymbolFlags::FunctionScopedVariable, func_scope_id, diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index 404f2bbd69512..b1530ae416ca3 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -7,7 +7,7 @@ use oxc_ast::{ visit::{walk, Visit}, }; use oxc_semantic::{AstNodeId, Reference, ScopeTree, SymbolTable}; -use oxc_span::{Atom, CompactStr, Span, SPAN}; +use oxc_span::{Atom, CompactStr, Span}; use oxc_syntax::{ reference::{ReferenceFlag, ReferenceId}, scope::{ScopeFlags, ScopeId}, @@ -245,8 +245,7 @@ impl TraverseScoping { let name = CompactStr::new(&self.find_uid_name(name)); // Add binding to scope - let symbol_id = - self.symbols.create_symbol(SPAN, name.clone(), flags, scope_id, AstNodeId::DUMMY); + let symbol_id = self.symbols.create_symbol(name.clone(), flags, scope_id, AstNodeId::DUMMY); self.scopes.add_binding(scope_id, name, symbol_id); symbol_id }