Skip to content
Permalink
Browse files

Add TS support to @babel/parser's Scope (#9766)

* [parser] Allow plugins to extend ScopeHandler

* Directly extend Scope

* Don't use new.target to get the ScopeHandler

* [parser] Add TS enum  support to the Scope

* Remove duplicated options in tests

* Fix

* Fix flow

* Rename tests

* Add tests

* Full typescript support in scope

* Remove BIND_SIMPLE_CATCH

SCOPE_SIMPLE_CATCH was used instead

* Export TS types

* Register function declarations

* Fix body-less functions and namespaces

1) Move this.scope.exit() for functions from parseFunctionBody to the callers.
    Otherwise the scope of body-less functions was never closed.
    Also, it is easier to track scope.exit() if it is near to scope.enter()
2) Register namespace ids for export

* Disallow redeclaration of enum with const enum
  • Loading branch information...
nicolo-ribaudo committed Apr 26, 2019
1 parent 293f3c9 commit 30d507c915dcdca4cedf50a089025a8b041942f1
Showing with 3,974 additions and 98 deletions.
  1. +1 βˆ’1 packages/babel-parser/src/parser/base.js
  2. +2 βˆ’1 packages/babel-parser/src/parser/expression.js
  3. +7 βˆ’0 packages/babel-parser/src/parser/index.js
  4. +3 βˆ’3 packages/babel-parser/src/parser/lval.js
  5. +31 βˆ’24 packages/babel-parser/src/parser/statement.js
  6. +1 βˆ’1 packages/babel-parser/src/plugins/estree.js
  7. +1 βˆ’1 packages/babel-parser/src/plugins/flow.js
  8. +63 βˆ’10 packages/babel-parser/src/plugins/{typescript.js β†’ typescript/index.js}
  9. +105 βˆ’0 packages/babel-parser/src/plugins/typescript/scope.js
  10. +78 βˆ’39 packages/babel-parser/src/util/scope.js
  11. +42 βˆ’9 packages/babel-parser/src/util/scopeflags.js
  12. +3 βˆ’3 packages/babel-parser/test/fixtures/estree/typescript/literals/input.js
  13. +6 βˆ’6 packages/babel-parser/test/fixtures/estree/typescript/literals/output.json
  14. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/enum-block-scoped/input.js
  15. +137 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/enum-block-scoped/output.json
  16. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-after/input.js
  17. +169 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-after/output.json
  18. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-before/input.js
  19. +169 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-before/output.json
  20. +5 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-enum-after/input.js
  21. +172 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-enum-after/output.json
  22. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-enum-before/input.js
  23. +136 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-enum-before/output.json
  24. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-interface-after/input.js
  25. +151 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-interface-after/output.json
  26. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-interface-before/input.js
  27. +151 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-interface-before/output.json
  28. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-namespace/input.js
  29. +151 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-namespace/output.json
  30. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-type-after/input.js
  31. +150 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-type-after/output.json
  32. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-type-before/input.js
  33. +150 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/export-type-before/output.json
  34. +4 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration/index.js
  35. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-class/input.js
  36. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-class/options.json
  37. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-enum/input.js
  38. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-enum/options.json
  39. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-interface/input.js
  40. +132 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-interface/output.json
  41. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-type/input.js
  42. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-class-type/options.json
  43. 0 ...rser/test/fixtures/typescript/scope/{no-dupl-decl-type-const β†’ redeclaration-const-type}/input.js
  44. 0 ...r/test/fixtures/typescript/scope/{no-dupl-decl-type-const β†’ redeclaration-const-type}/output.json
  45. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-constenum-constenum/input.js
  46. +103 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-constenum-constenum/output.json
  47. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-constenum-enum/input.js
  48. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-constenum-enum/options.json
  49. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-class/input.js
  50. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-class/options.json
  51. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-constenum/input.js
  52. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-constenum/options.json
  53. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-enum/input.js
  54. +101 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-enum/output.json
  55. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-function/input.js
  56. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-function/options.json
  57. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-interface/input.js
  58. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-interface/options.json
  59. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-let/input.js
  60. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-let/options.json
  61. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-type/input.js
  62. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-type/options.json
  63. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-var/input.js
  64. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-var/options.json
  65. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-enum/input.js
  66. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-enum/options.json
  67. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-interface/input.js
  68. +135 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-interface/output.json
  69. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-type/input.js
  70. +134 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-type/output.json
  71. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-class/input.js
  72. +132 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-class/output.json
  73. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-enum/input.js
  74. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-enum/options.json
  75. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-function/input.js
  76. +135 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-function/output.json
  77. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-interface/input.js
  78. +131 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-interface/output.json
  79. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-let/input.js
  80. +134 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-let/output.json
  81. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-var/input.js
  82. +134 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-var/output.json
  83. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-let-enum/input.js
  84. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-let-enum/options.json
  85. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-let-interface/input.js
  86. +134 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-let-interface/output.json
  87. 0 ...l-parser/test/fixtures/typescript/scope/{no-dupl-decl-type-let β†’ redeclaration-let-type}/input.js
  88. 0 ...arser/test/fixtures/typescript/scope/{no-dupl-decl-type-let β†’ redeclaration-let-type}/output.json
  89. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-class/input.js
  90. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-class/options.json
  91. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-enum/input.js
  92. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-enum/options.json
  93. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-function/input.js
  94. +134 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-function/output.json
  95. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-interface/input.js
  96. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-interface/options.json
  97. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-let/input.js
  98. +133 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-let/output.json
  99. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-type/input.js
  100. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-type/options.json
  101. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-var/input.js
  102. +133 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-var/output.json
  103. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-var-enum/input.js
  104. +3 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-var-enum/options.json
  105. +2 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-var-interface/input.js
  106. +134 βˆ’0 packages/babel-parser/test/fixtures/typescript/scope/redeclaration-var-interface/output.json
  107. 0 ...l-parser/test/fixtures/typescript/scope/{no-dupl-decl-type-var β†’ redeclaration-var-type}/input.js
  108. 0 ...arser/test/fixtures/typescript/scope/{no-dupl-decl-type-var β†’ redeclaration-var-type}/output.json
