feat(linter): check Directive in javascript

This commit is contained in:
Boshen 2023-03-13 23:19:35 +08:00
parent 7269d32346
commit 5381fd0cf8
No known key found for this signature in database
GPG key ID: 6AC90C77AAAA6ABC
4 changed files with 1070 additions and 126 deletions

View file

@ -34,6 +34,7 @@ impl Rule for EarlyErrorJavaScript {
AstKind::StringLiteral(lit) => check_string_literal(lit, node, ctx),
AstKind::RegExpLiteral(lit) => check_regexp_literal(lit, ctx),
AstKind::Directive(dir) => check_directive(dir, node, ctx),
AstKind::ModuleDeclaration(decl) => check_module_declaration(decl, node, ctx),
AstKind::WithStatement(stmt) => check_with_statement(stmt, node, ctx),
@ -300,6 +301,36 @@ fn check_string_literal<'a>(lit: &StringLiteral, node: &AstNode<'a>, ctx: &LintC
}
}
// It is a Syntax Error if FunctionBodyContainsUseStrict of AsyncFunctionBody is true and IsSimpleParameterList of FormalParameters is false.
// background: https://humanwhocodes.com/blog/2016/10/the-ecmascript-2016-change-you-probably-dont-know/
fn check_directive<'a>(directive: &Directive, node: &AstNode<'a>, ctx: &LintContext<'a>) {
#[derive(Debug, Error, Diagnostic)]
#[error("Illegal 'use strict' directive in function with non-simple parameter list")]
#[diagnostic()]
struct IllegalUseStrict(#[label] Span);
if directive.expression.value != "use strict" {
return;
}
if !ctx.scope(node).is_function() {
return;
}
for node_id in ctx.ancestors(node) {
match ctx.kind(node_id) {
AstKind::Function(Function { params, .. })
| AstKind::ArrowExpression(ArrowExpression { params, .. }) => {
if !params.is_simple_parameter_list() {
return ctx.diagnostic(IllegalUseStrict(directive.span));
}
break;
}
_ => {}
}
}
}
fn check_module_declaration<'a>(
decl: &ModuleDeclaration,
node: &AstNode<'a>,

View file

@ -1,7 +1,7 @@
Babel Summary:
AST Parsed : 2051/2069 (99.13%)
Positive Passed: 2051/2069 (99.13%)
Negative Passed: 1108/1502 (73.77%)
Negative Passed: 1120/1502 (74.57%)
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"
@ -134,18 +134,6 @@ Expect Syntax Error: "es2015/yield/function-name-strict/input.js"
Expect Syntax Error: "es2015/yield/parameter-default-strict/input.js"
Expect Syntax Error: "es2015/yield/parameter-name-strict-body/input.js"
Expect Syntax Error: "es2015/yield/parameter-name-strict/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/array-pattern-default/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/array-pattern/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/arrow-function/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/async-arrow-function/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/async-function/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/default/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/generator-function/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/generator-method/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/method/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/object-pattern-default/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/object-pattern/input.js"
Expect Syntax Error: "es2016/simple-parameter-list/rest/input.js"
Expect Syntax Error: "es2017/async-functions/await-async-function-expression-name/input.js"
Expect Syntax Error: "es2017/async-functions/await-binding-inside-arrow-params-inside-async-arrow-params/input.js"
Expect Syntax Error: "es2017/async-functions/await-function-declaration-name-inside-async-function/input.js"
@ -3959,6 +3947,30 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
╰────
help: Wrap unary expression in parentheses to enforce operator precedence
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/array-pattern-default/input.js:1:1]
1 │ function a([ option1, option2 ] = []) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/array-pattern/input.js:1:1]
1 │ function a([ option1, option2 ]) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/arrow-function/input.js:1:1]
1 │ var a = (options = {}) => {
2 │ "use strict";
· ─────────────
3 │ };
╰────
× Automatic Semicolon Insertion
╭─[es2016/simple-parameter-list/async-arrow-function-after-binary-operator/input.js:1:1]
1 │ 3 + async() => 2
@ -3975,6 +3987,78 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
╰────
help: Try insert a semicolon here
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/async-arrow-function/input.js:1:1]
1 │ var a = async (options = {}) => {
2 │ "use strict";
· ─────────────
3 │ };
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/async-function/input.js:1:1]
1 │ async function a(options = {}) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/default/input.js:1:1]
1 │ function a(options = {}) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/generator-function/input.js:1:1]
1 │ function* a(options = {}) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/generator-method/input.js:2:1]
2 │ * a(options = {}) {
3 │ "use strict";
· ─────────────
4 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/method/input.js:2:1]
2 │ a(options = {}) {
3 │ "use strict";
· ─────────────
4 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/object-pattern-default/input.js:1:1]
1 │ function a({ option1, option2 } = {}) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/object-pattern/input.js:1:1]
1 │ function a({ option1, option2 }) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[es2016/simple-parameter-list/rest/input.js:1:1]
1 │ function a(...options) {
2 │ "use strict";
· ─────────────
3 │ }
╰────
× Automatic Semicolon Insertion
╭─[es2017/async-arrow/parenthesized-array-pattern-nested-2/input.js:1:1]
1 │ async ([(a) = []] = []) => {}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
TypeScript Summary:
AST Parsed : 2305/2338 (98.59%)
Positive Passed: 2305/2338 (98.59%)
Negative Passed: 657/2532 (25.95%)
Negative Passed: 658/2532 (25.99%)
Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts"
Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts"
Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts"
@ -838,7 +838,6 @@ Expect Syntax Error: "functions/functionImplementationErrors.ts"
Expect Syntax Error: "functions/functionImplementations.ts"
Expect Syntax Error: "functions/functionOverloadCompatibilityWithVoid01.ts"
Expect Syntax Error: "functions/functionOverloadErrors.ts"
Expect Syntax Error: "functions/functionWithUseStrictAndSimpleParameterList_es2016.ts"
Expect Syntax Error: "functions/parameterInitializersForwardReferencing.2.ts"
Expect Syntax Error: "functions/parameterInitializersForwardReferencing.ts"
Expect Syntax Error: "functions/parameterInitializersForwardReferencing1.ts"
@ -8282,6 +8281,70 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
10 │ function fn5() { }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:3:1]
3 │ function a(a = 10) {
4 │ "use strict";
· ─────────────
5 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:17:1]
17 │ function rest(...args: any[]) {
18 │ 'use strict';
· ─────────────
19 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:21:1]
21 │ function rest1(a = 1, ...args) {
22 │ 'use strict';
· ─────────────
23 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:25:1]
25 │ function paramDefault(param = 1) {
26 │ 'use strict';
· ─────────────
27 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:29:1]
29 │ function objectBindingPattern({foo}: any) {
30 │ 'use strict';
· ─────────────
31 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:33:1]
33 │ function arrayBindingPattern([foo]: any[]) {
34 │ 'use strict';
· ─────────────
35 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:37:1]
37 │ function manyParameter(a = 10, b = 20) {
38 │ "use strict";
· ─────────────
39 │ }
╰────
× Illegal 'use strict' directive in function with non-simple parameter list
╭─[functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:42:1]
42 │ "foo";
43 │ "use strict";
· ─────────────
44 │ }
╰────
× Expect token
╭─[importAssertion/importAssertion4.ts:1:1]
1 │ import * as f from "./first" assert