Skip to content

Commit 4bc2650

Browse files
committed
refactor(linter): improve eslint/no-void (#11285)
- Add suggestion fix - Improve the documentation - Align the `allowAsStatement` option logic
1 parent 9eef4dd commit 4bc2650

File tree

2 files changed

+39
-17
lines changed

2 files changed

+39
-17
lines changed

crates/oxc_linter/src/rules/eslint/no_void.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use oxc_macros::declare_oxc_lint;
44
use oxc_span::Span;
55
use oxc_syntax::operator::UnaryOperator;
66

7-
use crate::{AstNode, context::LintContext, rule::Rule};
7+
use crate::{AstNode, ast_util::outermost_paren_parent, context::LintContext, rule::Rule};
88

99
fn no_void_diagnostic(span: Span) -> OxcDiagnostic {
1010
OxcDiagnostic::warn("Unexpected `void` operator")
@@ -20,11 +20,12 @@ pub struct NoVoid {
2020
declare_oxc_lint!(
2121
/// ### What it does
2222
///
23-
/// Disallow `void` operators.
23+
/// Disallows the use of the `void` operator.
2424
///
2525
/// Why is this bad
2626
///
27-
/// The `void` operator is often used to obtain the `undefined` primitive value, but it is unnecessary. You can use `undefined` directly instead.
27+
/// The `void` operator is often used to get `undefined`,
28+
/// but this is unnecessary because `undefined` can be used directly instead.
2829
///
2930
/// ### Examples
3031
///
@@ -40,10 +41,18 @@ declare_oxc_lint!(
4041
/// "foo.void()";
4142
/// "foo.void = bar";
4243
/// ```
44+
///
45+
/// ### Options
46+
///
47+
/// #### allowAsStatement
48+
///
49+
/// `{ type: boolean, default: false }`
50+
///
51+
/// If set to `true`, using `void` as a standalone statement is allowed.
4352
NoVoid,
4453
eslint,
4554
restriction,
46-
pending // TODO: suggestion
55+
suggestion
4756
);
4857

4958
impl Rule for NoVoid {
@@ -62,17 +71,16 @@ impl Rule for NoVoid {
6271
return;
6372
};
6473

65-
if let Some(kind) = ctx.nodes().parent_kind(node.id()) {
66-
if self.allow_as_statement && matches!(kind, AstKind::ExpressionStatement(_)) {
74+
if let Some(node) = outermost_paren_parent(node, ctx) {
75+
if self.allow_as_statement && matches!(node.kind(), AstKind::ExpressionStatement(_)) {
6776
return;
6877
}
6978
}
7079

7180
if unary_expr.operator == UnaryOperator::Void {
72-
ctx.diagnostic(no_void_diagnostic(Span::new(
73-
unary_expr.span.start,
74-
unary_expr.span.start + 4,
75-
)));
81+
ctx.diagnostic_with_suggestion(no_void_diagnostic(unary_expr.span), |fixer| {
82+
fixer.replace(unary_expr.span, "undefined")
83+
});
7684
}
7785
}
7886
}
@@ -88,6 +96,7 @@ fn test() {
8896
("delete foo;", None),
8997
("void 0", Some(serde_json::json!([{ "allowAsStatement": true }]))),
9098
("void(0)", Some(serde_json::json!([{ "allowAsStatement": true }]))),
99+
("(void 0)", Some(serde_json::json!([{ "allowAsStatement": true }]))),
91100
];
92101

93102
let fail = vec![
@@ -99,5 +108,18 @@ fn test() {
99108
("var foo = void 0", Some(serde_json::json!([{ "allowAsStatement": true }]))),
100109
];
101110

102-
Tester::new(NoVoid::NAME, NoVoid::PLUGIN, pass, fail).test_and_snapshot();
111+
let fix = vec![
112+
("void 0", "undefined", None),
113+
("void 0", "undefined", Some(serde_json::json!([{}]))),
114+
("void 0", "undefined", Some(serde_json::json!([{ "allowAsStatement": false }]))),
115+
("void(0)", "undefined", None),
116+
("var foo = void 0", "var foo = undefined", None),
117+
(
118+
"var foo = void 0",
119+
"var foo = undefined",
120+
Some(serde_json::json!([{ "allowAsStatement": true }])),
121+
),
122+
];
123+
124+
Tester::new(NoVoid::NAME, NoVoid::PLUGIN, pass, fail).expect_fix(fix).test_and_snapshot();
103125
}

crates/oxc_linter/src/snapshots/eslint_no_void.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,41 @@ source: crates/oxc_linter/src/tester.rs
44
eslint(no-void): Unexpected `void` operator
55
╭─[no_void.tsx:1:1]
66
1void 0
7-
· ────
7+
· ──────
88
╰────
99
help: Use `undefined` instead
1010

1111
eslint(no-void): Unexpected `void` operator
1212
╭─[no_void.tsx:1:1]
1313
1void 0
14-
· ────
14+
· ──────
1515
╰────
1616
help: Use `undefined` instead
1717

1818
eslint(no-void): Unexpected `void` operator
1919
╭─[no_void.tsx:1:1]
2020
1void 0
21-
· ────
21+
· ──────
2222
╰────
2323
help: Use `undefined` instead
2424

2525
eslint(no-void): Unexpected `void` operator
2626
╭─[no_void.tsx:1:1]
2727
1void(0)
28-
· ────
28+
· ───────
2929
╰────
3030
help: Use `undefined` instead
3131

3232
eslint(no-void): Unexpected `void` operator
3333
╭─[no_void.tsx:1:11]
3434
1var foo = void 0
35-
· ────
35+
· ──────
3636
╰────
3737
help: Use `undefined` instead
3838

3939
eslint(no-void): Unexpected `void` operator
4040
╭─[no_void.tsx:1:11]
4141
1var foo = void 0
42-
· ────
42+
· ──────
4343
╰────
4444
help: Use `undefined` instead

0 commit comments

Comments
 (0)