mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(linter/eslint/prefer-spread): report calls on non-member expressions (#28753)
`prefer-spread` now reports `(c ? a : b).apply(null, args)` and `m!.apply(null, args)`, matching ESLint. Check whether the applied expression is a member expression rather than requiring an identifier, while retaining receiver checks for method calls. Fixes #28728
This commit is contained in:
1 parent
28442f7246
commit
7a17a80d9e
2 files changed
+169
-9
No files matched your search
@@ -106,10 +106,10 @@ fn check_eslint_prefer_spread(call_expr: &CallExpression, ctx: &LintContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
let applied = callee.object().without_parentheses();
|
||||
let applied = callee.object().get_inner_expression();
|
||||
|
||||
if args0.is_null_or_undefined() {
|
||||
if !matches!(applied, Expression::Identifier(_)) {
|
||||
if as_member_expression_without_chain_expression(applied).is_some() {
|
||||
return;
|
||||
}
|
||||
} else if let Some(applied) = as_member_expression_without_chain_expression(applied) {
|
||||
@@ -138,13 +138,17 @@ fn check_eslint_prefer_spread(call_expr: &CallExpression, ctx: &LintContext) {
|
||||
fn as_member_expression_without_chain_expression<'a>(
|
||||
expr: &'a Expression,
|
||||
) -> Option<&'a MemberExpression<'a>> {
|
||||
match expr {
|
||||
Expression::ChainExpression(chain_expr) => match chain_expr.expression {
|
||||
match_member_expression!(ChainElement) => chain_expr.expression.as_member_expression(),
|
||||
_ => None,
|
||||
},
|
||||
match_member_expression!(Expression) => expr.as_member_expression(),
|
||||
_ => None,
|
||||
let mut expr = expr;
|
||||
loop {
|
||||
match expr {
|
||||
Expression::ChainExpression(chain_expr) => match &chain_expr.expression {
|
||||
ChainElement::TSNonNullExpression(non_null) => {
|
||||
expr = non_null.expression.get_inner_expression();
|
||||
}
|
||||
_ => return chain_expr.expression.as_member_expression(),
|
||||
},
|
||||
_ => return expr.as_member_expression(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +173,18 @@ fn test() {
|
||||
"(a?.b).c.foo.apply(a?.b.c, args);",
|
||||
"a?.b.c.foo.apply((a?.b).c, args);",
|
||||
"class C { #apply; foo() { foo.#apply(undefined, args); } }",
|
||||
"(c ? a : b).apply(obj, args);",
|
||||
"(obj.foo).apply(null, args);",
|
||||
"(obj?.foo).apply(null, args);",
|
||||
"(obj.foo as typeof b).apply(null, args);",
|
||||
"obj.foo!.apply(null, args);",
|
||||
"(obj.foo satisfies typeof b).apply(null, args);",
|
||||
"(obj.foo as typeof b).apply(other, args);",
|
||||
"(obj.foo!)?.apply(null, args);",
|
||||
"(obj?.foo!).apply(null, args);",
|
||||
"(obj?.foo!)!.apply(null, args);",
|
||||
"(obj.foo<number>).apply(null, args);",
|
||||
"obj[key]!.apply(null, args);",
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
@@ -192,6 +208,24 @@ fn test() {
|
||||
"(a?.b.c).foo.apply(a?.b.c, args);",
|
||||
"(a?.b).c.foo.apply((a?.b).c, args);",
|
||||
"class C { #foo; foo() { obj.#foo.apply(obj, args); } }",
|
||||
"(c ? a : b).apply(null, args);",
|
||||
"m!.apply(null, args);",
|
||||
"(a as typeof b).apply(null, args);",
|
||||
"(a satisfies typeof b).apply(null, args);",
|
||||
"(c ? a : b).apply(undefined, args);",
|
||||
"((a)).apply(void 0, args);",
|
||||
"(a, b).apply(null, args);",
|
||||
"(() => {}).apply(null, args);",
|
||||
"(function() {}).apply(null, args);",
|
||||
"getFunc().apply(null, args);",
|
||||
"(obj.foo as typeof b).apply(obj, args);",
|
||||
"obj.foo!.apply(obj, args);",
|
||||
"(obj.foo satisfies typeof b).apply(obj, args);",
|
||||
"(obj.foo!)?.apply(obj, args);",
|
||||
"(obj?.foo!).apply(obj, args);",
|
||||
"(obj?.foo!)!.apply(obj, args);",
|
||||
"(obj.foo<number>).apply(obj, args);",
|
||||
"obj[key]!.apply(obj, args);",
|
||||
];
|
||||
|
||||
Tester::new(PreferSpread::NAME, PreferSpread::PLUGIN, pass, fail).test_and_snapshot();
|
||||
|
||||
@@ -128,3 +128,129 @@ source: crates/oxc_linter/src/tester.rs
|
||||
· ─────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (c ? a : b).apply(null, args);
|
||||
· ─────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ m!.apply(null, args);
|
||||
· ────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (a as typeof b).apply(null, args);
|
||||
· ─────────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (a satisfies typeof b).apply(null, args);
|
||||
· ────────────────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (c ? a : b).apply(undefined, args);
|
||||
· ──────────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ ((a)).apply(void 0, args);
|
||||
· ─────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (a, b).apply(null, args);
|
||||
· ────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (() => {}).apply(null, args);
|
||||
· ────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (function() {}).apply(null, args);
|
||||
· ─────────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ getFunc().apply(null, args);
|
||||
· ───────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (obj.foo as typeof b).apply(obj, args);
|
||||
· ──────────────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ obj.foo!.apply(obj, args);
|
||||
· ─────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (obj.foo satisfies typeof b).apply(obj, args);
|
||||
· ─────────────────────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (obj.foo!)?.apply(obj, args);
|
||||
· ────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (obj?.foo!).apply(obj, args);
|
||||
· ────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (obj?.foo!)!.apply(obj, args);
|
||||
· ─────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ (obj.foo<number>).apply(obj, args);
|
||||
· ──────────────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
|
||||
⚠ eslint(prefer-spread): Use spread operators instead of `.apply()`.
|
||||
╭─[prefer_spread.tsx:1:1]
|
||||
1 │ obj[key]!.apply(obj, args);
|
||||
· ──────────────────────────
|
||||
╰────
|
||||
help: Replace `.apply()` with spread syntax (`...args`).
|
||||
Reference in new issue
Block a user