diff --git a/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs b/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs index b2cbcdcf9a052..fe750cf32a9de 100644 --- a/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs +++ b/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs @@ -44,10 +44,15 @@ fn reduce_unknown(spread_span: Span, reduce_span: Span) -> OxcDiagnostic { ]) } -fn loop_spread_diagnostic(spread_span: Span, loop_span: Span) -> OxcDiagnostic { +fn loop_spread_diagnostic( + accumulator_decl_span: Span, + spread_span: Span, + loop_span: Span, +) -> OxcDiagnostic { OxcDiagnostic::warn("Do not spread accumulators in loops") .with_help("Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead.\nUsing spreads within accumulators leads to `O(n^2)` time complexity.") .with_labels([ + accumulator_decl_span.label("From this accumulator"), spread_span.label("From this spread"), loop_span.label("For this loop") ]) @@ -191,9 +196,9 @@ fn check_loop_usage<'a>( return; } - if !matches!(declarator.kind(), AstKind::VariableDeclarator(_)) { + let AstKind::VariableDeclarator(declarator) = declarator.kind() else { return; - } + }; let Some(write_reference) = ctx.semantic().symbol_references(referenced_symbol_id).find(|r| r.is_write()) @@ -229,7 +234,11 @@ fn check_loop_usage<'a>( if !parent.kind().span().contains_inclusive(declaration.span) && parent.kind().span().contains_inclusive(spread_span) { - ctx.diagnostic(loop_spread_diagnostic(spread_span, loop_span)); + ctx.diagnostic(loop_spread_diagnostic( + declarator.id.span(), + spread_span, + loop_span, + )); } } } diff --git a/crates/oxc_linter/src/snapshots/no_accumulating_spread.snap b/crates/oxc_linter/src/snapshots/no_accumulating_spread.snap index 656beca4e7754..d976addcda41f 100644 --- a/crates/oxc_linter/src/snapshots/no_accumulating_spread.snap +++ b/crates/oxc_linter/src/snapshots/no_accumulating_spread.snap @@ -315,141 +315,155 @@ source: crates/oxc_linter/src/tester.rs Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = []; for (let i = 0; i < 10; i++) { foo = [...foo, i]; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = []; for (const i = 0; i < 10; i++) { foo = [...foo, i]; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = []; for (let i in [1,2,3]) { foo = [...foo, i]; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = []; for (const i in [1,2,3]) { foo = [...foo, i]; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = []; for (let i of [1,2,3]) { foo = [...foo, i]; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = []; for (const i of [1,2,3]) { foo = [...foo, i]; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = []; while (foo.length < 10) { foo = [...foo, foo.length]; } - · ──┬── ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ──┬── ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = {}; for (let i = 0; i < 10; i++) { foo = { ...foo, [i]: i }; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = {}; for (const i = 0; i < 10; i++) { foo = { ...foo, [i]: i }; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = {}; for (let i in [1,2,3]) { foo = { ...foo, [i]: i }; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = {}; for (const i in [1,2,3]) { foo = { ...foo, [i]: i }; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = {}; for (let i of [1,2,3]) { foo = { ...foo, [i]: i }; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = {}; for (const i of [1,2,3]) { foo = { ...foo, [i]: i }; } - · ─┬─ ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ─┬─ ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops - ╭─[no_accumulating_spread.tsx:1:15] + ╭─[no_accumulating_spread.tsx:1:5] 1 │ let foo = {}; while (Object.keys(foo).length < 10) { foo = { ...foo, [Object.keys(foo).length]: Object.keys(foo).length }; } - · ──┬── ───┬── - · │ ╰── From this spread - · ╰── For this loop + · ─┬─ ──┬── ───┬── + · │ │ ╰── From this spread + · │ ╰── For this loop + · ╰── From this accumulator ╰──── help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity.