mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(linter): no-empty
This commit is contained in:
parent
0bf8f817f5
commit
f72c96270e
3 changed files with 83 additions and 0 deletions
|
|
@ -1,6 +1,8 @@
|
|||
mod no_debugger;
|
||||
mod no_empty;
|
||||
|
||||
pub use no_debugger::NoDebugger;
|
||||
pub use no_empty::NoEmpty;
|
||||
use oxc_ast::AstKind;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
|
|
@ -8,12 +10,14 @@ use crate::{context::LintContext, rule::Rule};
|
|||
#[derive(Debug, Clone)]
|
||||
pub enum RuleEnum {
|
||||
NoDebugger(NoDebugger),
|
||||
NoEmpty(NoEmpty),
|
||||
}
|
||||
|
||||
impl RuleEnum {
|
||||
pub fn run<'a>(&self, kind: AstKind<'a>, ctx: &LintContext<'a>) {
|
||||
match self {
|
||||
Self::NoDebugger(rule) => rule.run(kind, ctx),
|
||||
Self::NoEmpty(rule) => rule.run(kind, ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ impl Rule for NoDebugger {
|
|||
fn test() {
|
||||
use crate::rules::RuleEnum;
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec!["var test = { debugger: 1 }; test.debugger;"];
|
||||
|
||||
let fail = vec!["if (foo) debugger"];
|
||||
|
|
|
|||
78
crates/oxc_linter/src/rules/no_empty.rs
Normal file
78
crates/oxc_linter/src/rules/no_empty.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
use oxc_ast::{AstKind, Span};
|
||||
use oxc_diagnostics::{
|
||||
miette::{self, Diagnostic},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint(no-empty): Disallow empty block statements")]
|
||||
#[diagnostic(severity(warning), help("Add comments inside {0} statement"))]
|
||||
struct NoEmptyDiagnostic(&'static str, #[label("Empty {0} statement")] pub Span);
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct NoEmpty;
|
||||
|
||||
impl Rule for NoEmpty {
|
||||
fn run<'a>(&self, kind: AstKind<'a>, ctx: &LintContext<'a>) {
|
||||
match kind {
|
||||
AstKind::BlockStatement(block) if block.body.is_empty() => {
|
||||
// TODO: check comment
|
||||
ctx.diagnostic(NoEmptyDiagnostic("block", block.span));
|
||||
}
|
||||
AstKind::SwitchStatement(switch) if switch.cases.is_empty() => {
|
||||
ctx.diagnostic(NoEmptyDiagnostic("switch", switch.span));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::rules::RuleEnum;
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec![
|
||||
"if (foo) { bar() }",
|
||||
"while (foo) { bar() }",
|
||||
"for (;foo;) { bar() }",
|
||||
"try { foo() } catch (ex) { foo() }",
|
||||
"switch(foo) {case 'foo': break;}",
|
||||
"(function() { }())",
|
||||
"var foo = () => {};",
|
||||
"function foo() { }",
|
||||
"if (foo) {/* empty */}",
|
||||
"while (foo) {/* empty */}",
|
||||
"for (;foo;) {/* empty */}",
|
||||
"try { foo() } catch (ex) {/* empty */}",
|
||||
"try { foo() } catch (ex) {// empty\n}",
|
||||
"try { foo() } finally {// empty\n}",
|
||||
"try { foo() } finally {// test\n}",
|
||||
"try { foo() } finally {\n \n // hi i am off no use\n}",
|
||||
"try { foo() } catch (ex) {/* test111 */}",
|
||||
"if (foo) { bar() } else { // nothing in me \n}",
|
||||
"if (foo) { bar() } else { /**/ \n}",
|
||||
"if (foo) { bar() } else { // \n}",
|
||||
"try { foo(); } catch (ex) {}",
|
||||
"try { foo(); } catch (ex) {} finally { bar(); }",
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
"try {} catch (ex) {throw ex}",
|
||||
"try { foo() } catch (ex) {}",
|
||||
"try { foo() } catch (ex) {throw ex} finally {}",
|
||||
"if (foo) {}",
|
||||
"while (foo) {}",
|
||||
"for (;foo;) {}",
|
||||
"switch(foo) {}",
|
||||
"switch (foo) { /* empty */ }",
|
||||
"try {} catch (ex) {}",
|
||||
"try { foo(); } catch (ex) {} finally {}",
|
||||
"try {} catch (ex) {} finally {}",
|
||||
"try { foo(); } catch (ex) {} finally {}",
|
||||
];
|
||||
|
||||
Tester::new("no-empty", RuleEnum::NoEmpty(NoEmpty), pass, fail).test_and_snapshot();
|
||||
}
|
||||
Loading…
Reference in a new issue