Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5da0c85
chore(linter): no-unused-vars boilerplate
DonIsaac Jul 23, 2023
c7a1958
feat(linter): add no-unused-vars options parsing
DonIsaac Jul 23, 2023
bfa819a
refactor(linter): regex option parsing, clippy fixes
DonIsaac Jul 23, 2023
03d3358
feat: start reference resolution steps
DonIsaac Jul 23, 2023
fef74ce
fix(linter): start var impl
DonIsaac Jul 24, 2023
56b4c41
Merge branch 'main' of https://github.com/Boshen/oxc into don/feat/no…
DonIsaac Jul 25, 2023
3603c40
test(linter): more no-unused-vars test cases
DonIsaac Jul 25, 2023
a974932
test(linter): start enabling eslint test cases
DonIsaac Jul 26, 2023
d196582
feat(linter/no-unused-vars): support exports
DonIsaac Jul 27, 2023
f2b8019
test(linter/no-unused-vars): add more fail cases
DonIsaac Jul 27, 2023
6e413b5
feat(linter/no-unused-vars): support class decls
DonIsaac Jul 27, 2023
7a3d490
feat(linter/no-unused-vars): start supporting args
DonIsaac Jul 27, 2023
b3177d7
Merge branch 'main' of https://github.com/Boshen/oxc into don/feat/no…
DonIsaac Jul 27, 2023
23562d0
refactor(linter/no-unused-vars): remove reliance on experimental feat…
DonIsaac Jul 27, 2023
e6a6bf6
feat(linter/no-unused-args): support after-used
DonIsaac Jul 28, 2023
a473a28
refactor(linter/no-unused-vars): cleanup
DonIsaac Jul 28, 2023
5084705
feat(linter/no-unused-vars): support caught errors
DonIsaac Jul 28, 2023
477c61e
test(linter/no-unused-vars): enable more passing tests
DonIsaac Jul 28, 2023
36c9dd5
fix(linter/no-unused-vars): support var: local option
DonIsaac Jul 28, 2023
f34e746
fix(linter/no-unused-vars): support exported variables
DonIsaac Jul 28, 2023
ed59097
feat(linter/no-unused-vars): start recursive binding check
DonIsaac Jul 28, 2023
f284f56
Merge branch 'main' of https://github.com/Boshen/oxc into don/feat/no…
DonIsaac Jul 28, 2023
410d739
feat(linter/no-unused-vars): arr/obj unpacking
DonIsaac Jul 29, 2023
3730312
fix(linter/no-unused-vars): arr unpacking in function args
DonIsaac Jul 29, 2023
e5a9007
style(linter): fix clippy lints
DonIsaac Jul 29, 2023
8966874
style(linter/no-unused-vars): fix clippy lints
DonIsaac Jul 29, 2023
a886407
test(linter/no-unused-vars): report unused imports, add a lot of fail…
DonIsaac Jul 29, 2023
dcf2e40
test(linter/no-unused-vars): more testing
DonIsaac Jul 29, 2023
def7d6b
feat(linter/no-unused-vars): support ignore rest siblings
DonIsaac Jul 29, 2023
0267425
Merge branch 'main' of https://github.com/Boshen/oxc into don/feat/no…
DonIsaac Jul 29, 2023
8c6d70f
fix(linter/no-unused-vars): more progress
DonIsaac Jul 31, 2023
dd16c82
Merge branch 'main' of https://github.com/Boshen/oxc into don/feat/no…
DonIsaac Jul 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(linter/no-unused-vars): arr/obj unpacking
  • Loading branch information
DonIsaac committed Jul 29, 2023
commit 410d739631e61868e37095290328e327b8a78dd8
92 changes: 62 additions & 30 deletions crates/oxc_linter/src/rules/eslint/no_unused_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,11 @@ impl NoUnusedVars {
) -> Option<Span> {
match &id.kind {
| BindingPatternKind::BindingIdentifier(id) => {
debug_assert!(id.name == name, "Expected BindingIdentifier to have name '{name}', but it had name '{}'", id.name);
if self.is_ignored_var(name) {
// debug_assert!(id.name == name, "Expected BindingIdentifier to
// have name '{name}', but it had name '{}'", id.name);
// id might not be name if we're in a recursive call from an
// array or object pattern
if &id.name != name || self.is_ignored_var(name) {
None
} else {
Some(id.span)
Expand All @@ -399,9 +402,41 @@ impl NoUnusedVars {
name,
&id.left,
ctx
) ,
| BindingPatternKind::ArrayPattern(arr) => todo!(),
| BindingPatternKind::ObjectPattern(obj) => todo!()
),
| BindingPatternKind::ArrayPattern(arr) => {
for el in arr.elements.iter() {
let Some(el) = el else { continue };
if let Some(id) = el.kind.identifier() {
if &id.name != name {
continue
}
// let _id_name = id.name.as_str();
if !self.is_ignored_array_destructured(&id.name) {
return Some(id.span)
}
} else {
return self.check_unused_binding_pattern(symbol_id, name, el, ctx);
}
}
None
},
| BindingPatternKind::ObjectPattern(obj) => {
for el in obj.properties.iter() {
let maybe_span = self.check_unused_binding_pattern(symbol_id, name, &el.value, ctx);
if maybe_span.is_some() {
return maybe_span
}
// match el.key {
// PropertyKey::Identifier(id) => {
// return Some(id.span)
// },
// _ => todo!()
// }
// let maybe_span = self.check_unused_binding_pattern(symbol_id, name, id, ctx)
// if el.name
}
None
}
}
}

Expand All @@ -413,28 +448,27 @@ impl NoUnusedVars {
) {
let name = ctx.symbols().get_name(symbol_id);

// match decl.id.kind {
// | BindingPatternKind::BindingIdentifier(id)
// | BindingPatternKind::AssignmentPattern(id) => todo!(),
// | BindingPatternKind::ArrayPattern(arr) => todo!()
// | BindingPatternKind::ObjectPattern(obj) => todo!()
// };
if
// allow unused vars that are ignored
self.is_ignored_var(name) ||
// Allow `var x` for "vars": "local" b/c var keyword has side effects
(self.vars == VarsOption::Local && decl.kind.is_var())
{
if self.vars == VarsOption::Local && decl.kind.is_var() {
return;
}
let var_decl_node = ctx.semantic().symbol_declaration(symbol_id);

// skip unused variable declarations
if self.is_ignored_var(name) {
return;
}

// allow ignored args
let Some(span) = self.check_unused_binding_pattern(symbol_id, name, &decl.id, ctx) else { return };

// ignore exported vars
let var_decl_node = ctx.semantic().symbol_declaration(symbol_id);
match ctx.nodes().parent_node(var_decl_node.id()) {
Some(parent) if Self::is_exported(parent, ctx) => return,
_ => { /* noop */ }
}

ctx.diagnostic(NoUnusedVarsDiagnostic::decl(name.clone(), decl.span));
ctx.diagnostic(NoUnusedVarsDiagnostic::decl(name.clone(), span));
}

fn check_unused_catch_clause<'a>(
Expand Down Expand Up @@ -957,8 +991,6 @@ mod tests {
// after used
("function foo(a, b) { return b }; foo()", None),
("function foo(a, b) { return b }; foo()", after_used),
// ("export function foo() { return }", None),
// ("export default function foo() { return }", None),
];
let fail = vec![
("function foo(a) { return }; foo()", None),
Expand Down Expand Up @@ -1094,12 +1126,12 @@ mod tests {
("function foo() {var foo = 1; return foo}; foo();", None),
("function foo(foo) {return foo}; foo(1);", None),
("function foo() {function foo() {return 1;}; return foo()}; foo();", None),
// ("const x = 1; const [y = x] = []; foo(y);", None),
// ("const x = 1; const {y = x} = {}; foo(y);", None),
// ("const x = 1; const {z: [y = x]} = {}; foo(y);", None),
// ("const x = []; const {z: [y] = x} = {}; foo(y);", None),
// ("const x = 1; let y; [y = x] = []; foo(y);", None),
// ("const x = 1; let y; ({z: [y = x]} = {}); foo(y);", None),
("const x = 1; const [y = x] = []; foo(y);", None),
("const x = 1; const {y = x} = {}; foo(y);", None),
("const x = 1; const {z: [y = x]} = {}; foo(y);", None),
("const x = []; const {z: [y] = x} = {}; foo(y);", None),
("const x = 1; let y; [y = x] = []; foo(y);", None),
("const x = 1; let y; ({z: [y = x]} = {}); foo(y);", None),
// ("const x = []; let y; ({z: [y] = x} = {}); foo(y);", None),
// ("const x = 1; function foo(y = x) { bar(y); } foo();", None),
// ("const x = 1; function foo({y = x} = {}) { bar(y); } foo();", None),
Expand Down Expand Up @@ -1141,10 +1173,10 @@ mod tests {
"var [ firstItemIgnored, secondItem ] = items;\nconsole.log(secondItem);",
Some(serde_json::json!([{ "vars": "all", "varsIgnorePattern": "[iI]gnored" }])),
),
(
"const [ a, _b, c ] = items;\nconsole.log(a+c);",
Some(serde_json::json!([{ "destructuredArrayIgnorePattern": "^_" }])),
),
// (
// "const [ a, _b, c ] = items;\nconsole.log(a+c);",
// Some(serde_json::json!([{ "destructuredArrayIgnorePattern": "^_" }])),
// ),
// (
// "const [ [a, _b, c] ] = items;\nconsole.log(a+c);",
// Some(serde_json::json!([{ "destructuredArrayIgnorePattern": "^_" }])),
Expand Down
26 changes: 13 additions & 13 deletions crates/oxc_linter/src/snapshots/no_unused_vars.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,91 +5,91 @@ expression: no_unused_vars
⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ var a=10
· ────
· ─
╰────
help: a is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ function f() { var a = 1; return function(){ f(a *= 2); }; }
· ─────
· ─
╰────
help: a is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ function f() { var a = 1; return function(){ f(++a); }; }
· ─────
· ─
╰────
help: a is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; x++, 0;
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; 0, x++;
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; 0, (1, x++);
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; foo = (x++, 0);
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; foo = ((0, x++), 0);
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; x += 1, 0;
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; 0, x += 1;
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; 0, (1, x += 1);
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; foo = (x += 1, 0);
· ─────
· ─
╰────
help: x is declared but never used

⚠ eslint(no-unused-vars): Unused variables are not allowed
╭─[no_unused_vars.tsx:1:1]
1 │ let x = 0; foo = ((0, x += 1), 0);
· ─────
· ─
╰────
help: x is declared but never used

Expand Down