feat(linter): check BindingIdentifier in javascript

This commit is contained in:
Boshen 2023-03-09 14:15:37 +08:00
parent 4ea7ac373d
commit 185acc49bd
4 changed files with 157 additions and 24 deletions

View file

@ -15,10 +15,11 @@ impl Rule for EarlyErrorJavaScript {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
match node.get().kind() {
AstKind::BindingIdentifier(ident) => {
check_identifier(&ident.name, ident.span, node, ctx)
check_identifier(&ident.name, ident.span, node, ctx);
check_binding_identifier(ident, node, ctx);
}
AstKind::IdentifierReference(ident) => {
check_identifier(&ident.name, ident.span, node, ctx)
check_identifier(&ident.name, ident.span, node, ctx);
}
AstKind::LabelIdentifier(ident) => check_identifier(&ident.name, ident.span, node, ctx),
AstKind::PrivateIdentifier(ident) => check_private_identifier(ident, node, ctx),
@ -70,7 +71,42 @@ fn check_identifier<'a>(name: &Atom, span: Span, node: &AstNode<'a>, ctx: &LintC
// It is a Syntax Error if this phrase is contained in strict mode code and the StringValue of IdentifierName is: "implements", "interface", "let", "package", "private", "protected", "public", "static", or "yield".
if ctx.strict_mode(node) && STRICT_MODE_NAMES.contains(name.as_str()) {
return ctx.diagnostic(ReservedKeyword(name.clone(), span));
ctx.diagnostic(ReservedKeyword(name.clone(), span));
}
}
fn check_binding_identifier<'a>(
ident: &BindingIdentifier,
node: &AstNode<'a>,
ctx: &LintContext<'a>,
) {
let strict_mode = ctx.strict_mode(node);
// It is a Diagnostic if the StringValue of a BindingIdentifier is "eval" or "arguments" within strict mode code.
// if strict_mode && !span.ctx.has_ambient() && matches!(name.as_str(), "eval" | "arguments") {
// return Some(Diagnostic::UnexpectedIdentifierAssign(name.clone(), span.range()));
// }
// LexicalDeclaration : LetOrConst BindingList ;
// * It is a Syntax Error if the BoundNames of BindingList contains "let".
if !strict_mode && ident.name == "let" {
for node_id in ctx.ancestors(node).skip(1) {
match ctx.kind(node_id) {
AstKind::VariableDeclaration(decl) if decl.kind.is_lexical() => {
#[derive(Debug, Error, Diagnostic)]
#[error(
"`let` cannot be declared as a variable name inside of a `{0:?}` declaration"
)]
#[diagnostic()]
struct InvalidLetDeclaration(String, #[label] Span);
return ctx
.diagnostic(InvalidLetDeclaration(decl.kind.to_string(), ident.span));
}
AstKind::VariableDeclaration(_) | AstKind::Function(_) | AstKind::Program(_) => {
break;
}
_ => {}
}
}
}
}

View file

@ -1,7 +1,7 @@
Babel Summary:
AST Parsed : 2056/2069 (99.37%)
Positive Passed: 2056/2069 (99.37%)
Negative Passed: 922/1502 (61.38%)
Negative Passed: 935/1502 (62.25%)
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"
@ -135,19 +135,6 @@ Expect Syntax Error: "es2015/for-in/var-arraybindingpattern-initializer/input.js
Expect Syntax Error: "es2015/for-in/var-objectbindingpattern-initializer/input.js"
Expect Syntax Error: "es2015/for-of/invalid-let-as-identifier/input.js"
Expect Syntax Error: "es2015/let/let-as-identifier-strict-fail/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-1/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-10/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-11/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-12/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-2/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-3/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-4/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-5/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-6/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-7/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-8/input.js"
Expect Syntax Error: "es2015/let/let-at-binding-list-fail-9/input.js"
Expect Syntax Error: "es2015/let/let-at-catch-block/input.js"
Expect Syntax Error: "es2015/meta-properties/invalid-arrow-function/input.js"
Expect Syntax Error: "es2015/meta-properties/new-invalid-prop/input.js"
Expect Syntax Error: "es2015/meta-properties/new-target-invalid/input.js"
@ -2203,6 +2190,86 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
╰────
help: Wrap this declaration in a block statement
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es2015/let/let-at-binding-list-fail-1/input.js:1:1]
1 │ let { let } = {};
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[es2015/let/let-at-binding-list-fail-10/input.js:1:1]
1 │ const [let = 10] = [];
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es2015/let/let-at-binding-list-fail-11/input.js:1:1]
1 │ let [...let] = [];
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[es2015/let/let-at-binding-list-fail-12/input.js:1:1]
1 │ const [...let] = [];
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[es2015/let/let-at-binding-list-fail-2/input.js:1:1]
1 │ const { let } = {};
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es2015/let/let-at-binding-list-fail-3/input.js:1:1]
1 │ let [let] = [];
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[es2015/let/let-at-binding-list-fail-4/input.js:1:1]
1 │ const [let] = [];
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es2015/let/let-at-binding-list-fail-5/input.js:1:1]
1 │ let let
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[es2015/let/let-at-binding-list-fail-6/input.js:1:1]
1 │ const let = ''
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es2015/let/let-at-binding-list-fail-7/input.js:1:1]
1 │ let { let = 10 } = {};
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[es2015/let/let-at-binding-list-fail-8/input.js:1:1]
1 │ const { let = 10 } = {};
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es2015/let/let-at-binding-list-fail-9/input.js:1:1]
1 │ let [let = 10] = [];
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es2015/let/let-at-catch-block/input.js:1:1]
1 │ try {} catch (err) {
2 │ let let;
· ───
3 │ }
╰────
× Keywords cannot contain escape characters
╭─[es2015/meta-properties/new-target-invalid-escaped-new/input.js:1:1]
1 │ function f() { n\u0065w.target; }

