mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
perf(semantic): remove span field from Reference (#4464)
Remove `span` field from `Reference`. Span can instead be got via looking up span on `AstKind` via `reference.node_id`. This shrinks `Reference` from 20 bytes to 12 bytes. It does make getting span of a `Reference` a bit slower, as there's an extra table lookup involved, but the only places this is needed is in linter, and almost always when generating a diagnostic (i.e. cold path).
This commit is contained in:
parent
6a9f4db609
commit
348c1ade96
14 changed files with 36 additions and 28 deletions
|
|
@ -42,7 +42,7 @@ impl Rule for NoClassAssign {
|
||||||
ctx.diagnostic(no_class_assign_diagnostic(
|
ctx.diagnostic(no_class_assign_diagnostic(
|
||||||
symbol_table.get_name(symbol_id),
|
symbol_table.get_name(symbol_id),
|
||||||
symbol_table.get_span(symbol_id),
|
symbol_table.get_span(symbol_id),
|
||||||
reference.span(),
|
ctx.semantic().reference_span(reference),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ impl Rule for NoConstAssign {
|
||||||
ctx.diagnostic(no_const_assign_diagnostic(
|
ctx.diagnostic(no_const_assign_diagnostic(
|
||||||
symbol_table.get_name(symbol_id),
|
symbol_table.get_name(symbol_id),
|
||||||
symbol_table.get_span(symbol_id),
|
symbol_table.get_span(symbol_id),
|
||||||
reference.span(),
|
ctx.semantic().reference_span(reference),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ impl Rule for NoExAssign {
|
||||||
if symbol_table.get_flag(symbol_id).is_catch_variable() {
|
if symbol_table.get_flag(symbol_id).is_catch_variable() {
|
||||||
for reference in symbol_table.get_resolved_references(symbol_id) {
|
for reference in symbol_table.get_resolved_references(symbol_id) {
|
||||||
if reference.is_write() {
|
if reference.is_write() {
|
||||||
ctx.diagnostic(no_ex_assign_diagnostic(reference.span()));
|
ctx.diagnostic(no_ex_assign_diagnostic(
|
||||||
|
ctx.semantic().reference_span(reference),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ impl Rule for NoFuncAssign {
|
||||||
if reference.is_write() {
|
if reference.is_write() {
|
||||||
ctx.diagnostic(no_func_assign_diagnostic(
|
ctx.diagnostic(no_func_assign_diagnostic(
|
||||||
symbol_table.get_name(symbol_id),
|
symbol_table.get_name(symbol_id),
|
||||||
reference.span(),
|
ctx.semantic().reference_span(reference),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,10 @@ impl Rule for NoGlobalAssign {
|
||||||
if !self.excludes.contains(&CompactStr::from(name))
|
if !self.excludes.contains(&CompactStr::from(name))
|
||||||
&& ctx.env_contains_var(name)
|
&& ctx.env_contains_var(name)
|
||||||
{
|
{
|
||||||
ctx.diagnostic(no_global_assign_diagnostic(name, reference.span()));
|
ctx.diagnostic(no_global_assign_diagnostic(
|
||||||
|
name,
|
||||||
|
ctx.semantic().reference_span(reference),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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))
|
|| 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 let Some((span, _)) = expr.static_property_info() {
|
||||||
if span != reference.span() {
|
if span != ctx.semantic().reference_span(reference) {
|
||||||
return ctx
|
return ctx
|
||||||
.diagnostic(no_import_assign_diagnostic(expr.span()));
|
.diagnostic(no_import_assign_diagnostic(expr.span()));
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +87,9 @@ impl Rule for NoImportAssign {
|
||||||
|| (is_namespace_specifier
|
|| (is_namespace_specifier
|
||||||
&& is_argument_of_well_known_mutation_function(reference.node_id(), ctx))
|
&& 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(
|
||||||
|
ctx.semantic().reference_span(reference),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use oxc_ast::AstKind;
|
use oxc_ast::AstKind;
|
||||||
use oxc_diagnostics::OxcDiagnostic;
|
use oxc_diagnostics::OxcDiagnostic;
|
||||||
use oxc_macros::declare_oxc_lint;
|
use oxc_macros::declare_oxc_lint;
|
||||||
use oxc_span::Span;
|
use oxc_span::{GetSpan, Span};
|
||||||
use oxc_syntax::operator::UnaryOperator;
|
use oxc_syntax::operator::UnaryOperator;
|
||||||
|
|
||||||
use crate::{context::LintContext, rule::Rule, AstNode};
|
use crate::{context::LintContext, rule::Rule, AstNode};
|
||||||
|
|
@ -67,7 +67,7 @@ impl Rule for NoUndef {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.diagnostic(no_undef_diagnostic(name, reference.span()));
|
ctx.diagnostic(no_undef_diagnostic(name, node.kind().span()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,11 @@ impl Rule for NoJasmineGlobals {
|
||||||
for &(reference_id, _) in reference_ids {
|
for &(reference_id, _) in reference_ids {
|
||||||
let reference = symbol_table.get_reference(reference_id);
|
let reference = symbol_table.get_reference(reference_id);
|
||||||
if let Some((error, help)) = get_non_jasmine_property_messages(name) {
|
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,
|
||||||
|
ctx.semantic().reference_span(reference),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use oxc_ast::AstKind;
|
use oxc_ast::AstKind;
|
||||||
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
|
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
|
||||||
use oxc_macros::declare_oxc_lint;
|
use oxc_macros::declare_oxc_lint;
|
||||||
use oxc_semantic::Reference;
|
|
||||||
|
|
||||||
use crate::{context::LintContext, rule::Rule};
|
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));
|
let kind = nodes.ancestors(r.node_id()).nth(2).map(|node_id| nodes.kind(node_id));
|
||||||
matches!(kind, Some(AstKind::JSXOpeningElement(_)))
|
matches!(kind, Some(AstKind::JSXOpeningElement(_)))
|
||||||
})
|
})
|
||||||
.map(Reference::span)
|
.map(|reference| ctx.semantic().reference_span(reference))
|
||||||
.map(LabeledSpan::underline)
|
.map(LabeledSpan::underline)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ fn has_assignment_before_node(
|
||||||
let symbol_table = ctx.semantic().symbols();
|
let symbol_table = ctx.semantic().symbols();
|
||||||
|
|
||||||
for reference in symbol_table.get_resolved_references(symbol_id) {
|
for reference in symbol_table.get_resolved_references(symbol_id) {
|
||||||
if reference.is_write() && reference.span().end < parent_span_end {
|
if reference.is_write() && ctx.semantic().reference_span(reference).end < parent_span_end {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1932,7 +1932,7 @@ impl<'a> SemanticBuilder<'a> {
|
||||||
|
|
||||||
fn reference_identifier(&mut self, ident: &IdentifierReference<'a>) {
|
fn reference_identifier(&mut self, ident: &IdentifierReference<'a>) {
|
||||||
let flag = self.resolve_reference_usages();
|
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);
|
let reference_id = self.declare_reference(ident.name.clone(), reference);
|
||||||
ident.reference_id.set(Some(reference_id));
|
ident.reference_id.set(Some(reference_id));
|
||||||
}
|
}
|
||||||
|
|
@ -1956,7 +1956,7 @@ impl<'a> SemanticBuilder<'a> {
|
||||||
Some(AstKind::JSXMemberExpressionObject(_)) => {}
|
Some(AstKind::JSXMemberExpressionObject(_)) => {}
|
||||||
_ => return,
|
_ => 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);
|
self.declare_reference(ident.name.clone(), reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ pub use jsdoc::{JSDoc, JSDocFinder, JSDocTag};
|
||||||
pub use node::{AstNode, AstNodeId, AstNodes};
|
pub use node::{AstNode, AstNodeId, AstNodes};
|
||||||
use oxc_ast::{ast::IdentifierReference, AstKind, Trivias};
|
use oxc_ast::{ast::IdentifierReference, AstKind, Trivias};
|
||||||
use oxc_cfg::ControlFlowGraph;
|
use oxc_cfg::ControlFlowGraph;
|
||||||
use oxc_span::SourceType;
|
use oxc_span::{GetSpan, SourceType, Span};
|
||||||
pub use oxc_syntax::{
|
pub use oxc_syntax::{
|
||||||
module_record::ModuleRecord,
|
module_record::ModuleRecord,
|
||||||
scope::{ScopeFlags, ScopeId},
|
scope::{ScopeFlags, ScopeId},
|
||||||
|
|
@ -148,6 +148,11 @@ impl<'a> Semantic<'a> {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reference_span(&self, reference: &Reference) -> Span {
|
||||||
|
let node = self.nodes.get_node(reference.node_id());
|
||||||
|
node.kind().span()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
|
// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use oxc_span::Span;
|
|
||||||
pub use oxc_syntax::reference::{ReferenceFlag, ReferenceId};
|
pub use oxc_syntax::reference::{ReferenceFlag, ReferenceId};
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
@ -14,7 +13,6 @@ use crate::{symbol::SymbolId, AstNodeId};
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
||||||
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
|
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
|
||||||
pub struct Reference {
|
pub struct Reference {
|
||||||
span: Span,
|
|
||||||
node_id: AstNodeId,
|
node_id: AstNodeId,
|
||||||
symbol_id: Option<SymbolId>,
|
symbol_id: Option<SymbolId>,
|
||||||
/// Describes how this referenced is used by other AST nodes. References can
|
/// Describes how this referenced is used by other AST nodes. References can
|
||||||
|
|
@ -23,21 +21,16 @@ pub struct Reference {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reference {
|
impl Reference {
|
||||||
pub fn new(span: Span, node_id: AstNodeId, flag: ReferenceFlag) -> Self {
|
pub fn new(node_id: AstNodeId, flag: ReferenceFlag) -> Self {
|
||||||
Self { span, node_id, symbol_id: None, flag }
|
Self { node_id, symbol_id: None, flag }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_symbol_id(
|
pub fn new_with_symbol_id(
|
||||||
span: Span,
|
|
||||||
node_id: AstNodeId,
|
node_id: AstNodeId,
|
||||||
symbol_id: SymbolId,
|
symbol_id: SymbolId,
|
||||||
flag: ReferenceFlag,
|
flag: ReferenceFlag,
|
||||||
) -> Self {
|
) -> 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 node_id(&self) -> AstNodeId {
|
pub fn node_id(&self) -> AstNodeId {
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ impl TraverseScoping {
|
||||||
symbol_id: SymbolId,
|
symbol_id: SymbolId,
|
||||||
flag: ReferenceFlag,
|
flag: ReferenceFlag,
|
||||||
) -> ReferenceId {
|
) -> 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);
|
let reference_id = self.symbols.create_reference(reference);
|
||||||
self.symbols.resolved_references[symbol_id].push(reference_id);
|
self.symbols.resolved_references[symbol_id].push(reference_id);
|
||||||
reference_id
|
reference_id
|
||||||
|
|
@ -296,7 +296,7 @@ impl TraverseScoping {
|
||||||
name: CompactStr,
|
name: CompactStr,
|
||||||
flag: ReferenceFlag,
|
flag: ReferenceFlag,
|
||||||
) -> ReferenceId {
|
) -> ReferenceId {
|
||||||
let reference = Reference::new(SPAN, AstNodeId::DUMMY, flag);
|
let reference = Reference::new(AstNodeId::DUMMY, flag);
|
||||||
let reference_id = self.symbols.create_reference(reference);
|
let reference_id = self.symbols.create_reference(reference);
|
||||||
self.scopes.add_root_unresolved_reference(name, (reference_id, flag));
|
self.scopes.add_root_unresolved_reference(name, (reference_id, flag));
|
||||||
reference_id
|
reference_id
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue