mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
perf(linter/react-exhaustive-deps): use stack of AstTypes instead of AstKinds (#8522)
This lint rule keeps a stack tracing the "visitation path" during `Visit`. Only the type of the nodes is used, not their values, so store only `AstType` (1 byte) rather than `AstKind` (16 bytes). This should be more performant, but the main motivation is #8461. This is one of very few places in the codebase which uses `enter_node` and `leave_node`. Not storing `AstKind`s here clears the way to remove the unsound lifetime extension in `Visit::alloc`.
This commit is contained in:
parent
a6d71f8f27
commit
250bbd193b
1 changed files with 15 additions and 19 deletions
|
|
@ -12,7 +12,7 @@ use oxc_ast::{
|
||||||
},
|
},
|
||||||
match_expression,
|
match_expression,
|
||||||
visit::walk::walk_function_body,
|
visit::walk::walk_function_body,
|
||||||
AstKind, Visit,
|
AstKind, AstType, Visit,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::OxcDiagnostic;
|
use oxc_diagnostics::OxcDiagnostic;
|
||||||
use oxc_macros::declare_oxc_lint;
|
use oxc_macros::declare_oxc_lint;
|
||||||
|
|
@ -973,7 +973,7 @@ fn func_call_without_react_namespace<'a>(
|
||||||
|
|
||||||
struct ExhaustiveDepsVisitor<'a, 'b> {
|
struct ExhaustiveDepsVisitor<'a, 'b> {
|
||||||
semantic: &'b Semantic<'a>,
|
semantic: &'b Semantic<'a>,
|
||||||
stack: Vec<AstKind<'a>>,
|
stack: Vec<AstType>,
|
||||||
skip_reporting_dependency: bool,
|
skip_reporting_dependency: bool,
|
||||||
set_state_call: bool,
|
set_state_call: bool,
|
||||||
found_dependencies: FxHashSet<Dependency<'a>>,
|
found_dependencies: FxHashSet<Dependency<'a>>,
|
||||||
|
|
@ -999,7 +999,7 @@ impl<'a, 'b> ExhaustiveDepsVisitor<'a, 'b> {
|
||||||
|
|
||||||
impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
|
impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
|
||||||
fn enter_node(&mut self, kind: AstKind<'a>) {
|
fn enter_node(&mut self, kind: AstKind<'a>) {
|
||||||
self.stack.push(kind);
|
self.stack.push(kind.ty());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn leave_node(&mut self, _kind: AstKind<'a>) {
|
fn leave_node(&mut self, _kind: AstKind<'a>) {
|
||||||
|
|
@ -1041,10 +1041,8 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_parent_call_expr = self
|
let is_parent_call_expr =
|
||||||
.stack
|
self.stack.get(self.stack.len() - 2).is_some_and(|&ty| ty == AstType::CallExpression);
|
||||||
.get(self.stack.len() - 2)
|
|
||||||
.is_some_and(|kind| matches!(kind, AstKind::CallExpression(_)));
|
|
||||||
|
|
||||||
match analyze_property_chain(&it.object, self.semantic) {
|
match analyze_property_chain(&it.object, self.semantic) {
|
||||||
Ok(source) => {
|
Ok(source) => {
|
||||||
|
|
@ -1110,9 +1108,10 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_set_state_call
|
if is_set_state_call
|
||||||
&& self.stack.iter().all(|kind| {
|
&& self
|
||||||
!matches!(kind, AstKind::Function(_) | AstKind::ArrowFunctionExpression(_))
|
.stack
|
||||||
})
|
.iter()
|
||||||
|
.all(|&ty| !matches!(ty, AstType::Function | AstType::ArrowFunctionExpression))
|
||||||
{
|
{
|
||||||
self.set_state_call = true;
|
self.set_state_call = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1120,21 +1119,18 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_inside_effect_cleanup(stack: &[AstKind<'_>]) -> bool {
|
fn is_inside_effect_cleanup(stack: &[AstType]) -> bool {
|
||||||
let mut iter = stack.iter().rev();
|
let mut iter = stack.iter().rev();
|
||||||
let mut is_in_returned_function = false;
|
let mut is_in_returned_function = false;
|
||||||
|
|
||||||
while let Some(cur) = iter.next() {
|
while let Some(&cur) = iter.next() {
|
||||||
match cur {
|
if matches!(cur, AstType::Function | AstType::ArrowFunctionExpression) {
|
||||||
AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => {
|
if let Some(&parent) = iter.next() {
|
||||||
if let Some(parent) = iter.next() {
|
if parent == AstType::ReturnStatement {
|
||||||
if matches!(parent, AstKind::ReturnStatement(_)) {
|
|
||||||
is_in_returned_function = true;
|
is_in_returned_function = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is_in_returned_function
|
is_in_returned_function
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue