From bc5e94d39116331c047731ccbe53a1af735e8c11 Mon Sep 17 00:00:00 2001 From: Cam McHenry Date: Wed, 28 Oct 2026 22:28:48 -0400 Subject: [PATCH] perf(linter/eslint/no-extra-boolean-cast): narrow AST dispatch (#28362) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle optional Boolean calls through their call nodes while retaining chain context for diagnostics and fixes. Reduce fixture callbacks from 72,504 to 71,712. --- Stack created with GitHub Stacks CLI • Give Feedback 💬 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/generated/rule_runner_impls.rs | 7 ++--- .../src/rules/eslint/no_extra_boolean_cast.rs | 31 ++++++++++--------- .../track_linter_timings/linter_timings.snap | 2 +- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/crates/oxc_linter/src/generated/rule_runner_impls.rs b/crates/oxc_linter/src/generated/rule_runner_impls.rs index 1fc38f6df0..703dd43e9a 100644 --- a/crates/oxc_linter/src/generated/rule_runner_impls.rs +++ b/crates/oxc_linter/src/generated/rule_runner_impls.rs @@ -709,11 +709,8 @@ impl RuleRunner for crate::rules::eslint::no_extra_bind::NoExtraBind { } impl RuleRunner for crate::rules::eslint::no_extra_boolean_cast::NoExtraBooleanCast { - const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[ - AstType::CallExpression, - AstType::ChainExpression, - AstType::UnaryExpression, - ])); + const NODE_TYPES: Option<&AstTypesBitset> = + Some(&AstTypesBitset::from_types(&[AstType::CallExpression, AstType::UnaryExpression])); const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run; } diff --git a/crates/oxc_linter/src/rules/eslint/no_extra_boolean_cast.rs b/crates/oxc_linter/src/rules/eslint/no_extra_boolean_cast.rs index fcebb0a35d..1b06f3c484 100644 --- a/crates/oxc_linter/src/rules/eslint/no_extra_boolean_cast.rs +++ b/crates/oxc_linter/src/rules/eslint/no_extra_boolean_cast.rs @@ -4,8 +4,8 @@ use serde::Deserialize; use oxc_ast::{ AstKind, ast::{ - CallExpression, ChainElement, ConditionalExpression, DoWhileStatement, Expression, - ForStatement, IfStatement, NewExpression, WhileStatement, + CallExpression, ConditionalExpression, DoWhileStatement, Expression, ForStatement, + IfStatement, NewExpression, WhileStatement, }, }; use oxc_diagnostics::OxcDiagnostic; @@ -99,19 +99,17 @@ impl Rule for NoExtraBooleanCast { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { match node.kind() { - AstKind::CallExpression(expr) - if !expr.optional - && expr.callee.is_specific_id("Boolean") - && is_flagged_ctx(node, ctx, self.enforce_for_inner_expressions) => - { - report_boolean_call(expr, node, ctx); - } - AstKind::ChainExpression(chain) - if is_flagged_ctx(node, ctx, self.enforce_for_inner_expressions) => - { - if let ChainElement::CallExpression(expr) = &chain.expression - && expr.callee.is_specific_id("Boolean") - { + AstKind::CallExpression(expr) if expr.callee.is_specific_id("Boolean") => { + let node = if expr.optional { + let parent = ctx.nodes().parent_node(node.id()); + if !matches!(parent.kind(), AstKind::ChainExpression(_)) { + return; + } + parent + } else { + node + }; + if is_flagged_ctx(node, ctx, self.enforce_for_inner_expressions) { report_boolean_call(expr, node, ctx); } } @@ -362,6 +360,8 @@ fn test() { use crate::tester::Tester; let pass = vec![ + ("if (Boolean?.(foo).value) {}", None), + ("if (Boolean?.(foo)()) {}", None), ("Boolean(bar, !!baz);", None), ("var foo = !!bar;", None), ("function foo() { return !!bar; }", None), @@ -1527,6 +1527,7 @@ fn test() { ]; let fix = vec![ + ("while (Boolean?.(foo)) {}", "while (foo) {}", None), ("if (!!foo) {}", "if (foo) {}", None), ("do {} while (!!foo)", "do {} while (foo)", None), ("while (!!foo) {}", "while (foo) {}", None), diff --git a/tasks/track_linter_timings/linter_timings.snap b/tasks/track_linter_timings/linter_timings.snap index 8bf06f84c7..d145717862 100644 --- a/tasks/track_linter_timings/linter_timings.snap +++ b/tasks/track_linter_timings/linter_timings.snap @@ -67,7 +67,7 @@ eslint/no-eval | 73005 eslint/no-ex-assign | 111 eslint/no-extend-native | 7 eslint/no-extra-bind | 62606 -eslint/no-extra-boolean-cast | 72504 +eslint/no-extra-boolean-cast | 71712 eslint/no-extra-label | 836 eslint/no-fallthrough | 284 eslint/no-func-assign | 14283