feat(linter): check WithStatement in javascript

This commit is contained in:
Boshen 2023-03-09 13:58:32 +08:00
parent 0fb8887d3c
commit 4a582f0487
7 changed files with 158 additions and 24 deletions

View file

@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc};
use indextree::{Ancestors, NodeId};
use oxc_ast::AstKind;
use oxc_ast::{AstKind, SourceType};
use oxc_diagnostics::Error;
use oxc_semantic::{AstNodes, Scope, ScopeTree, Semantic, SemanticNode};
@ -26,10 +26,21 @@ impl<'a> LintContext<'a> {
Self { source_text, semantic, diagnostics: RefCell::new(vec![]), fix }
}
#[must_use]
pub fn semantic(&self) -> &Semantic<'a> {
&self.semantic
}
#[must_use]
pub fn source_text(&self) -> &'a str {
self.source_text
}
#[must_use]
pub fn source_type(&self) -> &SourceType {
self.semantic().source_type()
}
/* Diagnostics */
pub fn into_message(self) -> Vec<Message<'a>> {
@ -52,11 +63,6 @@ impl<'a> LintContext<'a> {
}
}
#[must_use]
pub fn semantic(&self) -> &Semantic<'a> {
&self.semantic
}
/* Nodes */
#[must_use]

View file

@ -18,6 +18,7 @@ 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::WithStatement(stmt) => check_with_statement(stmt, 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),
@ -178,6 +179,17 @@ fn check_regexp_literal(lit: &RegExpLiteral, ctx: &LintContext) {
}
}
fn check_with_statement<'a>(stmt: &WithStatement, node: &AstNode<'a>, ctx: &LintContext<'a>) {
#[derive(Debug, Error, Diagnostic)]
#[error("'with' statements are not allowed")]
#[diagnostic()]
struct WithStatement(#[label] Span);
if ctx.strict_mode(node) || ctx.source_type().is_typescript() {
ctx.diagnostic(WithStatement(Span::new(stmt.span.start, stmt.span.start + 4)));
}
}
#[derive(Debug, Error, Diagnostic)]
#[error("Jump target cannot cross function boundary.")]
#[diagnostic()]

View file

@ -14,6 +14,8 @@ use crate::{
};
pub struct SemanticBuilder<'a> {
source_type: SourceType,
// states
current_node_id: AstNodeId,
current_node_flags: NodeFlags,
@ -31,14 +33,19 @@ impl<'a> SemanticBuilder<'a> {
let semantic_node =
SemanticNode::new(AstKind::Root, scope.current_scope_id, NodeFlags::empty());
let current_node_id = nodes.new_node(semantic_node).into();
Self { current_node_id, nodes, scope, current_node_flags: NodeFlags::empty() }
Self { source_type, current_node_id, nodes, scope, current_node_flags: NodeFlags::empty() }
}
#[must_use]
pub fn build(mut self, program: &'a Program<'a>, trivias: Rc<Trivias>) -> Semantic<'a> {
// AST pass
self.visit_program(program);
Semantic { nodes: self.nodes, scopes: self.scope.scopes, trivias }
Semantic {
source_type: self.source_type,
nodes: self.nodes,
scopes: self.scope.scopes,
trivias,
}
}
fn create_ast_node(&mut self, kind: AstKind<'a>) {

View file

@ -6,10 +6,12 @@ use std::rc::Rc;
pub use builder::SemanticBuilder;
pub use node::{AstNode, AstNodes, SemanticNode};
use oxc_ast::Trivias;
use oxc_ast::{SourceType, Trivias};
pub use scope::{Scope, ScopeTree};
pub struct Semantic<'a> {
source_type: SourceType,
nodes: AstNodes<'a>,
scopes: ScopeTree,
@ -18,6 +20,11 @@ pub struct Semantic<'a> {
}
impl<'a> Semantic<'a> {
#[must_use]
pub fn source_type(&self) -> &SourceType {
&self.source_type
}
#[must_use]
pub fn nodes(&self) -> &AstNodes<'a> {
&self.nodes

View file

@ -1,7 +1,7 @@
Babel Summary:
AST Parsed : 2056/2069 (99.37%)
Positive Passed: 2056/2069 (99.37%)
Negative Passed: 911/1502 (60.65%)
Negative Passed: 912/1502 (60.72%)
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"
@ -122,7 +122,6 @@ Expect Syntax Error: "core/uncategorised/552/input.js"
Expect Syntax Error: "es2015/class-methods/direct-super-in-object-method/input.js"
Expect Syntax Error: "es2015/class-methods/direct-super-outside-constructor/input.js"
Expect Syntax Error: "es2015/class-methods/disallow-duplicate-method-params/input.js"
Expect Syntax Error: "es2015/class/extends-strict/input.js"
Expect Syntax Error: "es2015/destructuring/binding-arguments-module/input.js"
Expect Syntax Error: "es2015/destructuring/binding-arguments-strict/input.js"
Expect Syntax Error: "es2015/destructuring/binding-eval/input.js"
@ -2043,6 +2042,14 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
╰────
help: replace with `super()` or `super.prop` or `super[prop]`
× 'with' statements are not allowed
╭─[es2015/class/extends-strict/input.js:1:1]
1 │ class C extends (function B() {
2 │ with ({});
· ────
3 │ return B;
╰────
× Keywords cannot contain escape characters
╭─[es2015/class/invalid-escape-get/input.js:1:1]
1 │ class X { ge\u0074 x() {} }

View file

@ -1,7 +1,7 @@
Test262 Summary:
AST Parsed : 44000/44009 (99.98%)
Positive Passed: 44000/44009 (99.98%)
Negative Passed: 2225/3917 (56.80%)
Negative Passed: 2231/3917 (56.96%)
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"
@ -1322,7 +1322,6 @@ Expect Syntax Error: "language/statements/class/static-init-invalid-return.js"
Expect Syntax Error: "language/statements/class/static-init-invalid-super-call.js"
Expect Syntax Error: "language/statements/class/static-init-invalid-yield.js"
Expect Syntax Error: "language/statements/class/static-method-param-yield.js"
Expect Syntax Error: "language/statements/class/strict-mode/with.js"
Expect Syntax Error: "language/statements/class/syntax/early-errors/class-definition-evaluation-block-duplicate-binding.js"
Expect Syntax Error: "language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js"
Expect Syntax Error: "language/statements/const/dstr/ary-ptrn-rest-init-ary.js"
@ -1685,15 +1684,10 @@ Expect Syntax Error: "language/statements/variable/id-eval-strict.js"
Expect Syntax Error: "language/statements/variable/static-init-await-binding-invalid.js"
Expect Syntax Error: "language/statements/while/decl-fun.js"
Expect Syntax Error: "language/statements/while/labelled-fn-stmt.js"
Expect Syntax Error: "language/statements/with/12.10.1-11gs.js"
Expect Syntax Error: "language/statements/with/decl-fun.js"
Expect Syntax Error: "language/statements/with/labelled-fn-stmt.js"
Expect Syntax Error: "language/statements/with/stict-script.js"
Expect Syntax Error: "language/statements/with/strict-fn-decl-nested-1.js"
Expect Syntax Error: "language/statements/with/strict-fn-decl-nested-2.js"
Expect Syntax Error: "language/statements/with/strict-fn-decl.js"
Expect Syntax Error: "language/statements/with/strict-fn-expr.js"
Expect Syntax Error: "language/statements/with/strict-fn-method.js"
Expect to Parse: "language/expressions/class/decorator/syntax/class-valid/decorator-member-expr-private-identifier.js"
× Unexpected token
@ -18461,6 +18455,14 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat
23 │ }
╰────
× 'with' statements are not allowed
╭─[language/statements/class/strict-mode/with.js:13:1]
13 │
14 │ class C extends (function B() { with ({}); return B; }()) {}
· ────
15 │
╰────
× Keywords cannot contain escape characters
╭─[language/statements/class/syntax/escaped-static.js:23:1]
23 │ class C {
@ -21418,6 +21420,13 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat
╰────
help: Wrap this declaration in a block statement
× 'with' statements are not allowed
╭─[language/statements/with/12.10.1-11gs.js:14:1]
14 │
15 │ with ({}) { }
· ────
╰────
× Async functions can only be declared at the top level or inside a block
╭─[language/statements/with/decl-async-fun.js:20:1]
20 │
@ -21468,6 +21477,13 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat
╰────
help: Try insert a semicolon here
× 'with' statements are not allowed
╭─[language/statements/with/labelled-fn-stmt.js:25:1]
25 │
26 │ with ({}) label1: label2: function test262() {}
· ────
╰────
× Lexical declaration cannot appear in a single-statement context
╭─[language/statements/with/let-array-with-newline.js:21:1]
21 │ if (false) {
@ -21478,6 +21494,28 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat
╰────
help: Wrap this declaration in a block statement
× 'with' statements are not allowed
╭─[language/statements/with/stict-script.js:16:1]
16 │
17 │ with ({}) {}
· ────
╰────
× 'with' statements are not allowed
╭─[language/statements/with/strict-fn-expr.js:17:1]
17 │ var o = {};
18 │ with (o) {};
· ────
19 │ };
╰────
× 'with' statements are not allowed
╭─[language/statements/with/strict-fn-method.js:16:1]
16 │
17 │ var obj = { get(a) { with(a){} } };
· ────
╰────
× Invalid assignment
╭─[language/types/boolean/S8.3_A2.1.js:14:1]
14 │

View file

@ -1,7 +1,7 @@
TypeScript Summary:
AST Parsed : 2310/2338 (98.80%)
Positive Passed: 2310/2338 (98.80%)
Negative Passed: 560/2531 (22.13%)
Negative Passed: 565/2531 (22.32%)
Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts"
Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts"
Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts"
@ -784,7 +784,6 @@ Expect Syntax Error: "expressions/functionCalls/typeArgumentInferenceConstructSi
Expect Syntax Error: "expressions/functionCalls/typeArgumentInferenceErrors.ts"
Expect Syntax Error: "expressions/functionCalls/typeArgumentInferenceWithConstraints.ts"
Expect Syntax Error: "expressions/functionCalls/typeArgumentInferenceWithObjectLiteral.ts"
Expect Syntax Error: "expressions/functions/arrowFunctionContexts.ts"
Expect Syntax Error: "expressions/functions/contextuallyTypedIifeStrict.ts"
Expect Syntax Error: "expressions/identifiers/scopeResolutionIdentifiers.ts"
Expect Syntax Error: "expressions/literals/literals.ts"
@ -1380,15 +1379,12 @@ Expect Syntax Error: "parser/ecmascript5/Statements/parserTryStatement1.d.ts"
Expect Syntax Error: "parser/ecmascript5/Statements/parserVariableStatement1.d.ts"
Expect Syntax Error: "parser/ecmascript5/Statements/parserVariableStatement2.d.ts"
Expect Syntax Error: "parser/ecmascript5/Statements/parserWhileStatement1.d.ts"
Expect Syntax Error: "parser/ecmascript5/Statements/parserWithStatement1.d.ts"
Expect Syntax Error: "parser/ecmascript5/Statements/parserWithStatement2.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/octalLiteralInStrictModeES3.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode1.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode10.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode11.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode12.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode13.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode14.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode15-negative.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode15.ts"
Expect Syntax Error: "parser/ecmascript5/StrictMode/parserStrictMode16.ts"
@ -1587,7 +1583,6 @@ Expect Syntax Error: "statements/forStatements/forStatementsMultipleInvalidDecl.
Expect Syntax Error: "statements/returnStatements/invalidReturnStatements.ts"
Expect Syntax Error: "statements/switchStatements/switchStatements.ts"
Expect Syntax Error: "statements/tryStatements/catchClauseWithTypeAnnotation.ts"
Expect Syntax Error: "statements/withStatements/withStatements.ts"
Expect Syntax Error: "types/any/anyAsConstructor.ts"
Expect Syntax Error: "types/any/anyAsGenericFunctionCall.ts"
Expect Syntax Error: "types/any/assignAnyToEveryType.ts"
@ -5340,6 +5335,22 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
18 │ (, BOOLEAN);
╰────
× 'with' statements are not allowed
╭─[expressions/functions/arrowFunctionContexts.ts:2:1]
2 │ // Arrow function used in with statement
3 │ with (window) {
· ────
4 │ var p = () => this;
╰────
× 'with' statements are not allowed
╭─[expressions/functions/arrowFunctionContexts.ts:43:1]
43 │ // Arrow function used in with statement
44 │ with (window) {
· ────
45 │ var p = () => this;
╰────
× Automatic Semicolon Insertion
╭─[expressions/newOperator/newOperatorErrorCases.ts:26:1]
26 │ // Construct expression with no parentheses for construct signature with > 0 parameters
@ -5846,6 +5857,14 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
╰────
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`
× 'with' statements are not allowed
╭─[jsdoc/typedefOnStatements.ts:38:1]
38 │ /** @typedef {{ m: string }} M */
39 │ with (name) {
· ────
40 │ }
╰────
× Unexpected token
╭─[jsx/checkJsxNamespaceNamesQuestionableForms.tsx:12:1]
12 │ <a:b></a:b>;
@ -7531,6 +7550,28 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
2 │ }
╰────
× 'with' statements are not allowed
╭─[parser/ecmascript5/Statements/parserWithStatement1.d.ts:1:1]
1 │ with (foo) {
· ────
2 │ }
╰────
× 'with' statements are not allowed
╭─[parser/ecmascript5/Statements/parserWithStatement2.ts:1:1]
1 │ with (1)
· ────
2 │ return;
╰────
× 'with' statements are not allowed
╭─[parser/ecmascript5/StrictMode/parserStrictMode14.ts:1:1]
1 │ "use strict";
2 │ with (a) {
· ────
3 │ }
╰────
× 'super' can only be used with function calls or in property accesses
╭─[parser/ecmascript5/SuperExpressions/parserSuperExpression2.ts:2:1]
2 │ M() {
@ -7832,6 +7873,14 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
╰────
help: for octal literals use the '0o' prefix instead
× 'with' statements are not allowed
╭─[salsa/plainJSBinderErrors.ts:30:1]
30 │ const redundant = 010
31 │ with (redundant) {
· ────
32 │ return toFixed()
╰────
× Jump target cannot cross function boundary.
╭─[salsa/plainJSBinderErrors.ts:37:1]
37 │ label: var x = 1
@ -8488,6 +8537,14 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
3 │
╰────
× 'with' statements are not allowed
╭─[statements/withStatements/withStatements.ts:1:1]
1 │ var x = 12;
2 │ with (x) {
· ────
3 │ name = 'twelve'
╰────
× Expect token
╭─[types/import/importWithTypeArguments.ts:1:1]
1 │ import<T>