mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(linter/no-unused-vars): false positive for functions and classes in arrays (#6394)
Fixes a false positive when a function or class expression is an array element.
Found while linting Jest tests in an internal repo.
```js
import { stringify } from './custom-stringify';
test.each(['a', 1, function foo() {}])('When stringifying %p, matches the snapshot', input => {
expect(stringify(input)).toMatchSnapshot();
})
```
This commit is contained in:
parent
994b60b420
commit
e08f956c00
3 changed files with 59 additions and 1 deletions
|
|
@ -26,7 +26,13 @@ impl<'s, 'a> Symbol<'s, 'a> {
|
|||
|
||||
for parent in self.iter_parents() {
|
||||
match parent.kind() {
|
||||
AstKind::MemberExpression(_) | AstKind::ParenthesizedExpression(_) => {
|
||||
AstKind::MemberExpression(_) | AstKind::ParenthesizedExpression(_)
|
||||
// e.g. `const x = [function foo() {}]`
|
||||
// Only considered used if the array containing the symbol is used.
|
||||
| AstKind::ArrayExpressionElement(_)
|
||||
| AstKind::ExpressionArrayElement(_)
|
||||
| AstKind::ArrayExpression(_)
|
||||
=> {
|
||||
continue;
|
||||
}
|
||||
// Returned from another function. Definitely won't be the same
|
||||
|
|
@ -37,6 +43,9 @@ impl<'s, 'a> Symbol<'s, 'a> {
|
|||
// Function declaration is passed as an argument to another function.
|
||||
| AstKind::CallExpression(_) | AstKind::Argument(_)
|
||||
// e.g. `const x = { foo: function foo() {} }`
|
||||
// Allowed off-the-bat since objects being the only child of an
|
||||
// ExpressionStatement is rare, since you would need to wrap the
|
||||
// object in parentheses to avoid creating a block statement.
|
||||
| AstKind::ObjectProperty(_)
|
||||
// e.g. var foo = function bar() { }
|
||||
// we don't want to check for violations on `bar`, just `foo`
|
||||
|
|
|
|||
|
|
@ -689,6 +689,37 @@ fn test_imports() {
|
|||
.test_and_snapshot();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_used_declarations() {
|
||||
let pass = vec![
|
||||
// function declarations passed as arguments, used in assignments, etc. are used, even if they are
|
||||
// first put into an intermediate (e.g. an object or array)
|
||||
"arr.reduce(function reducer (acc, el) { return acc + el }, 0)",
|
||||
"console.log({ foo: function foo() {} })",
|
||||
"test.each([ function foo() {} ])('test some function', (fn) => { expect(fn(1)).toBe(1) })",
|
||||
"export default { foo() {} }",
|
||||
"const arr = [function foo() {}, function bar() {}]; console.log(arr[0]())",
|
||||
"const foo = function foo() {}; console.log(foo())",
|
||||
"const foo = function bar() {}; console.log(foo())",
|
||||
// Class expressions behave similarly
|
||||
"console.log([class Foo {}])",
|
||||
"export default { foo: class Foo {} }",
|
||||
"export const Foo = class Foo {}",
|
||||
"export const Foo = class Bar {}",
|
||||
"export const Foo = @SomeDecorator() class Foo {}",
|
||||
];
|
||||
let fail = vec![
|
||||
// array is not used, so the function is not used
|
||||
";[function foo() {}]",
|
||||
";[class Foo {}]",
|
||||
];
|
||||
|
||||
Tester::new(NoUnusedVars::NAME, pass, fail)
|
||||
.intentionally_allow_no_fix_tests()
|
||||
.with_snapshot_suffix("oxc-used-declarations")
|
||||
.test_and_snapshot();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exports() {
|
||||
let pass = vec![
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
---
|
||||
⚠ eslint(no-unused-vars): Function 'foo' is declared but never used.
|
||||
╭─[no_unused_vars.tsx:1:12]
|
||||
1 │ ;[function foo() {}]
|
||||
· ─┬─
|
||||
· ╰── 'foo' is declared here
|
||||
╰────
|
||||
help: Consider removing this declaration.
|
||||
|
||||
⚠ eslint(no-unused-vars): Class 'Foo' is declared but never used.
|
||||
╭─[no_unused_vars.tsx:1:9]
|
||||
1 │ ;[class Foo {}]
|
||||
· ─┬─
|
||||
· ╰── 'Foo' is declared here
|
||||
╰────
|
||||
help: Consider removing this declaration.
|
||||
Loading…
Reference in a new issue