Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(linter/unicorn/prefer-array-flat): skip plain concat normalization - #26604

Open
im10furry wants to merge 1 commit into
oxc-project:mainfrom
im10furry:fix/prefer-array-flat-concat-spread
Open

fix(linter/unicorn/prefer-array-flat): skip plain concat normalization#26604
im10furry wants to merge 1 commit into
oxc-project:mainfrom
im10furry:fix/prefer-array-flat-concat-spread

Conversation

@im10furry

@im10furry im10furry commented Sep 13, 2026

Copy link
Copy Markdown

Bug

unicorn/prefer-array-flat reports plain concat normalization — patterns that do not consume an array of concat arguments. Upstream deliberately does not report them, and points at prefer-spread instead:

This rule intentionally does not report plain concat normalization like [].concat(value) or Array.prototype.concat.call([], value). Those patterns do not consume an array of concat arguments, so they are better handled by prefer-spread.

Two families are affected, both currently reported by Oxlint:

export const normalize = (value) => [].concat(value);                        // ❌ reported
export const normalize = (value) => Array.prototype.concat.call([], value);  // ❌ reported

Same root cause: the port reports the shape without checking whether the single argument is spread, which is what actually makes the call flatten.

Repro (all upstream-valid, i.e. should NOT be reported)

export const normalize = (value) => [].concat(value);
function foo(){ return [].concat(maybeArray); }
[].concat( [[foo]] );
async function a() { return [].concat(await getArray()); }
[/**/].concat(some.array);

[].concat.call([], maybeArray);
Array.prototype.concat.call([], [foo]);

Expected

Only the forms that actually flatten are reported:

const foo = [].concat(...array);                        // ✅ reported
const foo = [].concat.apply([], array);                 // ✅ reported (apply passes the array as-is)
const foo = Array.prototype.concat.call([], ...array);  // ✅ reported
const foo = Array.prototype.concat.apply([], array);    // ✅ reported

Fix

check_array_concat_case — require the single argument to be a SpreadElement:

if !array_expr.elements.is_empty()
    || !matches!(call_expr.arguments.first(), Some(Argument::SpreadElement(_)))
{
    return;
}

check_array_prototype_concat_casecall only flattens with a spread second argument, while apply passes the array as-is, so a spread there is not flattening (this mirrors upstream's arrayPrototypeConcat):

let is_spread_second_argument =
    matches!(call_expr.arguments.get(1), Some(Argument::SpreadElement(_)));
// ...
&& (if is_call_call { is_spread_second_argument } else { !is_spread_second_argument })

The rule's doc examples no longer list [].concat(maybeArray) / Array.prototype.concat.call([], maybeArray) as incorrect (upstream's docs do not either), and the upstream-valid normalization cases (16) were moved into the rule's pass list so the false positives cannot regress.

Tests

  • cargo test -p oxc_linter --all-features --lib1261 passed, 0 failed, 1 ignored
  • cargo test -p oxc_linter --lib rules::unicorn → 147 passed
  • cargo fmt -p oxc_linter -- --check clean, cargo clippy -p oxc_linter --all-targets no new warnings (only the pre-existing pedantic from_iter_instead_of_collect warnings in lib.rs)
  • Generated-file checks that CI runs are all no-ops here: cargo lintgen, pnpm --filter oxlint-app generate-config-types and cargo lint-timings produce no diff (rule node types and call counts are unchanged)
  • typos clean; cargo check --all-features --all-targets --locked on the workspace passes
  • Snapshot regenerated with cargo insta accept and reviewed: only the false-positive blocks are removed; the spread forms still report as before

Closes #26593

Prepared with AI assistance.

@im10furry
im10furry requested a review from camc314 as a code owner September 13, 2026 18:12
@im10furry
im10furry force-pushed the fix/prefer-array-flat-concat-spread branch from c129d61 to e025e73 Compare September 13, 2026 18:15
@im10furry
im10furry force-pushed the fix/prefer-array-flat-concat-spread branch from e025e73 to 570da6d Compare September 13, 2026 18:38
@im10furry im10furry changed the title fix(linter/unicorn/prefer-array-flat): skip plain [].concat(value) normalization fix(linter/unicorn/prefer-array-flat): skip plain concat normalization Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

linter: unicorn/prefer-array-flat reports plain concat normalization

1 participant