mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(linter): unicorn/switch-cases-braces support options (#8704)
close #8492
This commit is contained in:
parent
6589c3bbb3
commit
e8e69179d1
2 changed files with 102 additions and 30 deletions
|
|
@ -5,16 +5,33 @@ use oxc_span::{GetSpan, Span};
|
|||
|
||||
use crate::{context::LintContext, rule::Rule, AstNode};
|
||||
|
||||
fn switch_case_braces_diagnostic(span: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn(
|
||||
" Empty switch case shouldn't have braces and not-empty case should have braces around it.",
|
||||
)
|
||||
.with_help("There is less visual clutter for empty cases and proper scope for non-empty cases.")
|
||||
#[derive(Clone, Copy)]
|
||||
enum Diagnostic {
|
||||
EmptyClause,
|
||||
MissingBraces,
|
||||
UnnecessaryBraces,
|
||||
}
|
||||
|
||||
fn switch_case_braces_diagnostic(span: Span, diagnostic_type: Diagnostic) -> OxcDiagnostic {
|
||||
(match diagnostic_type {
|
||||
Diagnostic::EmptyClause => OxcDiagnostic::warn("Unexpected braces in empty case clause.")
|
||||
.with_help("Remove braces in empty case clause."),
|
||||
Diagnostic::MissingBraces => OxcDiagnostic::warn("Missing braces in case clause.")
|
||||
.with_help("Add Braces for case clause."),
|
||||
Diagnostic::UnnecessaryBraces => OxcDiagnostic::warn("Unnecessary braces in case clause.")
|
||||
.with_help("Remove Braces for case clause."),
|
||||
})
|
||||
.with_label(span)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct SwitchCaseBraces;
|
||||
pub struct SwitchCaseBraces {
|
||||
// true - "always" (default)
|
||||
// - Always report when clause is not a BlockStatement
|
||||
// false - "avoid"
|
||||
// - Only allow braces when there are variable declaration or function declaration which requires a scope.
|
||||
always_braces: bool,
|
||||
}
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
|
|
@ -41,6 +58,12 @@ declare_oxc_lint!(
|
|||
);
|
||||
|
||||
impl Rule for SwitchCaseBraces {
|
||||
fn from_configuration(value: serde_json::Value) -> Self {
|
||||
let always = value.get(0).map_or(true, |v| v.as_str() != Some("avoid"));
|
||||
|
||||
Self { always_braces: always }
|
||||
}
|
||||
|
||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
let AstKind::SwitchStatement(switch) = node.kind() else {
|
||||
return;
|
||||
|
|
@ -56,13 +79,54 @@ impl Rule for SwitchCaseBraces {
|
|||
Statement::BlockStatement(case_block) => {
|
||||
if case_block.body.is_empty() {
|
||||
ctx.diagnostic_with_fix(
|
||||
switch_case_braces_diagnostic(case_block.span),
|
||||
switch_case_braces_diagnostic(
|
||||
case_block.span,
|
||||
Diagnostic::EmptyClause,
|
||||
),
|
||||
|fixer| fixer.delete_range(case_block.span),
|
||||
);
|
||||
}
|
||||
|
||||
if !self.always_braces
|
||||
&& !case_block.body.iter().any(|stmt| {
|
||||
matches!(
|
||||
stmt,
|
||||
Statement::VariableDeclaration(_)
|
||||
| Statement::FunctionDeclaration(_)
|
||||
)
|
||||
})
|
||||
{
|
||||
ctx.diagnostic_with_fix(
|
||||
switch_case_braces_diagnostic(
|
||||
case_block.span(),
|
||||
Diagnostic::UnnecessaryBraces,
|
||||
),
|
||||
|fixer| {
|
||||
fixer.replace(
|
||||
case_block.span,
|
||||
fixer.source_range(Span::new(
|
||||
case_block.span.start + 1,
|
||||
case_block.span.end - 1,
|
||||
)),
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Statement::EmptyStatement(_) => {}
|
||||
_ => {
|
||||
if !self.always_braces
|
||||
&& !&case.consequent.iter().any(|stmt| {
|
||||
matches!(
|
||||
stmt,
|
||||
Statement::VariableDeclaration(_)
|
||||
| Statement::FunctionDeclaration(_)
|
||||
)
|
||||
})
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(first_statement) = &case.consequent.first() else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -74,7 +138,10 @@ impl Rule for SwitchCaseBraces {
|
|||
Span::new(first_statement.span().start, last_statement.span().end);
|
||||
|
||||
ctx.diagnostic_with_fix(
|
||||
switch_case_braces_diagnostic(case_body_span),
|
||||
switch_case_braces_diagnostic(
|
||||
case_body_span,
|
||||
Diagnostic::MissingBraces,
|
||||
),
|
||||
|fixer| {
|
||||
let modified_code = {
|
||||
let mut formatter = fixer.codegen();
|
||||
|
|
@ -155,6 +222,11 @@ fn test() {
|
|||
None,
|
||||
),
|
||||
("switch(s){case'':/]/}", "switch(s){case '': {/]/}}", None),
|
||||
(
|
||||
"switch(foo) { default: {doSomething();} }",
|
||||
"switch(foo) { default: doSomething(); }",
|
||||
Some(serde_json::json!(["avoid"])),
|
||||
),
|
||||
];
|
||||
|
||||
Tester::new(SwitchCaseBraces::NAME, SwitchCaseBraces::PLUGIN, pass, fail)
|
||||
|
|
|
|||
|
|
@ -1,79 +1,79 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
---
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Missing braces in case clause.
|
||||
╭─[switch_case_braces.tsx:1:18]
|
||||
1 │ switch(s){case'':/]/}
|
||||
· ───
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Add Braces for case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Unexpected braces in empty case clause.
|
||||
╭─[switch_case_braces.tsx:1:29]
|
||||
1 │ switch(something) { case 1: {} case 2: {console.log('something'); break;}}
|
||||
· ──
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Remove braces in empty case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Missing braces in case clause.
|
||||
╭─[switch_case_braces.tsx:1:37]
|
||||
1 │ switch(something) { case 1: case 2: console.log('something'); break;}
|
||||
· ────────────────────────────────
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Add Braces for case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Unexpected braces in empty case clause.
|
||||
╭─[switch_case_braces.tsx:1:23]
|
||||
1 │ switch(foo) { case 1: {} case 2: {} default: { doSomething(); } }
|
||||
· ──
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Remove braces in empty case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Unexpected braces in empty case clause.
|
||||
╭─[switch_case_braces.tsx:1:34]
|
||||
1 │ switch(foo) { case 1: {} case 2: {} default: { doSomething(); } }
|
||||
· ──
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Remove braces in empty case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Unexpected braces in empty case clause.
|
||||
╭─[switch_case_braces.tsx:1:23]
|
||||
1 │ switch(foo) { case 1: { /* fallthrough */ } default: {}/* fallthrough */ case 3: { doSomething(); break; } }
|
||||
· ─────────────────────
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Remove braces in empty case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Unexpected braces in empty case clause.
|
||||
╭─[switch_case_braces.tsx:1:54]
|
||||
1 │ switch(foo) { case 1: { /* fallthrough */ } default: {}/* fallthrough */ case 3: { doSomething(); break; } }
|
||||
· ──
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Remove braces in empty case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Missing braces in case clause.
|
||||
╭─[switch_case_braces.tsx:1:24]
|
||||
1 │ switch(foo) { default: doSomething(); }
|
||||
· ──────────────
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Add Braces for case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Missing braces in case clause.
|
||||
╭─[switch_case_braces.tsx:1:23]
|
||||
1 │ switch(foo) { case 1: { doSomething(); } break; /* <-- This should be between braces */ }
|
||||
· ─────────────────────────
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Add Braces for case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Missing braces in case clause.
|
||||
╭─[switch_case_braces.tsx:1:24]
|
||||
1 │ switch(foo) { default: label: {} }
|
||||
· ─────────
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Add Braces for case clause.
|
||||
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Empty switch case shouldn't have braces and not-empty case should have braces around it.
|
||||
⚠ eslint-plugin-unicorn(switch-case-braces): Missing braces in case clause.
|
||||
╭─[switch_case_braces.tsx:1:82]
|
||||
1 │ switch(something) { case 1: case 2: { console.log('something'); break; } case 3: console.log('something else'); }
|
||||
· ──────────────────────────────
|
||||
╰────
|
||||
help: There is less visual clutter for empty cases and proper scope for non-empty cases.
|
||||
help: Add Braces for case clause.
|
||||
|
|
|
|||
Loading…
Reference in a new issue