mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(linter): eslint-plugin-unicorn - no-empty-file (#1052)
This commit is contained in:
parent
8816649e3c
commit
db83f66ed0
3 changed files with 297 additions and 0 deletions
|
|
@ -142,6 +142,7 @@ mod unicorn {
|
|||
pub mod error_message;
|
||||
pub mod filename_case;
|
||||
pub mod no_console_spaces;
|
||||
pub mod no_empty_file;
|
||||
pub mod no_instanceof_array;
|
||||
pub mod no_thenable;
|
||||
pub mod no_unnecessary_await;
|
||||
|
|
@ -253,6 +254,7 @@ oxc_macros::declare_all_lint_rules! {
|
|||
unicorn::error_message,
|
||||
unicorn::filename_case,
|
||||
unicorn::no_console_spaces,
|
||||
unicorn::no_empty_file,
|
||||
unicorn::no_instanceof_array,
|
||||
unicorn::no_unnecessary_await,
|
||||
unicorn::no_thenable,
|
||||
|
|
|
|||
144
crates/oxc_linter/src/rules/unicorn/no_empty_file.rs
Normal file
144
crates/oxc_linter/src/rules/unicorn/no_empty_file.rs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
use oxc_ast::{ast::Statement, AstKind};
|
||||
use oxc_diagnostics::{
|
||||
miette::{self, Diagnostic},
|
||||
thiserror::Error,
|
||||
};
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.")]
|
||||
#[diagnostic(severity(warning), help("Delete this file or add some code to it."))]
|
||||
struct NoEmptyFileDiagnostic(#[label] pub Span);
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct NoEmptyFile;
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
///
|
||||
///
|
||||
/// Disallows any files only containing the following:
|
||||
/// - Whitespace
|
||||
/// - Comments
|
||||
/// - Directives
|
||||
/// - Empty statements
|
||||
/// - Empty blocks
|
||||
/// - Hashbang
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// Meaningless files clutter a codebase.
|
||||
///
|
||||
NoEmptyFile,
|
||||
correctness,
|
||||
);
|
||||
|
||||
impl Rule for NoEmptyFile {
|
||||
fn run_once(&self, ctx: &LintContext) {
|
||||
let Some(root) = ctx.nodes().iter().next() else { return };
|
||||
let AstKind::Program(program) = root.kind() else { return };
|
||||
|
||||
if program.body.iter().any(|node| !is_empty_stmt(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if has_triple_slash_directive(ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.diagnostic(NoEmptyFileDiagnostic(program.span));
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty_stmt(stmt: &Statement) -> bool {
|
||||
match stmt {
|
||||
Statement::BlockStatement(block_stmt) => {
|
||||
if block_stmt.body.is_empty() || block_stmt.body.iter().all(|node| is_empty_stmt(node))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
Statement::EmptyStatement(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn has_triple_slash_directive(ctx: &LintContext<'_>) -> bool {
|
||||
for (start, comment) in ctx.semantic().trivias().comments() {
|
||||
if !comment.is_single_line() {
|
||||
continue;
|
||||
}
|
||||
let span = Span::new(*start, comment.end());
|
||||
|
||||
let text = span.source_text(ctx.source_text());
|
||||
|
||||
if text.starts_with("///") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec![
|
||||
r#"const x = 0;"#,
|
||||
r#";; const x = 0;"#,
|
||||
r#"{{{;;const x = 0;}}}"#,
|
||||
r#"
|
||||
'use strict';
|
||||
const x = 0;
|
||||
"#,
|
||||
";;'use strict';",
|
||||
"{'use strict';}",
|
||||
r#"("use strict")"#,
|
||||
r#"`use strict`"#,
|
||||
r#"({})"#,
|
||||
r#"#!/usr/bin/env node
|
||||
console.log('done');
|
||||
"#,
|
||||
r#"false"#,
|
||||
r#"("")"#,
|
||||
r#"NaN"#,
|
||||
r#"undefined"#,
|
||||
r#"null"#,
|
||||
r#"[]"#,
|
||||
r#"(() => {})()"#,
|
||||
"(() => {})();",
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
r#""#,
|
||||
r#" "#,
|
||||
"\t",
|
||||
"\n",
|
||||
"\r",
|
||||
"\r\n",
|
||||
r#"
|
||||
|
||||
"#,
|
||||
r#"// comment"#,
|
||||
r#"/* comment */"#,
|
||||
r#"#!/usr/bin/env node"#,
|
||||
"'use asm';",
|
||||
"'use strict';",
|
||||
r#""use strict""#,
|
||||
r#""""#,
|
||||
r#";"#,
|
||||
r#";;"#,
|
||||
r#"{}"#,
|
||||
r#"{;;}"#,
|
||||
r#"{{}}"#,
|
||||
r#""";"#,
|
||||
r#""use strict";"#,
|
||||
];
|
||||
|
||||
Tester::new_without_config(NoEmptyFile::NAME, pass, fail).test_and_snapshot();
|
||||
}
|
||||
151
crates/oxc_linter/src/snapshots/no_empty_file.snap
Normal file
151
crates/oxc_linter/src/snapshots/no_empty_file.snap
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
expression: no_empty_file
|
||||
---
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │
|
||||
· ─
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │
|
||||
· ────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │
|
||||
· ─
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
0 │
|
||||
· ─
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │
|
||||
· ─
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ ╭─▶
|
||||
2 │ │
|
||||
3 │ ╰─▶
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ // comment
|
||||
· ──────────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ /* comment */
|
||||
· ─────────────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ #!/usr/bin/env node
|
||||
· ───────────────────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ 'use asm';
|
||||
· ──────────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ 'use strict';
|
||||
· ─────────────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ "use strict"
|
||||
· ────────────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ ""
|
||||
· ──
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ ;
|
||||
· ─
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ ;;
|
||||
· ──
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ {}
|
||||
· ──
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ {;;}
|
||||
· ────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ {{}}
|
||||
· ────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ "";
|
||||
· ───
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
⚠ eslint-plugin-unicorn(no-empty-file): Empty files are not allowed.
|
||||
╭─[no_empty_file.tsx:1:1]
|
||||
1 │ "use strict";
|
||||
· ─────────────
|
||||
╰────
|
||||
help: Delete this file or add some code to it.
|
||||
|
||||
|
||||
Loading…
Reference in a new issue