Skip to content

Commit

Permalink
feat(linter) eslint plugin unicorn: empty-brace-spaces (#1249)
Browse files Browse the repository at this point in the history
New contributor here to an amazing project. I think I covered all the
cases where braces can be used.
Plugin: #684 

[Rule](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/empty-brace-spaces.md)

---------

Co-authored-by: Radu Baston <radu.baston@sectorlabs.ro>
  • Loading branch information
radu2147 and Radu Baston authored Nov 13, 2023
1 parent 97e0212 commit 76d4690
Show file tree
Hide file tree
Showing 3 changed files with 256 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 @@ -143,6 +143,7 @@ mod react {

mod unicorn {
pub mod catch_error_name;
pub mod empty_brace_spaces;
pub mod error_message;
pub mod filename_case;
pub mod new_for_builtins;
Expand Down Expand Up @@ -293,6 +294,7 @@ oxc_macros::declare_all_lint_rules! {
jest::valid_expect,
jest::valid_title,
unicorn::catch_error_name,
unicorn::empty_brace_spaces,
unicorn::error_message,
unicorn::filename_case,
unicorn::new_for_builtins,
Expand Down
137 changes: 137 additions & 0 deletions crates/oxc_linter/src/rules/unicorn/empty_brace_spaces.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use oxc_ast::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, AstNode, Fix};

#[derive(Debug, Error, Diagnostic)]
#[error("eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed")]
#[diagnostic(severity(warning), help("There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code."))]
struct EmptyBraceSpacesDiagnostic(#[label] pub Span);

#[derive(Debug, Default, Clone)]
pub struct EmptyBraceSpaces;

declare_oxc_lint!(
/// ### What it does
/// Removes the extra spaces or new line characters inside a pair of braces that does not contain additional code.
///
/// ### Why is this bad?
/// There should be no spaces inside a pair of braces as it affects the overall readability of the code.
///
/// ### Example
/// ```javascript
/// const a = { };
/// class A {
/// }
/// ```
EmptyBraceSpaces,
style
);

impl Rule for EmptyBraceSpaces {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
match node.kind() {
AstKind::StaticBlock(static_block) => {
let Span { start, end } = static_block.span;
if static_block.body.is_empty() && end - start > 9 {
// length of "static {}"
ctx.diagnostic_with_fix(EmptyBraceSpacesDiagnostic(static_block.span), || {
Fix::new("static {}", static_block.span)
});
}
}
AstKind::ObjectExpression(obj) => {
remove_empty_braces_spaces(ctx, obj.properties.is_empty(), obj.span);
}
AstKind::FunctionBody(fb) => {
remove_empty_braces_spaces(ctx, fb.is_empty(), fb.span);
}
AstKind::Class(class) => {
remove_empty_braces_spaces(ctx, class.body.body.is_empty(), class.body.span);
}
AstKind::BlockStatement(block_stmt) => {
remove_empty_braces_spaces(ctx, block_stmt.body.is_empty(), block_stmt.span);
}
AstKind::CatchClause(catch_clause) => {
remove_empty_braces_spaces(
ctx,
catch_clause.body.body.is_empty(),
catch_clause.body.span,
);
}
_ => (),
};
}
}

fn remove_empty_braces_spaces(ctx: &LintContext, is_empty_body: bool, span: Span) {
let Span { start, end } = span;
if is_empty_body && end - start > 2 {
// length of "{}"
ctx.diagnostic_with_fix(EmptyBraceSpacesDiagnostic(span), || Fix::new("{}", span));
}
}

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

let pass = vec![
"class A {\nstatic {}\n}",
"function b() {}",
"class A {}",
"const x = () => {};",
"with (foo) {}",
"for(let i = 0; i < 3; i += 1) {}",
"\nif(true){}",
"try{}catch{}",
"try{\nconsole.log(\'test\');\n} catch {}",
];

let fail = vec![
"try{console.log('Hello');}finally{ \n}",
"const a = {\n};",
"return {\n\n};",
"const x = () => {\n\n};",
"class A {\n}",
"function a(){ }",
"do { }while(true)",
"class A {\nstatic { }\n}",
"with (foo) { }",
"for(let i = 0; i <3; i += 1) {\n }",
"\nif (true) {\n}",
"\nif (true) { }",
"try{ }catch{ }",
"try{\nconsole.log(\'test\');\n}catch{ }\n",
];

let fix = vec![
("const a = {\n};", "const a = {};", None),
("return {\n\n};", "return {};", None),
("const x = () => {\n\n};", "const x = () => {};", None),
("class A {\n}", "class A {}", None),
("function a(){ }", "function a(){}", None),
("do { }while(true)", "do {}while(true)", None),
("class A {\nstatic { }\n}", "class A {\nstatic {}\n}", None),
("with (foo) { }", "with (foo) {}", None),
("\nif (true) {\n}", "\nif (true) {}", None),
("\nif (true) { }", "\nif (true) {}", None),
("try{ }catch{ }", "try{}catch{}", None),
("for(let i = 0; i <3; i += 1) {\n }", "for(let i = 0; i <3; i += 1) {}", None),
("try{console.log('Hello');}finally{ \n}", "try{console.log('Hello');}finally{}", None),
(
"try{\nconsole.log(\'test\');\n}catch{ }\n",
"try{\nconsole.log(\'test\');\n}catch{}\n",
None,
),
];

Tester::new_without_config(EmptyBraceSpaces::NAME, pass, fail)
.expect_fix(fix)
.test_and_snapshot();
}
117 changes: 117 additions & 0 deletions crates/oxc_linter/src/snapshots/empty_brace_spaces.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
source: crates/oxc_linter/src/tester.rs
expression: empty_brace_spaces
---
eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1 │ ╭─▶ try{console.log('Hello');}finally{
2 │ ╰─▶ }
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1 │ ╭─▶ const a = {
2 │ ╰─▶ };
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1 │ ╭─▶ return {
2 │ │
3 │ ╰─▶ };
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1 │ ╭─▶ const x = () => {
2 │ │
3 │ ╰─▶ };
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1 │ ╭─▶ class A {
2 │ ╰─▶ }
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1function a(){ }
· ───
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1do { }while(true)
· ───
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1class A {
2static { }
· ──────────
3 │ }
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1with (foo) { }
· ─────
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1 │ ╭─▶ for(let i = 0; i <3; i += 1) {
2 │ ╰─▶ }
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1
2 │ ╭─▶ if (true) {
3 │ ╰─▶ }
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1
2if (true) { }
· ─────
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1try{ }catch{ }
· ────
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:1:1]
1try{ }catch{ }
· ────
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.

eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed
╭─[empty_brace_spaces.tsx:2:1]
2console.log('test');
3 │ }catch{ }
· ───
╰────
help: There should be no spaces or new lines inside a pair of empty braces as it affects the overall readability of the code.


0 comments on commit 76d4690

Please sign in to comment.