perf(linter/unicorn/no-useless-fallback-in-spread): narrow AST dispatch (#28361)

Start from spread elements and retain the existing object-spread and
parentheses checks. Reduce fixture callbacks from 12,119 to 454.


---

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Cam McHenryandCopilot authored and GitHub committed 2026-10-28 22:28:48 -04:00
1 parent 1a1f66eeb9
commit 93c6e6dd5e
3 files changed
+12 -11

No files matched your search

+1 -1
View File
@@ -3561,7 +3561,7 @@ impl RuleRunner
for crate::rules::unicorn::no_useless_fallback_in_spread::NoUselessFallbackInSpread
{
const NODE_TYPES: Option<&AstTypesBitset> =
Some(&AstTypesBitset::from_types(&[AstType::LogicalExpression]));
Some(&AstTypesBitset::from_types(&[AstType::SpreadElement]));
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
}
@@ -47,7 +47,12 @@ declare_oxc_lint!(
impl Rule for NoUselessFallbackInSpread {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::LogicalExpression(logical_expression) = node.kind() else {
let AstKind::SpreadElement(spread_element) = node.kind() else {
return;
};
let Expression::LogicalExpression(logical_expression) =
spread_element.argument.without_parentheses()
else {
return;
};
@@ -69,14 +74,6 @@ impl Rule for NoUselessFallbackInSpread {
return;
};
let AstKind::SpreadElement(spread_element) = parent.kind() else {
return;
};
let Some(parent) = outermost_paren_parent(parent, ctx) else {
return;
};
if !matches!(parent.kind(), AstKind::ObjectExpression(_)) {
return;
}
@@ -130,6 +127,8 @@ fn test() {
"const object = call({}, ...(foo || {}))",
r#"const object = {...(foo || {not: "empty"})}"#,
"const object = {...(foo || {...{}})}",
"const object = {...((foo || {}) as object)}",
"const object = {...(foo || ({} as object))}",
];
let fail = vec![
@@ -162,6 +161,8 @@ fn test() {
];
let fix = vec![
("const object = {...((foo || {}))}", "const object = {...foo}"),
("const object = {...(foo || {}), ...(bar ?? {})}", "const object = {...foo, ...bar}"),
(r"const object = {...(foo || {})}", r"const object = {...foo}"),
(r"const object = {...(foo?.bar || {})}", r"const object = {...foo?.bar}"),
(r"const object = {...(foo() || {})}", r"const object = {...foo()}"),
@@ -574,7 +574,7 @@ unicorn/no-unreadable-array-destructuring | 276
unicorn/no-unreadable-iife | 62606
unicorn/no-useless-collection-argument | 1421
unicorn/no-useless-error-capture-stack-trace | 62606
unicorn/no-useless-fallback-in-spread | 12119
unicorn/no-useless-fallback-in-spread | 454
unicorn/no-useless-iterator-to-array | 65257
unicorn/no-useless-length-check | 12119
unicorn/no-useless-promise-resolve-reject | 62606