mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +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,
|
||||
visit::walk::walk_function_body,
|
||||
AstKind, Visit,
|
||||
AstKind, AstType, Visit,
|
||||
};
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
|
|
@ -973,7 +973,7 @@ fn func_call_without_react_namespace<'a>(
|
|||
|
||||
struct ExhaustiveDepsVisitor<'a, 'b> {
|
||||
semantic: &'b Semantic<'a>,
|
||||
stack: Vec<AstKind<'a>>,
|
||||
stack: Vec<AstType>,
|
||||
skip_reporting_dependency: bool,
|
||||
set_state_call: bool,
|
||||
found_dependencies: FxHashSet<Dependency<'a>>,
|
||||
|
|
@ -999,7 +999,7 @@ impl<'a, 'b> ExhaustiveDepsVisitor<'a, 'b> {
|
|||
|
||||
impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'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>) {
|
||||
|
|
@ -1041,10 +1041,8 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
|
|||
return;
|
||||
}
|
||||
|
||||
let is_parent_call_expr = self
|
||||
.stack
|
||||
.get(self.stack.len() - 2)
|
||||
.is_some_and(|kind| matches!(kind, AstKind::CallExpression(_)));
|
||||
let is_parent_call_expr =
|
||||
self.stack.get(self.stack.len() - 2).is_some_and(|&ty| ty == AstType::CallExpression);
|
||||
|
||||
match analyze_property_chain(&it.object, self.semantic) {
|
||||
Ok(source) => {
|
||||
|
|
@ -1110,9 +1108,10 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
|
|||
};
|
||||
|
||||
if is_set_state_call
|
||||
&& self.stack.iter().all(|kind| {
|
||||
!matches!(kind, AstKind::Function(_) | AstKind::ArrowFunctionExpression(_))
|
||||
})
|
||||
&& self
|
||||
.stack
|
||||
.iter()
|
||||
.all(|&ty| !matches!(ty, AstType::Function | AstType::ArrowFunctionExpression))
|
||||
{
|
||||
self.set_state_call = true;
|
||||
}
|
||||
|
|
@ -1120,20 +1119,17 @@ 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 is_in_returned_function = false;
|
||||
|
||||
while let Some(cur) = iter.next() {
|
||||
match cur {
|
||||
AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => {
|
||||
if let Some(parent) = iter.next() {
|
||||
if matches!(parent, AstKind::ReturnStatement(_)) {
|
||||
is_in_returned_function = true;
|
||||
}
|
||||
while let Some(&cur) = iter.next() {
|
||||
if matches!(cur, AstType::Function | AstType::ArrowFunctionExpression) {
|
||||
if let Some(&parent) = iter.next() {
|
||||
if parent == AstType::ReturnStatement {
|
||||
is_in_returned_function = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue