Overview
The no_unused_vars rule has a partial but functional fixer implementation. Currently, all fixes are classified as "dangerous suggestions" because they modify code semantics. This meta issue tracks improvements to achieve near-complete auto-fix coverage.
Goal: Enable auto-fixing for basically every no_unused_vars diagnostic.
Current State
Supported
| Category |
Example |
Fix |
| Single import |
import foo from './foo' |
Delete entire import |
| Namespace import |
import * as foo from './foo' |
Delete entire import |
| Named import (single) |
import { Foo } from './foo' |
Delete entire import |
| Named import (multi) |
import { foo, bar } from './foo'; bar() |
Remove unused specifier |
| Type import |
import { type foo, bar } from './foo'; bar() |
Remove unused specifier |
| Simple declaration |
let a = 1 |
Delete declaration |
| Multi-declarator |
let a = 1, b = 2 (a unused) |
Remove unused declarator |
| Rename with refs |
let x = 1; x = 2 |
Rename to _x |
| Object destructure |
const { a, b } = obj; f(b) |
Remove unused property |
| Array destructure |
const [a, b] = arr; f(b) |
Replace with hole [, b] |
| For-of/for-in loops |
for (const unused of arr) {} |
Rename to _unused |
| Catch parameters |
catch (e) {} |
Remove the unused catch parameter |
| Function parameters |
function f(unused) {} |
Rename to _unused |
Unsupported
| Category |
Example |
Proposed Fix |
Tracking Issue |
| Binding rest elements |
const [...rest] = arr |
Rename to _rest |
#TBD |
| Type parameters |
type Foo<T> = {} |
Rename to _T |
#TBD |
| TS Namespaces |
namespace Foo {} |
Delete or rename |
#TBD |
| TS Interfaces |
interface Foo {} |
Delete or rename |
#TBD |
Complex varsIgnorePattern |
Patterns other than ^_ |
Support more patterns |
#TBD |
using declarations |
using x = getResource() |
TBD (side effects) |
#TBD |
Known Bugs to Fix
1. Multi-declarator incomplete cleanup
When multiple declarators are all unused, only the first is deleted:
// Input
let a = 1, b = 2; // both unused
// Current output (incorrect)
let b = 2;
// Expected output
// (entire statement deleted)
Location: fix_vars.rs
2. Destructures in multi-declarator statements
// Input
const l = "", { e } = r; // l unused
// Current output (incorrect)
const { e } = r;
// Should handle this case properly
Location: fix_vars.rs
Implementation Roadmap
Phase 1: Low-hanging fruit
Phase 2: TypeScript support
Phase 3: Advanced patterns
Phase 4: Edge cases
Notes
Why fixes are "dangerous"
All fixes are marked as dangerous_suggestion because:
- Removing code changes program semantics
- Initializers may have side effects
- Some "unused" variables are intentional (e.g., documentation, future use)
Current safety checks
- Root-scope function expressions are skipped (often intentional)
- Await expressions are skipped (side effects)
- Rename conflicts are resolved by appending numbers (
_x, _x0, _x1)
Contributing
Each sub-task should be its own PR. When implementing a new fixer:
- Add the fix logic in the appropriate
fixers/*.rs file
- Update the match arm in
mod.rs to call ctx.diagnostic_with_suggestion() instead of ctx.diagnostic()
- Add comprehensive tests in
tests/oxc.rs
- Ensure the fix is marked
.dangerously()
- Handle edge cases (side effects, naming conflicts, etc.)
Related
Overview
The
no_unused_varsrule has a partial but functional fixer implementation. Currently, all fixes are classified as "dangerous suggestions" because they modify code semantics. This meta issue tracks improvements to achieve near-complete auto-fix coverage.Goal: Enable auto-fixing for basically every
no_unused_varsdiagnostic.Current State
Supported
import foo from './foo'import * as foo from './foo'import { Foo } from './foo'import { foo, bar } from './foo'; bar()import { type foo, bar } from './foo'; bar()let a = 1let a = 1, b = 2(a unused)let x = 1; x = 2_xconst { a, b } = obj; f(b)const [a, b] = arr; f(b)[, b]for (const unused of arr) {}_unusedcatch (e) {}function f(unused) {}_unusedUnsupported
const [...rest] = arr_resttype Foo<T> = {}_Tnamespace Foo {}interface Foo {}varsIgnorePattern^_usingdeclarationsusing x = getResource()Known Bugs to Fix
1. Multi-declarator incomplete cleanup
When multiple declarators are all unused, only the first is deleted:
Location:
fix_vars.rs2. Destructures in multi-declarator statements
Location:
fix_vars.rsImplementation Roadmap
Phase 1: Low-hanging fruit
_parampattern)_epattern)Phase 2: TypeScript support
_Tpattern)Phase 3: Advanced patterns
varsIgnorePatternsupport beyond^_usingdeclaration handling (careful with side effects)Phase 4: Edge cases
Notes
Why fixes are "dangerous"
All fixes are marked as
dangerous_suggestionbecause:Current safety checks
_x,_x0,_x1)Contributing
Each sub-task should be its own PR. When implementing a new fixer:
fixers/*.rsfilemod.rsto callctx.diagnostic_with_suggestion()instead ofctx.diagnostic()tests/oxc.rs.dangerously()Related