View file

@ -1,7 +1,7 @@
Test262 Summary:
AST Parsed : 43997/44009 (99.97%)
Positive Passed: 43997/44009 (99.97%)
Negative Passed: 2505/3917 (63.95%)
Negative Passed: 2509/3917 (64.05%)
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"
@ -1155,10 +1155,8 @@ Expect Syntax Error: "language/statements/for-in/dstr/obj-id-init-simple-strict.
Expect Syntax Error: "language/statements/for-in/dstr/obj-id-simple-strict.js"
Expect Syntax Error: "language/statements/for-in/head-const-bound-names-dup.js"
Expect Syntax Error: "language/statements/for-in/head-const-bound-names-in-stmt.js"
Expect Syntax Error: "language/statements/for-in/head-const-bound-names-let.js"
Expect Syntax Error: "language/statements/for-in/head-let-bound-names-dup.js"
Expect Syntax Error: "language/statements/for-in/head-let-bound-names-in-stmt.js"
Expect Syntax Error: "language/statements/for-in/head-let-bound-names-let.js"
Expect Syntax Error: "language/statements/for-in/labelled-fn-stmt-const.js"
Expect Syntax Error: "language/statements/for-in/labelled-fn-stmt-let.js"
Expect Syntax Error: "language/statements/for-in/labelled-fn-stmt-lhs.js"
@ -1191,11 +1189,9 @@ Expect Syntax Error: "language/statements/for-of/dstr/var-ary-ptrn-rest-init-obj
Expect Syntax Error: "language/statements/for-of/dstr/var-obj-ptrn-init-err.js"
Expect Syntax Error: "language/statements/for-of/head-const-bound-names-dup.js"
Expect Syntax Error: "language/statements/for-of/head-const-bound-names-in-stmt.js"
Expect Syntax Error: "language/statements/for-of/head-const-bound-names-let.js"
Expect Syntax Error: "language/statements/for-of/head-const-init.js"
Expect Syntax Error: "language/statements/for-of/head-let-bound-names-dup.js"
Expect Syntax Error: "language/statements/for-of/head-let-bound-names-in-stmt.js"
Expect Syntax Error: "language/statements/for-of/head-let-bound-names-let.js"
Expect Syntax Error: "language/statements/for-of/head-let-init.js"
Expect Syntax Error: "language/statements/for-of/head-var-init.js"
Expect Syntax Error: "language/statements/for-of/labelled-fn-stmt-const.js"
@ -21128,6 +21124,20 @@ Expect to Parse: "language/statements/class/decorator/syntax/valid/decorator-par
34 │ ]) ;
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[language/statements/for-in/head-const-bound-names-let.js:16:1]
16 │
17 │ for (const let in {}) {}
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[language/statements/for-in/head-let-bound-names-let.js:16:1]
16 │
17 │ for (let let in {}) {}
· ───
╰────
× Unexpected token
╭─[language/statements/for-in/head-lhs-cover-non-asnmt-trgt.js:23:1]
23 │
@ -21520,6 +21530,13 @@ Expect to Parse: "language/statements/class/decorator/syntax/valid/decorator-par
· ╰── keyword cannot contain escape characters
╰────
× `let` cannot be declared as a variable name inside of a `"const"` declaration
╭─[language/statements/for-of/head-const-bound-names-let.js:16:1]
16 │
17 │ for (const let of []) {}
· ───
╰────
× Expect token
╭─[language/statements/for-of/head-decl-no-expr.js:16:1]
16 │
@ -21536,6 +21553,13 @@ Expect to Parse: "language/statements/class/decorator/syntax/valid/decorator-par
· ╰── Expect `)` here, but found `,`
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[language/statements/for-of/head-let-bound-names-let.js:16:1]
16 │
17 │ for (let let of []) {}
· ───
╰────
× The left-hand side of a `for...of` statement may not be `async`
╭─[language/statements/for-of/head-lhs-async-invalid.js:16:1]
16 │ var async;

View file

@ -1,7 +1,7 @@
TypeScript Summary:
AST Parsed : 2308/2338 (98.72%)
Positive Passed: 2308/2338 (98.72%)
Negative Passed: 576/2531 (22.76%)
Negative Passed: 577/2531 (22.80%)
Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts"
Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts"
Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts"
@ -572,7 +572,6 @@ Expect Syntax Error: "es6/for-ofStatements/for-of39.ts"
Expect Syntax Error: "es6/for-ofStatements/for-of46.ts"
Expect Syntax Error: "es6/for-ofStatements/for-of47.ts"
Expect Syntax Error: "es6/for-ofStatements/for-of48.ts"
Expect Syntax Error: "es6/for-ofStatements/for-of51.ts"
Expect Syntax Error: "es6/for-ofStatements/for-of52.ts"
Expect Syntax Error: "es6/for-ofStatements/for-of54.ts"
Expect Syntax Error: "es6/for-ofStatements/for-of55.ts"
@ -4644,6 +4643,13 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
· ───
╰────
× `let` cannot be declared as a variable name inside of a `"let"` declaration
╭─[es6/for-ofStatements/for-of51.ts:1:1]
1 │ //@target: ES6
2 │ for (let let of []) {}
· ───
╰────
× Unexpected token
╭─[es6/functionPropertyAssignments/FunctionPropertyAssignments2_es6.ts:1:1]
1 │ // @target: es6