Introduce scope tracking in the parser (#9493)
* Introduce scope tracking * Fix tests * Add new tests * Remove constructor-super check from transform as it is now in parser * Correctly handle class properties and class scope * Fix duplicate name check * Convert scope identifier storage to array * Enter a new scope in typescript module blocks * Add test for duplicate declaration * Rename error for duplicate exports * Treat class declarations as lexical declaration * Update whitelist * Add tests * Fix scope tracking for function declarations * Migrate try-catch duplicate error * Fix test * More tests * One more test * Make scope a separate class and fix review comments * Do not allow new.target in top scope arrow function * Correctly enter new scope for declare module and treat type aliases as lexical declarations * Tests for typescript scope tracking to not mark type aliases as duplicate * Fix flow scope tracking * Remove ident from test names as redundant * Add test case for var and function * Improve error messages * Improve literal regex
This commit is contained in:
@@ -9,6 +9,12 @@ import type State from "../tokenizer/state";
|
||||
import { types as tc } from "../tokenizer/context";
|
||||
import * as charCodes from "charcodes";
|
||||
import { isIteratorStart } from "../util/identifier";
|
||||
import {
|
||||
type BindingTypes,
|
||||
BIND_NONE,
|
||||
BIND_LEXICAL,
|
||||
SCOPE_OTHER,
|
||||
} from "../util/scopeflags";
|
||||
|
||||
const reservedTypes = [
|
||||
"any",
|
||||
@@ -257,6 +263,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
flowParseDeclareModule(node: N.FlowDeclareModule): N.FlowDeclareModule {
|
||||
this.next();
|
||||
|
||||
this.scope.enter(SCOPE_OTHER);
|
||||
|
||||
if (this.match(tt.string)) {
|
||||
node.id = this.parseExprAtom();
|
||||
} else {
|
||||
@@ -290,6 +298,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
body.push(bodyNode);
|
||||
}
|
||||
|
||||
this.scope.exit();
|
||||
|
||||
this.expect(tt.braceR);
|
||||
|
||||
this.finishNode(bodyNode, "BlockStatement");
|
||||
@@ -518,6 +529,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
flowParseTypeAlias(node: N.FlowTypeAlias): N.FlowTypeAlias {
|
||||
node.id = this.flowParseRestrictedIdentifier();
|
||||
this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.start);
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
@@ -537,6 +549,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
): N.FlowOpaqueType {
|
||||
this.expectContextual("type");
|
||||
node.id = this.flowParseRestrictedIdentifier(/*liberal*/ true);
|
||||
this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.start);
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
@@ -1761,7 +1774,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
"arrow function parameters",
|
||||
);
|
||||
// Use super's method to force the parameters to be checked
|
||||
super.checkFunctionNameAndParams(node, true);
|
||||
super.checkParams(node, false, true);
|
||||
} else {
|
||||
arrows.push(node);
|
||||
}
|
||||
@@ -1995,14 +2008,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
checkLVal(
|
||||
expr: N.Expression,
|
||||
isBinding: ?boolean,
|
||||
bindingType: ?BindingTypes = BIND_NONE,
|
||||
checkClashes: ?{ [key: string]: boolean },
|
||||
contextDescription: string,
|
||||
): void {
|
||||
if (expr.type !== "TypeCastExpression") {
|
||||
return super.checkLVal(
|
||||
expr,
|
||||
isBinding,
|
||||
bindingType,
|
||||
checkClashes,
|
||||
contextDescription,
|
||||
);
|
||||
@@ -2047,6 +2060,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
isGenerator: boolean,
|
||||
isAsync: boolean,
|
||||
isConstructor: boolean,
|
||||
allowsDirectSuper: boolean,
|
||||
): void {
|
||||
if ((method: $FlowFixMe).variance) {
|
||||
this.unexpected((method: $FlowFixMe).variance.start);
|
||||
@@ -2064,6 +2078,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
isGenerator,
|
||||
isAsync,
|
||||
isConstructor,
|
||||
allowsDirectSuper,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2217,7 +2232,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
? this.flowParseRestrictedIdentifier(true)
|
||||
: this.parseIdentifier();
|
||||
|
||||
this.checkLVal(specifier.local, true, undefined, contextDescription);
|
||||
this.checkLVal(
|
||||
specifier.local,
|
||||
BIND_LEXICAL,
|
||||
undefined,
|
||||
contextDescription,
|
||||
);
|
||||
node.specifiers.push(this.finishNode(specifier, type));
|
||||
}
|
||||
|
||||
@@ -2327,12 +2347,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
);
|
||||
}
|
||||
|
||||
this.checkLVal(specifier.local, true, undefined, "import specifier");
|
||||
this.checkLVal(
|
||||
specifier.local,
|
||||
BIND_LEXICAL,
|
||||
undefined,
|
||||
"import specifier",
|
||||
);
|
||||
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
|
||||
}
|
||||
|
||||
// parse function type parameters - function foo<T>() {}
|
||||
parseFunctionParams(node: N.Function): void {
|
||||
parseFunctionParams(node: N.Function, allowModifiers?: boolean): void {
|
||||
// $FlowFixMe
|
||||
const kind = node.kind;
|
||||
if (kind !== "get" && kind !== "set" && this.isRelational("<")) {
|
||||
@@ -2340,7 +2365,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
/* allowDefault */ false,
|
||||
);
|
||||
}
|
||||
super.parseFunctionParams(node);
|
||||
super.parseFunctionParams(node, allowModifiers);
|
||||
}
|
||||
|
||||
// parse flow type annotations on variable declarator heads - let foo: string = bar
|
||||
@@ -2519,8 +2544,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
checkFunctionNameAndParams(
|
||||
checkParams(
|
||||
node: N.Function,
|
||||
allowDuplicates: boolean,
|
||||
isArrowFunction: ?boolean,
|
||||
): void {
|
||||
if (
|
||||
@@ -2530,7 +2556,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return;
|
||||
}
|
||||
|
||||
return super.checkFunctionNameAndParams(node, isArrowFunction);
|
||||
return super.checkParams(node, allowDuplicates, isArrowFunction);
|
||||
}
|
||||
|
||||
parseParenAndDistinguishExpression(canBeArrow: boolean): N.Expression {
|
||||
|
||||
Reference in New Issue
Block a user