Skip to content

Commit

Permalink
feat(linter): eslint: no-void (#2162)
Browse files Browse the repository at this point in the history
  • Loading branch information
eryue0220 authored Jan 25, 2024
1 parent a5d7c67 commit 3891430
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ mod eslint {
pub mod no_useless_catch;
pub mod no_useless_escape;
pub mod no_var;
pub mod no_void;
pub mod require_yield;
pub mod use_isnan;
pub mod valid_typeof;
Expand Down Expand Up @@ -379,6 +380,7 @@ oxc_macros::declare_all_lint_rules! {
eslint::no_useless_catch,
eslint::no_useless_escape,
eslint::no_var,
eslint::no_void,
eslint::require_yield,
eslint::use_isnan,
eslint::valid_typeof,
Expand Down
97 changes: 97 additions & 0 deletions crates/oxc_linter/src/rules/eslint/no_void.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use crate::{context::LintContext, rule::Rule, AstNode};

use oxc_ast::AstKind;
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::Error,
};
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use oxc_syntax::operator::UnaryOperator;

#[derive(Debug, Error, Diagnostic)]
#[error("eslint(no-void): Disallow `void` operators")]
#[diagnostic(severity(warning), help("Expected 'undefined' and instead saw 'void'."))]
struct NoVoidDiagnostic(#[label] pub Span);

#[derive(Debug, Default, Clone)]
pub struct NoVoid {
pub allow_as_statement: bool,
}

declare_oxc_lint!(
/// ### What it does
///
/// Disallow `void` operators.
///
/// ### Example
///
/// ```javascript
/// // error
/// void 0;
/// var foo = void 0;
///
/// // success
/// "var foo = bar()",
/// "foo.void()",
/// "foo.void = bar",
/// ```
NoVoid,
restriction,
);

impl Rule for NoVoid {
fn from_configuration(value: serde_json::Value) -> Self {
let allow_as_statement = value
.get(0)
.and_then(|config| config.get("allowAsStatement"))
.and_then(serde_json::Value::as_bool)
.unwrap_or(false);

Self { allow_as_statement }
}

fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::UnaryExpression(unary_expr) = node.kind() else {
return;
};

if let Some(kind) = ctx.nodes().parent_kind(node.id()) {
if self.allow_as_statement && matches!(kind, AstKind::ExpressionStatement(_)) {
return;
}
};

if unary_expr.operator == UnaryOperator::Void {
ctx.diagnostic(NoVoidDiagnostic(Span {
start: unary_expr.span.start,
end: unary_expr.span.start + 4,
}));
}
}
}

#[test]
fn test() {
use crate::tester::Tester;

let pass = vec![
("var foo = bar()", None),
("foo.void()", None),
("foo.void = bar", None),
("delete foo;", None),
("void 0", Some(serde_json::json!([{ "allowAsStatement": true }]))),
("void(0)", Some(serde_json::json!([{ "allowAsStatement": true }]))),
];

let fail = vec![
("void 0", None),
("void 0", Some(serde_json::json!([{}]))),
("void 0", Some(serde_json::json!([{ "allowAsStatement": false }]))),
("void(0)", None),
("var foo = void 0", None),
("var foo = void 0", Some(serde_json::json!([{ "allowAsStatement": true }]))),
];

Tester::new(NoVoid::NAME, pass, fail).test_and_snapshot();
}
48 changes: 48 additions & 0 deletions crates/oxc_linter/src/snapshots/no_void.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
source: crates/oxc_linter/src/tester.rs
assertion_line: 150
expression: no_void
---
eslint(no-void): Disallow `void` operators
╭─[no_void.tsx:1:1]
1void 0
· ────
╰────
help: Expected 'undefined' and instead saw 'void'.

eslint(no-void): Disallow `void` operators
╭─[no_void.tsx:1:1]
1void 0
· ────
╰────
help: Expected 'undefined' and instead saw 'void'.

eslint(no-void): Disallow `void` operators
╭─[no_void.tsx:1:1]
1void 0
· ────
╰────
help: Expected 'undefined' and instead saw 'void'.

eslint(no-void): Disallow `void` operators
╭─[no_void.tsx:1:1]
1void(0)
· ────
╰────
help: Expected 'undefined' and instead saw 'void'.

eslint(no-void): Disallow `void` operators
╭─[no_void.tsx:1:1]
1var foo = void 0
· ────
╰────
help: Expected 'undefined' and instead saw 'void'.

eslint(no-void): Disallow `void` operators
╭─[no_void.tsx:1:1]
1var foo = void 0
· ────
╰────
help: Expected 'undefined' and instead saw 'void'.


0 comments on commit 3891430

Please sign in to comment.