diff --git a/crates/oxc_linter/src/rules/unicorn/no_useless_spread.rs b/crates/oxc_linter/src/rules/unicorn/no_useless_spread.rs index 02bbed661..5456be3c0 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_useless_spread.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_useless_spread.rs @@ -20,9 +20,12 @@ use crate::{ #[derive(Debug, Error, Diagnostic)] enum NoUselessSpreadDiagnostic { - #[error("eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily.")] + #[error("eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new {1} unnecessarily.")] #[diagnostic(severity(warning), help("Consider removing the spread operator."))] - SpreadInList(#[label] Span), + SpreadInList(#[label] Span, &'static str), + #[error("eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily.")] + #[diagnostic(severity(warning), help("This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly.\nFor example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`."))] + SpreadInArguments(#[label] Span), #[error("eslint-plugin-unicorn(no-useless-spread): `{1}` accepts an iterable, so it's unnecessary to convert the iterable to an array.")] #[diagnostic(severity(warning), help("Consider removing the spread operator."))] IterableToArray(#[label] Span, String), @@ -134,6 +137,7 @@ fn check_useless_spread_in_list<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) { let Some(parent) = outermost_paren_parent(node, ctx) else { return; }; + if let AstKind::SpreadElement(spread_elem) = parent.kind() { let Some(parent_parent) = outermost_paren_parent(parent, ctx) else { return; @@ -142,20 +146,23 @@ fn check_useless_spread_in_list<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) { let span = Span { start: spread_elem.span.start, end: spread_elem.span.start + 3 }; match node.kind() { - // { ...{ } } AstKind::ObjectExpression(_) => { + // { ...{ } } if matches!(parent_parent.kind(), AstKind::ObjectExpression(_)) { - ctx.diagnostic(NoUselessSpreadDiagnostic::SpreadInList(span)); + ctx.diagnostic(NoUselessSpreadDiagnostic::SpreadInList(span, "object")); } } - // [ ...[ ] ] - AstKind::ArrayExpression(_) => { - if matches!(parent_parent.kind(), AstKind::ArrayExpressionElement(_)) - || matches!(parent_parent.kind(), AstKind::Argument(_)) - { - ctx.diagnostic(NoUselessSpreadDiagnostic::SpreadInList(span)); + AstKind::ArrayExpression(_) => match parent_parent.kind() { + // ...[ ] + AstKind::ArrayExpressionElement(_) => { + ctx.diagnostic(NoUselessSpreadDiagnostic::SpreadInList(span, "array")); } - } + // foo(...[ ]) + AstKind::Argument(_) => { + ctx.diagnostic(NoUselessSpreadDiagnostic::SpreadInArguments(span)); + } + _ => {} + }, _ => { unreachable!() } @@ -556,6 +563,12 @@ fn test() { r"[...await Promise.allSettled(foo)]", r"for (const foo of[...iterable]);", r"for (const foo of[...iterable2]);", + // https://github.com/getsentry/sentry/blob/9e4359030e7ec088aa3f47582f1afbad539a6377/static/app/views/performance/database/useAvailableDurationAggregates.tsx#L15-L17 + r" + if (organization.features?.includes('performance-database-view-percentiles')) { + availableAggregates.push(...['p50', 'p75', 'p95', 'p99']); + } + ", ]; Tester::new_without_config(NoUselessSpread::NAME, pass, fail).test_and_snapshot(); diff --git a/crates/oxc_linter/src/snapshots/no_useless_spread.snap b/crates/oxc_linter/src/snapshots/no_useless_spread.snap index 1e725e1f2..9114130ae 100644 --- a/crates/oxc_linter/src/snapshots/no_useless_spread.snap +++ b/crates/oxc_linter/src/snapshots/no_useless_spread.snap @@ -9,7 +9,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {...{a}} · ─── @@ -21,14 +21,16 @@ expression: no_useless_spread 1 │ foo(...[a]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[a]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -37,7 +39,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {...{a,}} · ─── @@ -49,14 +51,16 @@ expression: no_useless_spread 1 │ foo(...[a,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[a,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -65,7 +69,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {...{a,},} · ─── @@ -77,14 +81,16 @@ expression: no_useless_spread 1 │ foo(...[a,],) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[a,],) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -93,7 +99,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {...(( {a} ))} · ─── @@ -105,14 +111,16 @@ expression: no_useless_spread 1 │ foo(...(( [a] ))) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...(( [a] ))) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -121,7 +129,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {...{}} · ─── @@ -133,14 +141,16 @@ expression: no_useless_spread 1 │ foo(...[]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -154,14 +164,16 @@ expression: no_useless_spread 1 │ foo(...[,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -175,14 +187,16 @@ expression: no_useless_spread 1 │ foo(...[,,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[,,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -196,14 +210,16 @@ expression: no_useless_spread 1 │ foo(...[a, , b,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[a, , b,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -217,21 +233,24 @@ expression: no_useless_spread 1 │ foo(...[a, , b,],) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[a, , b,],) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ foo(...[,, ,(( a )), ,,(0, b), ,,]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -240,7 +259,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {a, ...{a, b}} · ─── @@ -252,14 +271,16 @@ expression: no_useless_spread 1 │ foo(a, ...[a, b]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(a, ...[a, b]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -268,7 +289,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {...{a, b}, b,} · ─── @@ -280,14 +301,16 @@ expression: no_useless_spread 1 │ foo(...[a, b], b,) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(...[a, b], b,) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] @@ -296,7 +319,7 @@ expression: no_useless_spread ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ const object = {a, ...{a, b}, b,} · ─── @@ -308,37 +331,39 @@ expression: no_useless_spread 1 │ foo(a, ...[a, b], b,) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Foo(a, ...[a, b], b,) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ ({a:1, ...{a: 2}}) · ─── ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ ({...{a:1}, ...{a: 2}}) · ─── ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ ({...{a:1}, ...{a: 2}}) · ─── ╰──── help: Consider removing the spread operator. - ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new object unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ ({[a]:1, ...{[a]: 2}}) · ─── @@ -350,14 +375,16 @@ expression: no_useless_spread 1 │ Promise.all(...[...iterable]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. ╭─[no_useless_spread.tsx:1:1] 1 │ new Map(...[...iterable]) · ─── ╰──── - help: Consider removing the spread operator. + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. ⚠ eslint-plugin-unicorn(no-useless-spread): `Map` accepts an iterable, so it's unnecessary to convert the iterable to an array. ╭─[no_useless_spread.tsx:1:1] @@ -674,4 +701,14 @@ expression: no_useless_spread ╰──── help: `for…of` can iterate over iterable, it's unnecessary to convert to an array. + ⚠ eslint-plugin-unicorn(no-useless-spread): Using a spread operator here creates a new array unnecessarily. + ╭─[no_useless_spread.tsx:2:1] + 2 │ if (organization.features?.includes('performance-database-view-percentiles')) { + 3 │ availableAggregates.push(...['p50', 'p75', 'p95', 'p99']); + · ─── + 4 │ } + ╰──── + help: This function accepts a rest parameter, it's unnecessary to create a new array and then spread it. Instead, supply the arguments directly. + For example, replace `foo(...[1, 2, 3])` with `foo(1, 2, 3)`. +