mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(ast)!: IdentifierReference::reference_id return ReferenceId (#7126)
Alter `IdentifierReference::reference_id` to return `ReferenceId`, instead of `Option<ReferenceId>`. This method is only useful on a post-semantic AST, where it will never return `None`. Returning `ReferenceId` discourages the anti-pattern of treating the result as if it could be either `Some` or `None`, and shortens code.
This commit is contained in:
parent
ff8bd50d38
commit
843bce4d92
14 changed files with 29 additions and 36 deletions
|
|
@ -294,10 +294,15 @@ impl<'a> fmt::Display for IdentifierName<'a> {
|
|||
}
|
||||
|
||||
impl<'a> IdentifierReference<'a> {
|
||||
/// Get `ReferenceId` of `IdentifierReference`.
|
||||
///
|
||||
/// Only use this method on a post-semantic AST where `ReferenceId`s are always defined.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `reference_id` is `None`.
|
||||
#[inline]
|
||||
#[allow(missing_docs)]
|
||||
pub fn reference_id(&self) -> Option<ReferenceId> {
|
||||
self.reference_id.get()
|
||||
pub fn reference_id(&self) -> ReferenceId {
|
||||
self.reference_id.get().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,10 +147,7 @@ impl NoThrowLiteral {
|
|||
|| Self::could_be_error(ctx, &expr.alternate)
|
||||
}
|
||||
Expression::Identifier(ident) => {
|
||||
let Some(ref_id) = ident.reference_id() else {
|
||||
return true;
|
||||
};
|
||||
let reference = ctx.symbols().get_reference(ref_id);
|
||||
let reference = ctx.symbols().get_reference(ident.reference_id());
|
||||
let Some(symbol_id) = reference.symbol_id() else {
|
||||
return true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -211,9 +211,8 @@ impl NoAsyncEndpointHandlers {
|
|||
match arg {
|
||||
Expression::Identifier(handler) => {
|
||||
// Unresolved reference? Nothing we can do.
|
||||
let Some(symbol_id) = handler
|
||||
.reference_id()
|
||||
.and_then(|id| ctx.symbols().get_reference(id).symbol_id())
|
||||
let Some(symbol_id) =
|
||||
ctx.symbols().get_reference(handler.reference_id()).symbol_id()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use oxc_semantic::{Reference, ReferenceId, ScopeId, SymbolId};
|
||||
use oxc_semantic::{ReferenceId, ScopeId, SymbolId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Deref;
|
||||
|
||||
|
|
@ -354,10 +354,10 @@ impl Rule for NoMapSpread {
|
|||
|
||||
match leftmost_identifier_reference(&call_expr.callee) {
|
||||
Ok(ident) => {
|
||||
if let Some(ref_id) = ident.reference_id() {
|
||||
if self.is_ignored_map_call(ctx, ident.name.as_str(), ref_id, call_expr.span) {
|
||||
return;
|
||||
}
|
||||
let reference_id = ident.reference_id();
|
||||
if self.is_ignored_map_call(ctx, ident.name.as_str(), reference_id, call_expr.span)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Mapped class properties likely have their elements spread to
|
||||
|
|
@ -675,10 +675,8 @@ where
|
|||
// check if identifier is a reference to a spread-initialized
|
||||
// variable declared within the map callback.
|
||||
Expression::Identifier(ident) => {
|
||||
let Some(symbol_id) = ident
|
||||
.reference_id()
|
||||
.map(|id| self.ctx.symbols().get_reference(id))
|
||||
.and_then(Reference::symbol_id)
|
||||
let Some(symbol_id) =
|
||||
self.ctx.symbols().get_reference(ident.reference_id()).symbol_id()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -228,8 +228,7 @@ fn is_recursive_call(
|
|||
ctx: &LintContext,
|
||||
) -> bool {
|
||||
if let Expression::Identifier(identifier) = &call_expr.callee {
|
||||
if let Some(symbol_id) =
|
||||
identifier.reference_id().and_then(|id| ctx.symbols().get_reference(id).symbol_id())
|
||||
if let Some(symbol_id) = ctx.symbols().get_reference(identifier.reference_id()).symbol_id()
|
||||
{
|
||||
return symbol_id == function_symbol_id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ impl Rule for JsxNoUndef {
|
|||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
if let AstKind::JSXOpeningElement(elem) = &node.kind() {
|
||||
if let Some(ident) = get_resolvable_ident(&elem.name) {
|
||||
let reference = ctx.symbols().get_reference(ident.reference_id().unwrap());
|
||||
let reference = ctx.symbols().get_reference(ident.reference_id());
|
||||
if reference.symbol_id().is_some() {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ impl Rule for NoWrapperObjectTypes {
|
|||
};
|
||||
|
||||
if matches!(ident_name, "BigInt" | "Boolean" | "Number" | "Object" | "String" | "Symbol") {
|
||||
if reference_id.and_then(|v| ctx.symbols().get_reference(v).symbol_id()).is_some() {
|
||||
if ctx.symbols().get_reference(reference_id).symbol_id().is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ struct ReferencesFinder {
|
|||
|
||||
impl<'a> Visit<'a> for ReferencesFinder {
|
||||
fn visit_identifier_reference(&mut self, it: &oxc_ast::ast::IdentifierReference<'a>) {
|
||||
self.references.push(it.reference_id().unwrap());
|
||||
self.references.push(it.reference_id());
|
||||
}
|
||||
|
||||
fn visit_jsx_element_name(&mut self, _it: &oxc_ast::ast::JSXElementName<'a>) {
|
||||
|
|
|
|||
|
|
@ -94,9 +94,7 @@ where
|
|||
let Expression::Identifier(ident) = expr else {
|
||||
return;
|
||||
};
|
||||
let Some(symbol_id) =
|
||||
ident.reference_id().and_then(|id| ctx.symbols().get_reference(id).symbol_id())
|
||||
else {
|
||||
let Some(symbol_id) = ctx.symbols().get_reference(ident.reference_id()).symbol_id() else {
|
||||
return;
|
||||
};
|
||||
// Symbols declared at the root scope won't (or, at least, shouldn't) be
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl ConformanceTest for IdentifierReferenceTest {
|
|||
let AstKind::IdentifierReference(id) = node.kind() else {
|
||||
return TestResult::Pass;
|
||||
};
|
||||
let Some(reference_id) = id.reference_id() else {
|
||||
let Some(reference_id) = id.reference_id.get() else {
|
||||
return missing_reference_id(id);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
|
|||
let mut temp_var_inits = ctx.ast.vec();
|
||||
|
||||
// Make sure side-effects of evaluating `left` only happen once
|
||||
let reference = ctx.scoping.symbols_mut().get_reference_mut(ident.reference_id().unwrap());
|
||||
let reference = ctx.scoping.symbols_mut().get_reference_mut(ident.reference_id());
|
||||
let pow_left =
|
||||
if let Some(symbol_id) = reference.symbol_id() {
|
||||
// This variable is declared in scope so evaluating it multiple times can't trigger a getter.
|
||||
|
|
@ -492,8 +492,7 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
|
|||
match obj {
|
||||
Expression::Super(super_) => return ctx.ast.expression_super(super_.span),
|
||||
Expression::Identifier(ident) => {
|
||||
let symbol_id =
|
||||
ctx.symbols().get_reference(ident.reference_id().unwrap()).symbol_id();
|
||||
let symbol_id = ctx.symbols().get_reference(ident.reference_id()).symbol_id();
|
||||
if let Some(symbol_id) = symbol_id {
|
||||
// This variable is declared in scope so evaluating it multiple times can't trigger a getter.
|
||||
// No need for a temp var.
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> {
|
|||
ident: &IdentifierReference<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> (Expression<'a>, AssignmentTarget<'a>) {
|
||||
let reference = ctx.symbols_mut().get_reference_mut(ident.reference_id().unwrap());
|
||||
let reference = ctx.symbols_mut().get_reference_mut(ident.reference_id());
|
||||
*reference.flags_mut() = ReferenceFlags::Read;
|
||||
let symbol_id = reference.symbol_id();
|
||||
let left_expr = Expression::Identifier(ctx.alloc(ident.clone()));
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ struct ReferenceFlagsSetter<'s> {
|
|||
|
||||
impl<'a, 's> Visit<'a> for ReferenceFlagsSetter<'s> {
|
||||
fn visit_identifier_reference(&mut self, ident: &IdentifierReference<'a>) {
|
||||
let reference_id = ident.reference_id().unwrap();
|
||||
let reference_id = ident.reference_id();
|
||||
let reference = self.symbols.get_reference_mut(reference_id);
|
||||
*reference.flags_mut() |= ReferenceFlags::Read;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,10 +347,8 @@ impl TraverseScoping {
|
|||
}
|
||||
|
||||
/// Delete reference for an `IdentifierReference`.
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn delete_reference_for_identifier(&mut self, ident: &IdentifierReference) {
|
||||
// `unwrap` should never panic as `IdentifierReference`s should always have a `ReferenceId`
|
||||
self.delete_reference(ident.reference_id().unwrap(), &ident.name);
|
||||
self.delete_reference(ident.reference_id(), &ident.name);
|
||||
}
|
||||
|
||||
/// Determine whether evaluating the specific input `node` is a consequenceless reference.
|
||||
|
|
|
|||
Loading…
Reference in a new issue