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 dc1be943d1e79..a1e85a4bf7108 100644 --- a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs @@ -42,7 +42,7 @@ impl Rule for NoClassAssign { ctx.diagnostic(no_class_assign_diagnostic( symbol_table.get_name(symbol_id), symbol_table.get_span(symbol_id), - reference.span(), + reference.span(ctx.semantic()), )); } } 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 998b8168605e9..bd9fa1074eb01 100644 --- a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs @@ -41,7 +41,7 @@ impl Rule for NoConstAssign { ctx.diagnostic(no_const_assign_diagnostic( symbol_table.get_name(symbol_id), symbol_table.get_span(symbol_id), - reference.span(), + reference.span(ctx.semantic()), )); } } diff --git a/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs b/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs index 3bf015414ac4d..a0d52c8bd8b5d 100644 --- a/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs @@ -41,7 +41,7 @@ impl Rule for NoExAssign { if symbol_table.get_flag(symbol_id).is_catch_variable() { for reference in symbol_table.get_resolved_references(symbol_id) { if reference.is_write() { - ctx.diagnostic(no_ex_assign_diagnostic(reference.span())); + ctx.diagnostic(no_ex_assign_diagnostic(reference.span(ctx.semantic()))); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_func_assign.rs b/crates/oxc_linter/src/rules/eslint/no_func_assign.rs index 603e14ee72319..c19d6e3873c3c 100644 --- a/crates/oxc_linter/src/rules/eslint/no_func_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_func_assign.rs @@ -40,7 +40,7 @@ impl Rule for NoFuncAssign { if reference.is_write() { ctx.diagnostic(no_func_assign_diagnostic( symbol_table.get_name(symbol_id), - reference.span(), + reference.span(ctx.semantic()), )); } } diff --git a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs index 750a8b570c1fe..c211f9844700d 100644 --- a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs @@ -67,7 +67,10 @@ impl Rule for NoGlobalAssign { if !self.excludes.contains(&CompactStr::from(name)) && ctx.env_contains_var(name) { - ctx.diagnostic(no_global_assign_diagnostic(name, reference.span())); + ctx.diagnostic(no_global_assign_diagnostic( + name, + reference.span(ctx.semantic()), + )); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_import_assign.rs b/crates/oxc_linter/src/rules/eslint/no_import_assign.rs index dbc6200708710..0aca2fb87a4cc 100644 --- a/crates/oxc_linter/src/rules/eslint/no_import_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_import_assign.rs @@ -74,7 +74,7 @@ impl Rule for NoImportAssign { || matches!(parent_parent_kind, AstKind::ChainExpression(_) if ctx.nodes().parent_kind(parent_parent_node.id()).is_some_and(is_unary_expression_with_delete_operator)) { if let Some((span, _)) = expr.static_property_info() { - if span != reference.span() { + if span != reference.span(ctx.semantic()) { return ctx .diagnostic(no_import_assign_diagnostic(expr.span())); } @@ -87,7 +87,7 @@ impl Rule for NoImportAssign { || (is_namespace_specifier && is_argument_of_well_known_mutation_function(reference.node_id(), ctx)) { - ctx.diagnostic(no_import_assign_diagnostic(reference.span())); + ctx.diagnostic(no_import_assign_diagnostic(reference.span(ctx.semantic()))); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_undef.rs b/crates/oxc_linter/src/rules/eslint/no_undef.rs index d748853002877..2cd257130a7a3 100644 --- a/crates/oxc_linter/src/rules/eslint/no_undef.rs +++ b/crates/oxc_linter/src/rules/eslint/no_undef.rs @@ -67,7 +67,7 @@ impl Rule for NoUndef { continue; } - ctx.diagnostic(no_undef_diagnostic(name, reference.span())); + ctx.diagnostic(no_undef_diagnostic(name, reference.span(ctx.semantic()))); } } } diff --git a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs index eb9361edaa61e..d7ea4078280ef 100644 --- a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs +++ b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs @@ -54,7 +54,11 @@ impl Rule for NoJasmineGlobals { for &(reference_id, _) in reference_ids { let reference = symbol_table.get_reference(reference_id); if let Some((error, help)) = get_non_jasmine_property_messages(name) { - ctx.diagnostic(no_jasmine_globals_diagnostic(error, help, reference.span())); + ctx.diagnostic(no_jasmine_globals_diagnostic( + error, + help, + reference.span(ctx.semantic()), + )); } } } diff --git a/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs b/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs index 1fd279a3b4468..f531729ac5917 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs @@ -1,7 +1,6 @@ use oxc_ast::AstKind; use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_macros::declare_oxc_lint; -use oxc_semantic::Reference; use crate::{context::LintContext, rule::Rule}; @@ -65,7 +64,7 @@ impl Rule for NoDuplicateHead { let kind = nodes.ancestors(r.node_id()).nth(2).map(|node_id| nodes.kind(node_id)); matches!(kind, Some(AstKind::JSXOpeningElement(_))) }) - .map(Reference::span) + .map(|reference| reference.span(ctx.semantic())) .map(LabeledSpan::underline) .collect::>(); diff --git a/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_nullish_coalescing.rs b/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_nullish_coalescing.rs index 73357c4bda49a..f869eb0355f53 100644 --- a/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_nullish_coalescing.rs +++ b/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_nullish_coalescing.rs @@ -60,7 +60,7 @@ fn has_assignment_before_node( let symbol_table = ctx.semantic().symbols(); for reference in symbol_table.get_resolved_references(symbol_id) { - if reference.is_write() && reference.span().end < parent_span_end { + if reference.is_write() && reference.span(ctx.semantic()).end < parent_span_end { return true; } } diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 7e6bb8e66fc91..80c742c1eb901 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -1932,7 +1932,7 @@ impl<'a> SemanticBuilder<'a> { fn reference_identifier(&mut self, ident: &IdentifierReference<'a>) { let flag = self.resolve_reference_usages(); - let reference = Reference::new(ident.span, self.current_node_id, flag); + let reference = Reference::new(self.current_node_id, flag); let reference_id = self.declare_reference(ident.name.clone(), reference); ident.reference_id.set(Some(reference_id)); } @@ -1956,7 +1956,7 @@ impl<'a> SemanticBuilder<'a> { Some(AstKind::JSXMemberExpressionObject(_)) => {} _ => return, } - let reference = Reference::new(ident.span, self.current_node_id, ReferenceFlag::read()); + let reference = Reference::new(self.current_node_id, ReferenceFlag::read()); self.declare_reference(ident.name.clone(), reference); } diff --git a/crates/oxc_semantic/src/node.rs b/crates/oxc_semantic/src/node.rs index 0588f0196803c..7639d1a5a622f 100644 --- a/crates/oxc_semantic/src/node.rs +++ b/crates/oxc_semantic/src/node.rs @@ -1,6 +1,7 @@ use oxc_ast::AstKind; use oxc_cfg::BasicBlockId; use oxc_index::IndexVec; +use oxc_span::{GetSpan, Span}; pub use oxc_syntax::node::{AstNodeId, NodeFlags}; use crate::scope::ScopeId; @@ -55,6 +56,10 @@ impl<'a> AstNode<'a> { pub fn flags_mut(&mut self) -> &mut NodeFlags { &mut self.flags } + + pub fn span(&self) -> Span { + self.kind.span() + } } /// Untyped AST nodes flattened into an vec @@ -94,6 +99,10 @@ impl<'a> AstNodes<'a> { self.nodes[ast_node_id].kind } + pub fn span(&self, ast_node_id: AstNodeId) -> Span { + self.nodes[ast_node_id].kind.span() + } + pub fn parent_id(&self, ast_node_id: AstNodeId) -> Option { self.parent_ids[ast_node_id] } diff --git a/crates/oxc_semantic/src/reference.rs b/crates/oxc_semantic/src/reference.rs index ea36782a56de4..a3cbe74a705ae 100644 --- a/crates/oxc_semantic/src/reference.rs +++ b/crates/oxc_semantic/src/reference.rs @@ -8,13 +8,12 @@ use serde::Serialize; #[cfg(feature = "serialize")] use tsify::Tsify; -use crate::{symbol::SymbolId, AstNodeId}; +use crate::{symbol::SymbolId, AstNodeId, Semantic}; #[derive(Debug, Clone)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] pub struct Reference { - span: Span, node_id: AstNodeId, symbol_id: Option, /// Describes how this referenced is used by other AST nodes. References can @@ -23,21 +22,20 @@ pub struct Reference { } impl Reference { - pub fn new(span: Span, node_id: AstNodeId, flag: ReferenceFlag) -> Self { - Self { span, node_id, symbol_id: None, flag } + pub fn new(node_id: AstNodeId, flag: ReferenceFlag) -> Self { + Self { node_id, symbol_id: None, flag } } pub fn new_with_symbol_id( - span: Span, node_id: AstNodeId, symbol_id: SymbolId, flag: ReferenceFlag, ) -> Self { - Self { span, node_id, symbol_id: Some(symbol_id), flag } + Self { node_id, symbol_id: Some(symbol_id), flag } } - pub fn span(&self) -> Span { - self.span + pub fn span(&self, semantic: &Semantic) -> Span { + semantic.nodes().span(self.node_id) } pub fn node_id(&self) -> AstNodeId { diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index fa58b9cca1ef5..404f2bbd69512 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -267,7 +267,7 @@ impl TraverseScoping { symbol_id: SymbolId, flag: ReferenceFlag, ) -> ReferenceId { - let reference = Reference::new_with_symbol_id(SPAN, AstNodeId::DUMMY, symbol_id, flag); + let reference = Reference::new_with_symbol_id(AstNodeId::DUMMY, symbol_id, flag); let reference_id = self.symbols.create_reference(reference); self.symbols.resolved_references[symbol_id].push(reference_id); reference_id @@ -296,7 +296,7 @@ impl TraverseScoping { name: CompactStr, flag: ReferenceFlag, ) -> ReferenceId { - let reference = Reference::new(SPAN, AstNodeId::DUMMY, flag); + let reference = Reference::new(AstNodeId::DUMMY, flag); let reference_id = self.symbols.create_reference(reference); self.scopes.add_root_unresolved_reference(name, (reference_id, flag)); reference_id