mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
feat(linter): check LabeledStatement in javascript
This commit is contained in:
parent
26387c0660
commit
0fb8887d3c
4 changed files with 102 additions and 12 deletions
|
|
@ -18,13 +18,23 @@ impl Rule for EarlyErrorJavaScript {
|
|||
AstKind::NumberLiteral(lit) => check_number_literal(lit, node, ctx),
|
||||
AstKind::StringLiteral(lit) => check_string_literal(lit, node, ctx),
|
||||
AstKind::RegExpLiteral(lit) => check_regexp_literal(lit, ctx),
|
||||
AstKind::BreakStatement(lit) => check_break_statement(lit, node, ctx),
|
||||
AstKind::ContinueStatement(lit) => check_continue_statement(lit, node, ctx),
|
||||
AstKind::BreakStatement(stmt) => check_break_statement(stmt, node, ctx),
|
||||
AstKind::ContinueStatement(stmt) => check_continue_statement(stmt, node, ctx),
|
||||
AstKind::LabeledStatement(stmt) => check_labeled_statement(stmt, node, ctx),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("Identifier `{0:?}` has already been declared")]
|
||||
#[diagnostic()]
|
||||
struct Redeclaration(
|
||||
Atom,
|
||||
#[label("`{0}` has already been declared here")] Span,
|
||||
#[label("It can not be redeclared here")] Span,
|
||||
);
|
||||
|
||||
fn check_private_identifier<'a>(
|
||||
ident: &PrivateIdentifier,
|
||||
node: &AstNode<'a>,
|
||||
|
|
@ -282,3 +292,21 @@ fn check_continue_statement<'a>(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_labeled_statement<'a>(stmt: &LabeledStatement, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
for node_id in ctx.ancestors(node).skip(1) {
|
||||
match ctx.kind(node_id) {
|
||||
// label cannot cross boundary on function or static block
|
||||
AstKind::Function(_) | AstKind::StaticBlock(_) | AstKind::Program(_) => break,
|
||||
// check label name redeclaration
|
||||
AstKind::LabeledStatement(label_stmt) if stmt.label.name == label_stmt.label.name => {
|
||||
return ctx.diagnostic(Redeclaration(
|
||||
stmt.label.name.clone(),
|
||||
label_stmt.label.span,
|
||||
stmt.label.span,
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
Babel Summary:
|
||||
AST Parsed : 2056/2069 (99.37%)
|
||||
Positive Passed: 2056/2069 (99.37%)
|
||||
Negative Passed: 908/1502 (60.45%)
|
||||
Negative Passed: 911/1502 (60.65%)
|
||||
Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-multiple-labels/input.js"
|
||||
|
|
@ -61,7 +61,6 @@ Expect Syntax Error: "core/scope/undecl-export/input.js"
|
|||
Expect Syntax Error: "core/uncategorised/415/input.js"
|
||||
Expect Syntax Error: "core/uncategorised/427/input.js"
|
||||
Expect Syntax Error: "core/uncategorised/454/input.js"
|
||||
Expect Syntax Error: "core/uncategorised/465/input.js"
|
||||
Expect Syntax Error: "core/uncategorised/466/input.js"
|
||||
Expect Syntax Error: "core/uncategorised/467/input.js"
|
||||
Expect Syntax Error: "core/uncategorised/468/input.js"
|
||||
|
|
@ -389,7 +388,6 @@ Expect Syntax Error: "esprima/invalid-syntax/migrated_0101/input.js"
|
|||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0123/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0143/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0171/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0182/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0183/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0184/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0185/input.js"
|
||||
|
|
@ -453,7 +451,6 @@ Expect Syntax Error: "esprima/invalid-syntax/migrated_0244/input.js"
|
|||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0245/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0246/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0247/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0248/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0249/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0250/input.js"
|
||||
Expect Syntax Error: "esprima/invalid-syntax/migrated_0260/input.js"
|
||||
|
|
@ -1765,6 +1762,14 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
|
|||
╰────
|
||||
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`
|
||||
|
||||
× Identifier `"x"` has already been declared
|
||||
╭─[core/uncategorised/465/input.js:1:1]
|
||||
1 │ x: while (true) { x: while (true) { } }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `x` has already been declared here
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[core/uncategorised/523/input.js:1:1]
|
||||
1 │ var this = 10;
|
||||
|
|
@ -6856,6 +6861,22 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
|
|||
╰────
|
||||
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`
|
||||
|
||||
× Identifier `"x"` has already been declared
|
||||
╭─[esprima/invalid-syntax/migrated_0182/input.js:1:1]
|
||||
1 │ x: while (true) { x: while (true) { } }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `x` has already been declared here
|
||||
╰────
|
||||
|
||||
× Identifier `"__proto__"` has already been declared
|
||||
╭─[esprima/invalid-syntax/migrated_0248/input.js:1:1]
|
||||
1 │ __proto__: __proto__: 42;
|
||||
· ────┬──── ────┬────
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `__proto__` has already been declared here
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[esprima/invalid-syntax/migrated_0252/input.js:1:1]
|
||||
1 │ var
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
Test262 Summary:
|
||||
AST Parsed : 44000/44009 (99.98%)
|
||||
Positive Passed: 44000/44009 (99.98%)
|
||||
Negative Passed: 2223/3917 (56.75%)
|
||||
Negative Passed: 2225/3917 (56.80%)
|
||||
Expect Syntax Error: "annexB/language/statements/for-in/const-initializer.js"
|
||||
Expect Syntax Error: "annexB/language/statements/for-in/let-initializer.js"
|
||||
Expect Syntax Error: "annexB/language/statements/for-in/strict-initializer.js"
|
||||
|
|
@ -851,7 +851,6 @@ Expect Syntax Error: "language/module-code/early-dup-export-dflt-id.js"
|
|||
Expect Syntax Error: "language/module-code/early-dup-export-id-as.js"
|
||||
Expect Syntax Error: "language/module-code/early-dup-export-id.js"
|
||||
Expect Syntax Error: "language/module-code/early-dup-export-star-as-dflt.js"
|
||||
Expect Syntax Error: "language/module-code/early-dup-lables.js"
|
||||
Expect Syntax Error: "language/module-code/early-dup-lex.js"
|
||||
Expect Syntax Error: "language/module-code/early-dup-top-function-async-generator.js"
|
||||
Expect Syntax Error: "language/module-code/early-dup-top-function-async.js"
|
||||
|
|
@ -1317,7 +1316,6 @@ Expect Syntax Error: "language/statements/class/static-gen-method-param-dflt-yie
|
|||
Expect Syntax Error: "language/statements/class/static-init-await-binding-invalid.js"
|
||||
Expect Syntax Error: "language/statements/class/static-init-invalid-arguments.js"
|
||||
Expect Syntax Error: "language/statements/class/static-init-invalid-await.js"
|
||||
Expect Syntax Error: "language/statements/class/static-init-invalid-label-dup.js"
|
||||
Expect Syntax Error: "language/statements/class/static-init-invalid-lex-dup.js"
|
||||
Expect Syntax Error: "language/statements/class/static-init-invalid-lex-var.js"
|
||||
Expect Syntax Error: "language/statements/class/static-init-invalid-return.js"
|
||||
|
|
@ -14092,6 +14090,18 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat
|
|||
17 │ export default var x = null;
|
||||
╰────
|
||||
|
||||
× Identifier `"label"` has already been declared
|
||||
╭─[language/module-code/early-dup-lables.js:15:1]
|
||||
15 │
|
||||
16 │ label: {
|
||||
· ──┬──
|
||||
· ╰── `label` has already been declared here
|
||||
17 │ label: 0;
|
||||
· ──┬──
|
||||
· ╰── It can not be redeclared here
|
||||
18 │ }
|
||||
╰────
|
||||
|
||||
× An export name cannot include a unicode lone surrogate
|
||||
╭─[language/module-code/early-export-ill-formed-string.js:20:1]
|
||||
20 │ // 🌙 is '\uD83C\uDF19'
|
||||
|
|
@ -18425,6 +18435,16 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat
|
|||
18 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"x"` has already been declared
|
||||
╭─[language/statements/class/static-init-invalid-label-dup.js:20:1]
|
||||
20 │ static {
|
||||
21 │ x: x: 0;
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `x` has already been declared here
|
||||
22 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[language/statements/class/static-init-invalid-undefined-break-target.js:21:1]
|
||||
21 │ x: while (false) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
TypeScript Summary:
|
||||
AST Parsed : 2310/2338 (98.80%)
|
||||
Positive Passed: 2310/2338 (98.80%)
|
||||
Negative Passed: 558/2531 (22.05%)
|
||||
Negative Passed: 560/2531 (22.13%)
|
||||
Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts"
|
||||
Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts"
|
||||
Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts"
|
||||
|
|
@ -1337,8 +1337,6 @@ Expect Syntax Error: "parser/ecmascript5/RegularExpressions/parserRegularExpress
|
|||
Expect Syntax Error: "parser/ecmascript5/Statements/BreakStatements/parser_breakInIterationOrSwitchStatement4.ts"
|
||||
Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueInIterationStatement4.ts"
|
||||
Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement4.ts"
|
||||
Expect Syntax Error: "parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel1.ts"
|
||||
Expect Syntax Error: "parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel2.ts"
|
||||
Expect Syntax Error: "parser/ecmascript5/Statements/ReturnStatements/parserReturnStatement1.ts"
|
||||
Expect Syntax Error: "parser/ecmascript5/Statements/ReturnStatements/parserReturnStatement2.ts"
|
||||
Expect Syntax Error: "parser/ecmascript5/Statements/parserBlockStatement1.d.ts"
|
||||
|
|
@ -7445,6 +7443,29 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
|
|||
3 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"target"` has already been declared
|
||||
╭─[parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel1.ts:1:1]
|
||||
1 │ target:
|
||||
· ───┬──
|
||||
· ╰── `target` has already been declared here
|
||||
2 │ target:
|
||||
· ───┬──
|
||||
· ╰── It can not be redeclared here
|
||||
3 │ while (true) {
|
||||
╰────
|
||||
|
||||
× Identifier `"target"` has already been declared
|
||||
╭─[parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel2.ts:1:1]
|
||||
1 │ target:
|
||||
· ───┬──
|
||||
· ╰── `target` has already been declared here
|
||||
2 │ while (true) {
|
||||
3 │ target:
|
||||
· ───┬──
|
||||
· ╰── It can not be redeclared here
|
||||
4 │ while (true) {
|
||||
╰────
|
||||
|
||||
× Illegal break statement
|
||||
╭─[parser/ecmascript5/Statements/parserBreakStatement1.d.ts:1:1]
|
||||
1 │ break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue