feat(linter): check IdentifierReference in javascript

This commit is contained in:
Boshen 2023-03-09 20:20:19 +08:00
parent da8355f418
commit 5b8bdaabab
No known key found for this signature in database
GPG key ID: 6AC90C77AAAA6ABC
4 changed files with 954 additions and 122 deletions

View file

@ -20,6 +20,7 @@ impl Rule for EarlyErrorJavaScript {
}
AstKind::IdentifierReference(ident) => {
check_identifier(&ident.name, ident.span, node, ctx);
check_identifier_reference(ident, node, ctx);
}
AstKind::LabelIdentifier(ident) => check_identifier(&ident.name, ident.span, node, ctx),
AstKind::PrivateIdentifier(ident) => check_private_identifier(ident, node, ctx),
@ -110,6 +111,61 @@ fn check_binding_identifier<'a>(
}
}
fn check_identifier_reference<'a>(
ident: &IdentifierReference,
node: &AstNode<'a>,
ctx: &LintContext<'a>,
) {
#[derive(Debug, Error, Diagnostic)]
#[error("Cannot assign to '{0:?}' in strict mode")]
#[diagnostic()]
struct UnexpectedIdentifierAssign(Atom, #[label] Span);
#[derive(Debug, Error, Diagnostic)]
#[error("'arguments' is not allowed in {0:?}")]
#[diagnostic()]
struct UnexpectedArguments(&'static str, #[label] Span);
// Static Semantics: AssignmentTargetType
// 1. If this IdentifierReference is contained in strict mode code and StringValue of Identifier is "eval" or "arguments", return invalid.
if ctx.strict_mode(node) && matches!(ident.name.as_str(), "arguments" | "eval") {
for node_id in ctx.ancestors(node).skip(1) {
match ctx.kind(node_id) {
AstKind::AssignmentTarget(_) | AstKind::SimpleAssignmentTarget(_) => {
return ctx
.diagnostic(UnexpectedIdentifierAssign(ident.name.clone(), ident.span));
}
AstKind::MemberExpression(_) => break,
_ => {}
}
}
}
// FieldDefinition : ClassElementName Initializeropt
// It is a Syntax Error if Initializer is present and ContainsArguments of Initializer is true.
// ClassStaticBlockBody : ClassStaticBlockStatementList
// It is a Syntax Error if ContainsArguments of ClassStaticBlockStatementList is true.
if ident.name == "arguments" {
for node_id in ctx.ancestors(node).skip(1) {
match ctx.kind(node_id) {
AstKind::Function(_) => break,
AstKind::PropertyDefinition(_) => {
return ctx
.diagnostic(UnexpectedArguments("class field initializer", ident.span));
}
AstKind::StaticBlock(_) => {
return ctx.diagnostic(UnexpectedArguments(
"static initialization block",
ident.span,
));
}
_ => {}
}
}
}
}
fn check_private_identifier<'a>(
ident: &PrivateIdentifier,
node: &AstNode<'a>,

View file

@ -1,7 +1,7 @@
Babel Summary:
AST Parsed : 2056/2069 (99.37%)
Positive Passed: 2056/2069 (99.37%)
Negative Passed: 935/1502 (62.25%)
Negative Passed: 936/1502 (62.32%)
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"
@ -200,7 +200,6 @@ Expect Syntax Error: "es2015/uncategorised/291/input.js"
Expect Syntax Error: "es2015/uncategorised/296/input.js"
Expect Syntax Error: "es2015/uncategorised/297/input.js"
Expect Syntax Error: "es2015/uncategorised/332/input.js"
Expect Syntax Error: "es2015/uncategorised/334/input.js"
Expect Syntax Error: "es2015/uncategorised/349/input.js"
Expect Syntax Error: "es2015/yield/function-name-function-declaration-inside-generator/input.js"
Expect Syntax Error: "es2015/yield/function-name-generator-expression/input.js"
@ -2913,6 +2912,12 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
· ╰── Classes can only be declared at top level or inside a block
╰────
× Cannot assign to '"eval"' in strict mode
╭─[es2015/uncategorised/334/input.js:1:1]
1 │ [...eval] = arr
· ────
╰────
× Bad escape sequence in untagged template literal
╭─[es2015/uncategorised/339/input.js:1:1]
1 │ `\07`

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
TypeScript Summary:
AST Parsed : 2308/2338 (98.72%)
Positive Passed: 2308/2338 (98.72%)
Negative Passed: 577/2531 (22.80%)
Negative Passed: 578/2531 (22.84%)
Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts"
Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts"
Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts"
@ -408,7 +408,6 @@ Expect Syntax Error: "es6/arrowFunction/emitArrowFunctionWhenUsingArguments16.ts
Expect Syntax Error: "es6/arrowFunction/emitArrowFunctionWhenUsingArguments17.ts"
Expect Syntax Error: "es6/arrowFunction/emitArrowFunctionWhenUsingArguments18.ts"
Expect Syntax Error: "es6/arrowFunction/emitArrowFunctionWhenUsingArguments19.ts"
Expect Syntax Error: "es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts"
Expect Syntax Error: "es6/classDeclaration/superCallBeforeThisAccessing3.ts"
Expect Syntax Error: "es6/classDeclaration/superCallBeforeThisAccessing4.ts"
Expect Syntax Error: "es6/classDeclaration/superCallBeforeThisAccessing6.ts"
@ -4339,6 +4338,14 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
3 │ var oct2 = 0o34318592;
╰────
× Cannot assign to '"arguments"' in strict mode
╭─[es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts:6:1]
6 │ private bar(eval:any) {
7 │ arguments = "hello";
· ─────────
8 │ }
╰────
× A 'set' accessor must have exactly one parameter.
╭─[es6/computedProperties/computedPropertyNames49_ES5.ts:9:1]
9 │ },