refactor(linter): improve eslint/no-lone-blocks (#8588)

The code `let mut lone_blocks = Vec::new();` is unnecessary because it
will contain at most one element throughout its usage.

Additionally, special test cases has been added for when
`parent_node.kind()` is `AstKind::FunctionBody(_)`.
This commit is contained in:
dalaoshu 2025-01-19 07:54:17 +08:00 committed by GitHub
parent 01ac773d0c
commit 40f51654ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 43 additions and 48 deletions

View file

@ -61,58 +61,55 @@ impl Rule for NoLoneBlocks {
return;
};
let body = &stmt.body;
if body.is_empty() {
if stmt.body.is_empty() {
if !matches!(parent_node.kind(), AstKind::TryStatement(_) | AstKind::CatchClause(_)) {
report(ctx, node, parent_node);
}
return;
}
if body.len() == 1
&& matches!(parent_node.kind(), AstKind::FunctionBody(parent) if parent.statements.len() == 1)
{
report(ctx, node, parent_node);
}
let mut is_lone_blocks = is_lone_block(node, parent_node);
let mut lone_blocks = Vec::new();
if is_lone_block(node, parent_node) {
lone_blocks.push(node);
}
for child in &stmt.body {
match child.as_declaration() {
Some(Declaration::VariableDeclaration(decl))
if decl.kind != VariableDeclarationKind::Var =>
{
mark_lone_block(node, &mut lone_blocks);
if is_lone_blocks {
for child in &stmt.body {
match child.as_declaration() {
Some(Declaration::VariableDeclaration(decl))
if decl.kind != VariableDeclarationKind::Var =>
{
is_lone_blocks = false;
}
Some(
Declaration::ClassDeclaration(_) | Declaration::FunctionDeclaration(_),
) => {
is_lone_blocks = false;
}
_ => {}
}
Some(Declaration::ClassDeclaration(_) | Declaration::FunctionDeclaration(_)) => {
mark_lone_block(node, &mut lone_blocks);
}
_ => {}
}
}
if let Some(last) = lone_blocks.last() {
if last.id() == node.id() {
lone_blocks.pop();
if is_lone_blocks {
report(ctx, node, parent_node);
return;
}
} else {
match parent_node.kind() {
AstKind::BlockStatement(parent_statement) => {
if parent_statement.body.len() == 1 {
report(ctx, node, parent_node);
}
}
match parent_node.kind() {
AstKind::FunctionBody(parent) => {
if parent.statements.len() == 1 && stmt.body.len() == 1 {
report(ctx, node, parent_node);
}
AstKind::StaticBlock(parent_statement) => {
if parent_statement.body.len() == 1 {
report(ctx, node, parent_node);
}
}
_ => {}
}
AstKind::BlockStatement(parent_statement) => {
if parent_statement.body.len() == 1 {
report(ctx, node, parent_node);
}
}
AstKind::StaticBlock(parent_statement) => {
if parent_statement.body.len() == 1 {
report(ctx, node, parent_node);
}
}
_ => {}
}
}
}
@ -142,16 +139,6 @@ fn is_lone_block(node: &AstNode, parent_node: &AstNode) -> bool {
}
}
fn mark_lone_block(parent_node: &AstNode, lone_blocks: &mut Vec<&AstNode>) {
if lone_blocks.is_empty() {
return;
}
if lone_blocks.last().is_some_and(|last| last.id() == parent_node.id()) {
lone_blocks.pop();
}
}
#[test]
fn test() {
use crate::tester::Tester;
@ -160,6 +147,7 @@ fn test() {
"if (foo) { if (bar) { baz(); } }",
"do { bar(); } while (foo)",
"function foo() { while (bar) { baz() } }",
"function test() { { console.log(6); console.log(6) } }",
"{ let x = 1; }", // { "ecmaVersion": 6 },
"{ const x = 1; }", // { "ecmaVersion": 6 },
"'use strict'; { function bar() {} }", // { "ecmaVersion": 6 },
@ -216,6 +204,7 @@ fn test() {
"{}",
"{var x = 1;}",
"foo(); {} bar();",
"function test() { { console.log(6); } }",
"if (foo) { bar(); {} baz(); }",
"{
{ } }",

View file

@ -19,6 +19,12 @@ source: crates/oxc_linter/src/tester.rs
· ──
╰────
⚠ eslint(no-lone-blocks): Block is unnecessary.
╭─[no_lone_blocks.tsx:1:19]
1 │ function test() { { console.log(6); } }
· ───────────────────
╰────
⚠ eslint(no-lone-blocks): Nested block is redundant.
╭─[no_lone_blocks.tsx:1:19]
1 │ if (foo) { bar(); {} baz(); }