@@ -9,7 +9,7 @@ export default class BaseParser {
// Properties set by constructor in index.js
options: Options;
inModule: boolean;
scope: ScopeHandler;
scope: ScopeHandler<*>;
plugins: PluginsMap;
filename: ?string;
sawUnambiguousESM: boolean = false;
@@ -1767,6 +1767,7 @@ export default class ExpressionParser extends LValParser {
this.parseFunctionParams((node: any), allowModifiers);
this.checkYieldAwaitInDefaultParams();
this.parseFunctionBodyAndFinish(node, type, true);
this.scope.exit();

this.state.yieldPos = oldYieldPos;
this.state.awaitPos = oldAwaitPos;
@@ -1795,6 +1796,7 @@ export default class ExpressionParser extends LValParser {
if (params) this.setArrowFunctionParameters(node, params);
this.parseFunctionBody(node, true);

this.scope.exit();
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
this.state.yieldPos = oldYieldPos;
this.state.awaitPos = oldAwaitPos;
@@ -1890,7 +1892,6 @@ export default class ExpressionParser extends LValParser {
node.body = this.parseBlock(true, false);
this.state.labels = oldLabels;
}
this.scope.exit();

this.state.inParameters = oldInParameters;
// Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
@@ -20,13 +20,20 @@ export default class Parser extends StatementParser {
options = getOptions(options);
super(options, input);

const ScopeHandler = this.getScopeHandler();

this.options = options;
this.inModule = this.options.sourceType === "module";
this.scope = new ScopeHandler(this.raise.bind(this), this.inModule);
this.plugins = pluginsMap(this.options.plugins);
this.filename = options.sourceFilename;
}

// This can be overwritten, for example, by the TypeScript plugin.
getScopeHandler(): Class<ScopeHandler<*>> {
return ScopeHandler;
}

parse(): File {
this.scope.enter(SCOPE_PROGRAM);
const file = this.startNode();
@@ -16,7 +16,7 @@ import type {
import type { Pos, Position } from "../util/location";
import { isStrictBindReservedWord } from "../util/identifier";
import { NodeUtils } from "./node";
import { type BindingTypes, BIND_NONE, BIND_OUTSIDE } from "../util/scopeflags";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags";

export default class LValParser extends NodeUtils {
// Forward-declaration: defined in expression.js
@@ -325,7 +325,7 @@ export default class LValParser extends NodeUtils {

checkLVal(
expr: Expression,
bindingType: ?BindingTypes = BIND_NONE,
bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean },
contextDescription: string,
): void {
@@ -363,7 +363,7 @@ export default class LValParser extends NodeUtils {
checkClashes[key] = true;
}
}
if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) {
if (!(bindingType & BIND_NONE)) {
this.scope.declareName(expr.name, bindingType, expr.start);
}
break;
@@ -11,7 +11,7 @@ import {
import { lineBreak, skipWhiteSpace } from "../util/whitespace";
import * as charCodes from "charcodes";
import {
BIND_SIMPLE_CATCH,
BIND_CLASS,
BIND_LEXICAL,
BIND_VAR,
BIND_FUNCTION,
@@ -662,12 +662,7 @@ export default class StatementParser extends ExpressionParser {
clause.param = this.parseBindingAtom();
const simple = clause.param.type === "Identifier";
this.scope.enter(simple ? SCOPE_SIMPLE_CATCH : 0);
this.checkLVal(
clause.param,
simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL,
null,
"catch clause",
);
this.checkLVal(clause.param, BIND_LEXICAL, null, "catch clause");
this.expect(tt.parenR);
} else {
clause.param = null;
@@ -1056,22 +1051,6 @@ export default class StatementParser extends ExpressionParser {

if (isStatement) {
node.id = this.parseFunctionId(requireId);
if (node.id && !isHangingStatement) {
// If it is a regular function declaration in sloppy mode, then it is
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
// mode depends on properties of the current scope (see
// treatFunctionsAsVar).
this.checkLVal(
node.id,
this.state.strict || node.generator || node.async
? this.scope.treatFunctionsAsVar
? BIND_VAR
: BIND_LEXICAL
: BIND_FUNCTION,
null,
"function name",
);
}
}

const oldInClassProperty = this.state.inClassProperty;
@@ -1099,6 +1078,15 @@ export default class StatementParser extends ExpressionParser {
);
});

this.scope.exit();

if (isStatement && !isHangingStatement) {
// We need to validate this _after_ parsing the function body
// because of TypeScript body-less function declarations,
// which shouldn't be added to the scope.
this.checkFunctionStatementId(node);
}

this.state.inClassProperty = oldInClassProperty;
this.state.yieldPos = oldYieldPos;
this.state.awaitPos = oldAwaitPos;
@@ -1125,6 +1113,25 @@ export default class StatementParser extends ExpressionParser {
this.checkYieldAwaitInDefaultParams();
}

checkFunctionStatementId(node: N.Function): void {
if (!node.id) return;

// If it is a regular function declaration in sloppy mode, then it is
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
// mode depends on properties of the current scope (see
// treatFunctionsAsVar).
this.checkLVal(
node.id,
this.state.strict || node.generator || node.async
? this.scope.treatFunctionsAsVar
? BIND_VAR
: BIND_LEXICAL
: BIND_FUNCTION,
null,
"function name",
);
}

// Parse a class declaration or literal (depending on the
// `isStatement` parameter).

@@ -1612,7 +1619,7 @@ export default class StatementParser extends ExpressionParser {
if (this.match(tt.name)) {
node.id = this.parseIdentifier();
if (isStatement) {
this.checkLVal(node.id, BIND_LEXICAL, undefined, "class name");
this.checkLVal(node.id, BIND_CLASS, undefined, "class name");
}
} else {
if (optionalId || !isStatement) {
@@ -105,7 +105,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>

checkLVal(
expr: N.Expression,
bindingType: ?BindingTypes = BIND_NONE,
bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean },
contextDescription: string,
): void {
@@ -2016,7 +2016,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>

checkLVal(
expr: N.Expression,
bindingType: ?BindingTypes = BIND_NONE,
bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean },
contextDescription: string,
): void {
@@ -1,12 +1,23 @@
// @flow

import type { TokenType } from "../tokenizer/types";
import { types as tt } from "../tokenizer/types";
import { types as ct } from "../tokenizer/context";
import * as N from "../types";
import type { Pos, Position } from "../util/location";
import Parser from "../parser";
import { type BindingTypes, BIND_NONE, SCOPE_OTHER } from "../util/scopeflags";
import type { TokenType } from "../../tokenizer/types";
import { types as tt } from "../../tokenizer/types";
import { types as ct } from "../../tokenizer/context";
import * as N from "../../types";
import type { Pos, Position } from "../../util/location";
import type Parser from "../../parser";
import {
type BindingTypes,
BIND_NONE,
SCOPE_OTHER,
BIND_TS_ENUM,
BIND_TS_CONST_ENUM,
BIND_TS_TYPE,
BIND_TS_INTERFACE,
BIND_TS_FN_TYPE,
BIND_TS_NAMESPACE,
} from "../../util/scopeflags";
import TypeScriptScopeHandler from "./scope";

type TsModifier =
| "readonly"
@@ -69,6 +80,10 @@ function keywordTypeFromName(

export default (superClass: Class<Parser>): Class<Parser> =>
class extends superClass {
getScopeHandler(): Class<TypeScriptScopeHandler> {
return TypeScriptScopeHandler;
}

tsIsIdentifier(): boolean {
// TODO: actually a bit more complex in TypeScript, but shouldn't matter.
// See https://github.com/Microsoft/TypeScript/issues/15008
@@ -1017,6 +1032,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.TsInterfaceDeclaration,
): N.TsInterfaceDeclaration {
node.id = this.parseIdentifier();
this.checkLVal(
node.id,
BIND_TS_INTERFACE,
undefined,
"typescript interface declaration",
);
node.typeParameters = this.tsTryParseTypeParameters();
if (this.eat(tt._extends)) {
node.extends = this.tsParseHeritageClause("extends");
@@ -1031,6 +1052,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.TsTypeAliasDeclaration,
): N.TsTypeAliasDeclaration {
node.id = this.parseIdentifier();
this.checkLVal(node.id, BIND_TS_TYPE, undefined, "typescript type alias");

node.typeParameters = this.tsTryParseTypeParameters();
node.typeAnnotation = this.tsExpectThenParseType(tt.eq);
this.semicolon();
@@ -1099,6 +1122,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
): N.TsEnumDeclaration {
if (isConst) node.const = true;
node.id = this.parseIdentifier();
this.checkLVal(
node.id,
isConst ? BIND_TS_CONST_ENUM : BIND_TS_ENUM,
undefined,
"typescript enum declaration",
);

this.expect(tt.braceL);
node.members = this.tsParseDelimitedList(
"EnumMembers",
@@ -1126,11 +1156,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>

tsParseModuleOrNamespaceDeclaration(
node: N.TsModuleDeclaration,
nested?: boolean = false,
): N.TsModuleDeclaration {
node.id = this.parseIdentifier();

if (!nested) {
this.checkLVal(
node.id,
BIND_TS_NAMESPACE,
null,
"module or namespace declaration",
);
}

if (this.eat(tt.dot)) {
const inner = this.startNode();
this.tsParseModuleOrNamespaceDeclaration(inner);
this.tsParseModuleOrNamespaceDeclaration(inner, true);
node.body = inner;
} else {
node.body = this.tsParseModuleBlock();
@@ -1260,7 +1301,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>

switch (starttype) {
case tt._function:
return this.parseFunctionStatement(nany);
return this.parseFunctionStatement(
nany,
/* async */ false,
/* declarationPosition */ true,
);
case tt._class:
return this.parseClass(
nany,
@@ -1531,6 +1576,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
super.parseFunctionBodyAndFinish(node, type, isMethod);
}

checkFunctionStatementId(node: N.Function): void {
if (!node.body && node.id) {
this.checkLVal(node.id, BIND_TS_FN_TYPE, null, "function name");
} else {
super.checkFunctionStatementId(...arguments);
}
}

parseSubscript(
base: N.Expression,
startPos: number,
@@ -2214,7 +2267,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>

checkLVal(
expr: N.Expression,
bindingType: ?BindingTypes = BIND_NONE,
bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean },
contextDescription: string,
): void {

0 comments on commit 30d507c

Please sign in to comment.
You can’t perform that action at this time.