diff --git a/crates/oxc_linter/src/rules/oxc/no_map_spread.rs b/crates/oxc_linter/src/rules/oxc/no_map_spread.rs index 5573fe423a9bf..35b22a22f651e 100644 --- a/crates/oxc_linter/src/rules/oxc/no_map_spread.rs +++ b/crates/oxc_linter/src/rules/oxc/no_map_spread.rs @@ -33,9 +33,9 @@ fn no_map_spread_diagnostic( assert!(!spans.is_empty()); let mut spread_labels = spread.spread_spans().into_iter(); let first_message = if spans.len() == 1 { - "It should be mutated in place" + "This spread allocates a new value on each iteration" } else { - "They should be mutated in place" + "These spreads allocate new values on each iteration" }; let first = spread_labels.next().unwrap().label(first_message); let others = spread_labels.map(LabeledSpan::from); @@ -51,13 +51,23 @@ fn no_map_spread_diagnostic( "Spreading to modify object properties in `map` calls is inefficient", ) .with_labels([map_call.label("This map call spreads an object"), first]) - .with_help("Consider using `Object.assign` instead"), + .with_help( + "If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading", + ) + .with_note( + "`Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required.", + ), // Array Spread::Array(_) => OxcDiagnostic::warn( "Spreading to modify array elements in `map` calls is inefficient", ) .with_labels([map_call.label("This map call spreads an array"), first]) - .with_help("Consider using `Array.prototype.concat` or `Array.prototype.push` instead"), + .with_help( + "If in-place mutation is acceptable, use `push` (or `concat` when semantics match) instead of spreading", + ) + .with_note( + "`push` mutates the array. `concat` returns a new array and is not equivalent for every iterable.", + ), }; diagnostic.and_labels(others).and_labels(returned_label) diff --git a/crates/oxc_linter/src/snapshots/oxc_no_map_spread.snap b/crates/oxc_linter/src/snapshots/oxc_no_map_spread.snap index 8595c5da7e040..2d6281608a4d5 100644 --- a/crates/oxc_linter/src/snapshots/oxc_no_map_spread.snap +++ b/crates/oxc_linter/src/snapshots/oxc_no_map_spread.snap @@ -1,125 +1,139 @@ --- source: crates/oxc_linter/src/tester.rs +assertion_line: 444 --- ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => ({ ...x, ...y })) · ─┬─ ──┬─ ──── - · │ ╰── They should be mutated in place + · │ ╰── These spreads allocate new values on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:23] 1 │ let b = []; let a = b.map(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => { return { ...x } }) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify array elements in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => [ ...x ]) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an array ╰──── - help: Consider using `Array.prototype.concat` or `Array.prototype.push` instead + help: If in-place mutation is acceptable, use `push` (or `concat` when semantics match) instead of spreading + note: `push` mutates the array. `concat` returns a new array and is not equivalent for every iterable. ⚠ oxc(no-map-spread): Spreading to modify array elements in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => [ ...x, ...y ]) · ─┬─ ──┬─ ──── - · │ ╰── They should be mutated in place + · │ ╰── These spreads allocate new values on each iteration · ╰── This map call spreads an array ╰──── - help: Consider using `Array.prototype.concat` or `Array.prototype.push` instead + help: If in-place mutation is acceptable, use `push` (or `concat` when semantics match) instead of spreading + note: `push` mutates the array. `concat` returns a new array and is not equivalent for every iterable. ⚠ oxc(no-map-spread): Spreading to modify array elements in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => { return [ ...x ] }) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an array ╰──── - help: Consider using `Array.prototype.concat` or `Array.prototype.push` instead + help: If in-place mutation is acceptable, use `push` (or `concat` when semantics match) instead of spreading + note: `push` mutates the array. `concat` returns a new array and is not equivalent for every iterable. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:3] 1 │ a.map?.(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.flatMap(x => ({ ...x })) · ───┬─── ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => ({ ...x })); console.log(b) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:39] 1 │ let b = []; console.log(b); let a = b.map(x => ({ ...x })); · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => { let x2 = { ...x }; return x2; }) · ─┬─ ──┬─ ─┬ · │ │ ╰── Map returns the spread here - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => { let x2 = { ...x }; let x3 = x2; return x3; }) · ─┬─ ──┬─ ─┬ · │ │ ╰── Map returns the spread here - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] @@ -128,7 +142,7 @@ source: crates/oxc_linter/src/tester.rs · ╰── This map call spreads an object 2 │ let y = { ...x }; · ──┬─ - · ╰── It should be mutated in place + · ╰── This spread allocates a new value on each iteration 3 │ if (y.foo) { ╰──── ╭─[no_map_spread.tsx:6:21] @@ -138,166 +152,185 @@ source: crates/oxc_linter/src/tester.rs · ╰── Map returns the spread here 7 │ } ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => someCond ? { ...x, foo: true } : { ...x, foo: false }) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => someCond ? { ...x, foo: true } : { ...x, foo: false }) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map( ({ x, y }) => ({ ...(cond ? x : y) }) ) · ─┬─ ────────┬──────── - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:13] 1 │ const b = a.map((x, i) => y ? { ...x, i } : x) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:13] 1 │ const b = a.map((x, i) => y ? x : { ...x, i }) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(x => (0, { ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map(({ x, y }) => (x ?? { ...y })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ let a = b.map((x => ({ ...x }))) as MyCustomMapper · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:7] 1 │ foo().map(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:8] 1 │ foo[1].map(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:11] 1 │ foo?.bar?.map(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:14] 1 │ (foo ?? bar).map(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:10] 1 │ obj.#foo.map(x => ({ ...x })) · ─┬─ ──┬─ - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:3] 1 │ a.map(x => ({ ...x.y })) · ─┬─ ───┬── - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:3] 1 │ a.map(x => ({ ...x[y] })) · ─┬─ ───┬─── - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:3] 1 │ a.map(x => ({ ...(x ?? y) })) · ─┬─ ─────┬───── - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:28] 1 │ function foo(a) { return a.map(x => ({ ...(x ?? y) })) } · ─┬─ ─────┬───── - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required. ⚠ oxc(no-map-spread): Spreading to modify object properties in `map` calls is inefficient ╭─[no_map_spread.tsx:1:20] 1 │ const foo = a => a.map(x => ({ ...(x ?? y) })) · ─┬─ ─────┬───── - · │ ╰── It should be mutated in place + · │ ╰── This spread allocates a new value on each iteration · ╰── This map call spreads an object ╰──── - help: Consider using `Object.assign` instead + help: If in-place mutation is acceptable, use `Object.assign` or direct property assignment instead of spreading + note: `Object.assign` mutates the first argument. Disable this rule if copy-on-write behavior is required.