mirror of
https://github.com/crazy-max/ghaction-upx.git
synced 2024-11-23 02:46:09 -07:00
2689 lines
81 KiB
JavaScript
2689 lines
81 KiB
JavaScript
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.default = void 0;
|
||
|
||
var _types = require("../tokenizer/types");
|
||
|
||
var N = _interopRequireWildcard(require("../types"));
|
||
|
||
var _context = require("../tokenizer/context");
|
||
|
||
var _identifier = require("../util/identifier");
|
||
|
||
var _scopeflags = require("../util/scopeflags");
|
||
|
||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
||
|
||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||
|
||
const reservedTypes = new Set(["_", "any", "bool", "boolean", "empty", "extends", "false", "interface", "mixed", "null", "number", "static", "string", "true", "typeof", "void"]);
|
||
|
||
function isEsModuleType(bodyElement) {
|
||
return bodyElement.type === "DeclareExportAllDeclaration" || bodyElement.type === "DeclareExportDeclaration" && (!bodyElement.declaration || bodyElement.declaration.type !== "TypeAlias" && bodyElement.declaration.type !== "InterfaceDeclaration");
|
||
}
|
||
|
||
function hasTypeImportKind(node) {
|
||
return node.importKind === "type" || node.importKind === "typeof";
|
||
}
|
||
|
||
function isMaybeDefaultImport(state) {
|
||
return (state.type === _types.types.name || !!state.type.keyword) && state.value !== "from";
|
||
}
|
||
|
||
const exportSuggestions = {
|
||
const: "declare export var",
|
||
let: "declare export var",
|
||
type: "export type",
|
||
interface: "export interface"
|
||
};
|
||
|
||
function partition(list, test) {
|
||
const list1 = [];
|
||
const list2 = [];
|
||
|
||
for (let i = 0; i < list.length; i++) {
|
||
(test(list[i], i, list) ? list1 : list2).push(list[i]);
|
||
}
|
||
|
||
return [list1, list2];
|
||
}
|
||
|
||
const FLOW_PRAGMA_REGEX = /\*?\s*@((?:no)?flow)\b/;
|
||
|
||
var _default = superClass => class extends superClass {
|
||
constructor(options, input) {
|
||
super(options, input);
|
||
this.flowPragma = undefined;
|
||
}
|
||
|
||
shouldParseTypes() {
|
||
return this.getPluginOption("flow", "all") || this.flowPragma === "flow";
|
||
}
|
||
|
||
shouldParseEnums() {
|
||
return !!this.getPluginOption("flow", "enums");
|
||
}
|
||
|
||
finishToken(type, val) {
|
||
if (type !== _types.types.string && type !== _types.types.semi && type !== _types.types.interpreterDirective) {
|
||
if (this.flowPragma === undefined) {
|
||
this.flowPragma = null;
|
||
}
|
||
}
|
||
|
||
return super.finishToken(type, val);
|
||
}
|
||
|
||
addComment(comment) {
|
||
if (this.flowPragma === undefined) {
|
||
const matches = FLOW_PRAGMA_REGEX.exec(comment.value);
|
||
|
||
if (!matches) {} else if (matches[1] === "flow") {
|
||
this.flowPragma = "flow";
|
||
} else if (matches[1] === "noflow") {
|
||
this.flowPragma = "noflow";
|
||
} else {
|
||
throw new Error("Unexpected flow pragma");
|
||
}
|
||
}
|
||
|
||
return super.addComment(comment);
|
||
}
|
||
|
||
flowParseTypeInitialiser(tok) {
|
||
const oldInType = this.state.inType;
|
||
this.state.inType = true;
|
||
this.expect(tok || _types.types.colon);
|
||
const type = this.flowParseType();
|
||
this.state.inType = oldInType;
|
||
return type;
|
||
}
|
||
|
||
flowParsePredicate() {
|
||
const node = this.startNode();
|
||
const moduloLoc = this.state.startLoc;
|
||
const moduloPos = this.state.start;
|
||
this.expect(_types.types.modulo);
|
||
const checksLoc = this.state.startLoc;
|
||
this.expectContextual("checks");
|
||
|
||
if (moduloLoc.line !== checksLoc.line || moduloLoc.column !== checksLoc.column - 1) {
|
||
this.raise(moduloPos, "Spaces between ´%´ and ´checks´ are not allowed here.");
|
||
}
|
||
|
||
if (this.eat(_types.types.parenL)) {
|
||
node.value = this.parseExpression();
|
||
this.expect(_types.types.parenR);
|
||
return this.finishNode(node, "DeclaredPredicate");
|
||
} else {
|
||
return this.finishNode(node, "InferredPredicate");
|
||
}
|
||
}
|
||
|
||
flowParseTypeAndPredicateInitialiser() {
|
||
const oldInType = this.state.inType;
|
||
this.state.inType = true;
|
||
this.expect(_types.types.colon);
|
||
let type = null;
|
||
let predicate = null;
|
||
|
||
if (this.match(_types.types.modulo)) {
|
||
this.state.inType = oldInType;
|
||
predicate = this.flowParsePredicate();
|
||
} else {
|
||
type = this.flowParseType();
|
||
this.state.inType = oldInType;
|
||
|
||
if (this.match(_types.types.modulo)) {
|
||
predicate = this.flowParsePredicate();
|
||
}
|
||
}
|
||
|
||
return [type, predicate];
|
||
}
|
||
|
||
flowParseDeclareClass(node) {
|
||
this.next();
|
||
this.flowParseInterfaceish(node, true);
|
||
return this.finishNode(node, "DeclareClass");
|
||
}
|
||
|
||
flowParseDeclareFunction(node) {
|
||
this.next();
|
||
const id = node.id = this.parseIdentifier();
|
||
const typeNode = this.startNode();
|
||
const typeContainer = this.startNode();
|
||
|
||
if (this.isRelational("<")) {
|
||
typeNode.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
} else {
|
||
typeNode.typeParameters = null;
|
||
}
|
||
|
||
this.expect(_types.types.parenL);
|
||
const tmp = this.flowParseFunctionTypeParams();
|
||
typeNode.params = tmp.params;
|
||
typeNode.rest = tmp.rest;
|
||
this.expect(_types.types.parenR);
|
||
[typeNode.returnType, node.predicate] = this.flowParseTypeAndPredicateInitialiser();
|
||
typeContainer.typeAnnotation = this.finishNode(typeNode, "FunctionTypeAnnotation");
|
||
id.typeAnnotation = this.finishNode(typeContainer, "TypeAnnotation");
|
||
this.resetEndLocation(id);
|
||
this.semicolon();
|
||
return this.finishNode(node, "DeclareFunction");
|
||
}
|
||
|
||
flowParseDeclare(node, insideModule) {
|
||
if (this.match(_types.types._class)) {
|
||
return this.flowParseDeclareClass(node);
|
||
} else if (this.match(_types.types._function)) {
|
||
return this.flowParseDeclareFunction(node);
|
||
} else if (this.match(_types.types._var)) {
|
||
return this.flowParseDeclareVariable(node);
|
||
} else if (this.eatContextual("module")) {
|
||
if (this.match(_types.types.dot)) {
|
||
return this.flowParseDeclareModuleExports(node);
|
||
} else {
|
||
if (insideModule) {
|
||
this.raise(this.state.lastTokStart, "`declare module` cannot be used inside another `declare module`");
|
||
}
|
||
|
||
return this.flowParseDeclareModule(node);
|
||
}
|
||
} else if (this.isContextual("type")) {
|
||
return this.flowParseDeclareTypeAlias(node);
|
||
} else if (this.isContextual("opaque")) {
|
||
return this.flowParseDeclareOpaqueType(node);
|
||
} else if (this.isContextual("interface")) {
|
||
return this.flowParseDeclareInterface(node);
|
||
} else if (this.match(_types.types._export)) {
|
||
return this.flowParseDeclareExportDeclaration(node, insideModule);
|
||
} else {
|
||
throw this.unexpected();
|
||
}
|
||
}
|
||
|
||
flowParseDeclareVariable(node) {
|
||
this.next();
|
||
node.id = this.flowParseTypeAnnotatableIdentifier(true);
|
||
this.scope.declareName(node.id.name, _scopeflags.BIND_VAR, node.id.start);
|
||
this.semicolon();
|
||
return this.finishNode(node, "DeclareVariable");
|
||
}
|
||
|
||
flowParseDeclareModule(node) {
|
||
this.scope.enter(_scopeflags.SCOPE_OTHER);
|
||
|
||
if (this.match(_types.types.string)) {
|
||
node.id = this.parseExprAtom();
|
||
} else {
|
||
node.id = this.parseIdentifier();
|
||
}
|
||
|
||
const bodyNode = node.body = this.startNode();
|
||
const body = bodyNode.body = [];
|
||
this.expect(_types.types.braceL);
|
||
|
||
while (!this.match(_types.types.braceR)) {
|
||
let bodyNode = this.startNode();
|
||
|
||
if (this.match(_types.types._import)) {
|
||
this.next();
|
||
|
||
if (!this.isContextual("type") && !this.match(_types.types._typeof)) {
|
||
this.raise(this.state.lastTokStart, "Imports within a `declare module` body must always be `import type` or `import typeof`");
|
||
}
|
||
|
||
this.parseImport(bodyNode);
|
||
} else {
|
||
this.expectContextual("declare", "Only declares and type imports are allowed inside declare module");
|
||
bodyNode = this.flowParseDeclare(bodyNode, true);
|
||
}
|
||
|
||
body.push(bodyNode);
|
||
}
|
||
|
||
this.scope.exit();
|
||
this.expect(_types.types.braceR);
|
||
this.finishNode(bodyNode, "BlockStatement");
|
||
let kind = null;
|
||
let hasModuleExport = false;
|
||
const errorMessage = "Found both `declare module.exports` and `declare export` in the same module. " + "Modules can only have 1 since they are either an ES module or they are a CommonJS module";
|
||
body.forEach(bodyElement => {
|
||
if (isEsModuleType(bodyElement)) {
|
||
if (kind === "CommonJS") {
|
||
this.raise(bodyElement.start, errorMessage);
|
||
}
|
||
|
||
kind = "ES";
|
||
} else if (bodyElement.type === "DeclareModuleExports") {
|
||
if (hasModuleExport) {
|
||
this.raise(bodyElement.start, "Duplicate `declare module.exports` statement");
|
||
}
|
||
|
||
if (kind === "ES") this.raise(bodyElement.start, errorMessage);
|
||
kind = "CommonJS";
|
||
hasModuleExport = true;
|
||
}
|
||
});
|
||
node.kind = kind || "CommonJS";
|
||
return this.finishNode(node, "DeclareModule");
|
||
}
|
||
|
||
flowParseDeclareExportDeclaration(node, insideModule) {
|
||
this.expect(_types.types._export);
|
||
|
||
if (this.eat(_types.types._default)) {
|
||
if (this.match(_types.types._function) || this.match(_types.types._class)) {
|
||
node.declaration = this.flowParseDeclare(this.startNode());
|
||
} else {
|
||
node.declaration = this.flowParseType();
|
||
this.semicolon();
|
||
}
|
||
|
||
node.default = true;
|
||
return this.finishNode(node, "DeclareExportDeclaration");
|
||
} else {
|
||
if (this.match(_types.types._const) || this.isLet() || (this.isContextual("type") || this.isContextual("interface")) && !insideModule) {
|
||
const label = this.state.value;
|
||
const suggestion = exportSuggestions[label];
|
||
this.unexpected(this.state.start, `\`declare export ${label}\` is not supported. Use \`${suggestion}\` instead`);
|
||
}
|
||
|
||
if (this.match(_types.types._var) || this.match(_types.types._function) || this.match(_types.types._class) || this.isContextual("opaque")) {
|
||
node.declaration = this.flowParseDeclare(this.startNode());
|
||
node.default = false;
|
||
return this.finishNode(node, "DeclareExportDeclaration");
|
||
} else if (this.match(_types.types.star) || this.match(_types.types.braceL) || this.isContextual("interface") || this.isContextual("type") || this.isContextual("opaque")) {
|
||
node = this.parseExport(node);
|
||
|
||
if (node.type === "ExportNamedDeclaration") {
|
||
node.type = "ExportDeclaration";
|
||
node.default = false;
|
||
delete node.exportKind;
|
||
}
|
||
|
||
node.type = "Declare" + node.type;
|
||
return node;
|
||
}
|
||
}
|
||
|
||
throw this.unexpected();
|
||
}
|
||
|
||
flowParseDeclareModuleExports(node) {
|
||
this.next();
|
||
this.expectContextual("exports");
|
||
node.typeAnnotation = this.flowParseTypeAnnotation();
|
||
this.semicolon();
|
||
return this.finishNode(node, "DeclareModuleExports");
|
||
}
|
||
|
||
flowParseDeclareTypeAlias(node) {
|
||
this.next();
|
||
this.flowParseTypeAlias(node);
|
||
node.type = "DeclareTypeAlias";
|
||
return node;
|
||
}
|
||
|
||
flowParseDeclareOpaqueType(node) {
|
||
this.next();
|
||
this.flowParseOpaqueType(node, true);
|
||
node.type = "DeclareOpaqueType";
|
||
return node;
|
||
}
|
||
|
||
flowParseDeclareInterface(node) {
|
||
this.next();
|
||
this.flowParseInterfaceish(node);
|
||
return this.finishNode(node, "DeclareInterface");
|
||
}
|
||
|
||
flowParseInterfaceish(node, isClass = false) {
|
||
node.id = this.flowParseRestrictedIdentifier(!isClass, true);
|
||
this.scope.declareName(node.id.name, isClass ? _scopeflags.BIND_FUNCTION : _scopeflags.BIND_LEXICAL, node.id.start);
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
} else {
|
||
node.typeParameters = null;
|
||
}
|
||
|
||
node.extends = [];
|
||
node.implements = [];
|
||
node.mixins = [];
|
||
|
||
if (this.eat(_types.types._extends)) {
|
||
do {
|
||
node.extends.push(this.flowParseInterfaceExtends());
|
||
} while (!isClass && this.eat(_types.types.comma));
|
||
}
|
||
|
||
if (this.isContextual("mixins")) {
|
||
this.next();
|
||
|
||
do {
|
||
node.mixins.push(this.flowParseInterfaceExtends());
|
||
} while (this.eat(_types.types.comma));
|
||
}
|
||
|
||
if (this.isContextual("implements")) {
|
||
this.next();
|
||
|
||
do {
|
||
node.implements.push(this.flowParseInterfaceExtends());
|
||
} while (this.eat(_types.types.comma));
|
||
}
|
||
|
||
node.body = this.flowParseObjectType({
|
||
allowStatic: isClass,
|
||
allowExact: false,
|
||
allowSpread: false,
|
||
allowProto: isClass,
|
||
allowInexact: false
|
||
});
|
||
}
|
||
|
||
flowParseInterfaceExtends() {
|
||
const node = this.startNode();
|
||
node.id = this.flowParseQualifiedTypeIdentifier();
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterInstantiation();
|
||
} else {
|
||
node.typeParameters = null;
|
||
}
|
||
|
||
return this.finishNode(node, "InterfaceExtends");
|
||
}
|
||
|
||
flowParseInterface(node) {
|
||
this.flowParseInterfaceish(node);
|
||
return this.finishNode(node, "InterfaceDeclaration");
|
||
}
|
||
|
||
checkNotUnderscore(word) {
|
||
if (word === "_") {
|
||
this.raise(this.state.start, "`_` is only allowed as a type argument to call or new");
|
||
}
|
||
}
|
||
|
||
checkReservedType(word, startLoc, declaration) {
|
||
if (!reservedTypes.has(word)) return;
|
||
|
||
if (declaration) {
|
||
this.raise(startLoc, `Cannot overwrite reserved type ${word}`);
|
||
return;
|
||
}
|
||
|
||
this.raise(startLoc, `Unexpected reserved type ${word}`);
|
||
}
|
||
|
||
flowParseRestrictedIdentifier(liberal, declaration) {
|
||
this.checkReservedType(this.state.value, this.state.start, declaration);
|
||
return this.parseIdentifier(liberal);
|
||
}
|
||
|
||
flowParseTypeAlias(node) {
|
||
node.id = this.flowParseRestrictedIdentifier(false, true);
|
||
this.scope.declareName(node.id.name, _scopeflags.BIND_LEXICAL, node.id.start);
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
} else {
|
||
node.typeParameters = null;
|
||
}
|
||
|
||
node.right = this.flowParseTypeInitialiser(_types.types.eq);
|
||
this.semicolon();
|
||
return this.finishNode(node, "TypeAlias");
|
||
}
|
||
|
||
flowParseOpaqueType(node, declare) {
|
||
this.expectContextual("type");
|
||
node.id = this.flowParseRestrictedIdentifier(true, true);
|
||
this.scope.declareName(node.id.name, _scopeflags.BIND_LEXICAL, node.id.start);
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
} else {
|
||
node.typeParameters = null;
|
||
}
|
||
|
||
node.supertype = null;
|
||
|
||
if (this.match(_types.types.colon)) {
|
||
node.supertype = this.flowParseTypeInitialiser(_types.types.colon);
|
||
}
|
||
|
||
node.impltype = null;
|
||
|
||
if (!declare) {
|
||
node.impltype = this.flowParseTypeInitialiser(_types.types.eq);
|
||
}
|
||
|
||
this.semicolon();
|
||
return this.finishNode(node, "OpaqueType");
|
||
}
|
||
|
||
flowParseTypeParameter(requireDefault = false) {
|
||
const nodeStart = this.state.start;
|
||
const node = this.startNode();
|
||
const variance = this.flowParseVariance();
|
||
const ident = this.flowParseTypeAnnotatableIdentifier();
|
||
node.name = ident.name;
|
||
node.variance = variance;
|
||
node.bound = ident.typeAnnotation;
|
||
|
||
if (this.match(_types.types.eq)) {
|
||
this.eat(_types.types.eq);
|
||
node.default = this.flowParseType();
|
||
} else {
|
||
if (requireDefault) {
|
||
this.raise(nodeStart, "Type parameter declaration needs a default, since a preceding type parameter declaration has a default.");
|
||
}
|
||
}
|
||
|
||
return this.finishNode(node, "TypeParameter");
|
||
}
|
||
|
||
flowParseTypeParameterDeclaration() {
|
||
const oldInType = this.state.inType;
|
||
const node = this.startNode();
|
||
node.params = [];
|
||
this.state.inType = true;
|
||
|
||
if (this.isRelational("<") || this.match(_types.types.jsxTagStart)) {
|
||
this.next();
|
||
} else {
|
||
this.unexpected();
|
||
}
|
||
|
||
let defaultRequired = false;
|
||
|
||
do {
|
||
const typeParameter = this.flowParseTypeParameter(defaultRequired);
|
||
node.params.push(typeParameter);
|
||
|
||
if (typeParameter.default) {
|
||
defaultRequired = true;
|
||
}
|
||
|
||
if (!this.isRelational(">")) {
|
||
this.expect(_types.types.comma);
|
||
}
|
||
} while (!this.isRelational(">"));
|
||
|
||
this.expectRelational(">");
|
||
this.state.inType = oldInType;
|
||
return this.finishNode(node, "TypeParameterDeclaration");
|
||
}
|
||
|
||
flowParseTypeParameterInstantiation() {
|
||
const node = this.startNode();
|
||
const oldInType = this.state.inType;
|
||
node.params = [];
|
||
this.state.inType = true;
|
||
this.expectRelational("<");
|
||
const oldNoAnonFunctionType = this.state.noAnonFunctionType;
|
||
this.state.noAnonFunctionType = false;
|
||
|
||
while (!this.isRelational(">")) {
|
||
node.params.push(this.flowParseType());
|
||
|
||
if (!this.isRelational(">")) {
|
||
this.expect(_types.types.comma);
|
||
}
|
||
}
|
||
|
||
this.state.noAnonFunctionType = oldNoAnonFunctionType;
|
||
this.expectRelational(">");
|
||
this.state.inType = oldInType;
|
||
return this.finishNode(node, "TypeParameterInstantiation");
|
||
}
|
||
|
||
flowParseTypeParameterInstantiationCallOrNew() {
|
||
const node = this.startNode();
|
||
const oldInType = this.state.inType;
|
||
node.params = [];
|
||
this.state.inType = true;
|
||
this.expectRelational("<");
|
||
|
||
while (!this.isRelational(">")) {
|
||
node.params.push(this.flowParseTypeOrImplicitInstantiation());
|
||
|
||
if (!this.isRelational(">")) {
|
||
this.expect(_types.types.comma);
|
||
}
|
||
}
|
||
|
||
this.expectRelational(">");
|
||
this.state.inType = oldInType;
|
||
return this.finishNode(node, "TypeParameterInstantiation");
|
||
}
|
||
|
||
flowParseInterfaceType() {
|
||
const node = this.startNode();
|
||
this.expectContextual("interface");
|
||
node.extends = [];
|
||
|
||
if (this.eat(_types.types._extends)) {
|
||
do {
|
||
node.extends.push(this.flowParseInterfaceExtends());
|
||
} while (this.eat(_types.types.comma));
|
||
}
|
||
|
||
node.body = this.flowParseObjectType({
|
||
allowStatic: false,
|
||
allowExact: false,
|
||
allowSpread: false,
|
||
allowProto: false,
|
||
allowInexact: false
|
||
});
|
||
return this.finishNode(node, "InterfaceTypeAnnotation");
|
||
}
|
||
|
||
flowParseObjectPropertyKey() {
|
||
return this.match(_types.types.num) || this.match(_types.types.string) ? this.parseExprAtom() : this.parseIdentifier(true);
|
||
}
|
||
|
||
flowParseObjectTypeIndexer(node, isStatic, variance) {
|
||
node.static = isStatic;
|
||
|
||
if (this.lookahead().type === _types.types.colon) {
|
||
node.id = this.flowParseObjectPropertyKey();
|
||
node.key = this.flowParseTypeInitialiser();
|
||
} else {
|
||
node.id = null;
|
||
node.key = this.flowParseType();
|
||
}
|
||
|
||
this.expect(_types.types.bracketR);
|
||
node.value = this.flowParseTypeInitialiser();
|
||
node.variance = variance;
|
||
return this.finishNode(node, "ObjectTypeIndexer");
|
||
}
|
||
|
||
flowParseObjectTypeInternalSlot(node, isStatic) {
|
||
node.static = isStatic;
|
||
node.id = this.flowParseObjectPropertyKey();
|
||
this.expect(_types.types.bracketR);
|
||
this.expect(_types.types.bracketR);
|
||
|
||
if (this.isRelational("<") || this.match(_types.types.parenL)) {
|
||
node.method = true;
|
||
node.optional = false;
|
||
node.value = this.flowParseObjectTypeMethodish(this.startNodeAt(node.start, node.loc.start));
|
||
} else {
|
||
node.method = false;
|
||
|
||
if (this.eat(_types.types.question)) {
|
||
node.optional = true;
|
||
}
|
||
|
||
node.value = this.flowParseTypeInitialiser();
|
||
}
|
||
|
||
return this.finishNode(node, "ObjectTypeInternalSlot");
|
||
}
|
||
|
||
flowParseObjectTypeMethodish(node) {
|
||
node.params = [];
|
||
node.rest = null;
|
||
node.typeParameters = null;
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
}
|
||
|
||
this.expect(_types.types.parenL);
|
||
|
||
while (!this.match(_types.types.parenR) && !this.match(_types.types.ellipsis)) {
|
||
node.params.push(this.flowParseFunctionTypeParam());
|
||
|
||
if (!this.match(_types.types.parenR)) {
|
||
this.expect(_types.types.comma);
|
||
}
|
||
}
|
||
|
||
if (this.eat(_types.types.ellipsis)) {
|
||
node.rest = this.flowParseFunctionTypeParam();
|
||
}
|
||
|
||
this.expect(_types.types.parenR);
|
||
node.returnType = this.flowParseTypeInitialiser();
|
||
return this.finishNode(node, "FunctionTypeAnnotation");
|
||
}
|
||
|
||
flowParseObjectTypeCallProperty(node, isStatic) {
|
||
const valueNode = this.startNode();
|
||
node.static = isStatic;
|
||
node.value = this.flowParseObjectTypeMethodish(valueNode);
|
||
return this.finishNode(node, "ObjectTypeCallProperty");
|
||
}
|
||
|
||
flowParseObjectType({
|
||
allowStatic,
|
||
allowExact,
|
||
allowSpread,
|
||
allowProto,
|
||
allowInexact
|
||
}) {
|
||
const oldInType = this.state.inType;
|
||
this.state.inType = true;
|
||
const nodeStart = this.startNode();
|
||
nodeStart.callProperties = [];
|
||
nodeStart.properties = [];
|
||
nodeStart.indexers = [];
|
||
nodeStart.internalSlots = [];
|
||
let endDelim;
|
||
let exact;
|
||
let inexact = false;
|
||
|
||
if (allowExact && this.match(_types.types.braceBarL)) {
|
||
this.expect(_types.types.braceBarL);
|
||
endDelim = _types.types.braceBarR;
|
||
exact = true;
|
||
} else {
|
||
this.expect(_types.types.braceL);
|
||
endDelim = _types.types.braceR;
|
||
exact = false;
|
||
}
|
||
|
||
nodeStart.exact = exact;
|
||
|
||
while (!this.match(endDelim)) {
|
||
let isStatic = false;
|
||
let protoStart = null;
|
||
let inexactStart = null;
|
||
const node = this.startNode();
|
||
|
||
if (allowProto && this.isContextual("proto")) {
|
||
const lookahead = this.lookahead();
|
||
|
||
if (lookahead.type !== _types.types.colon && lookahead.type !== _types.types.question) {
|
||
this.next();
|
||
protoStart = this.state.start;
|
||
allowStatic = false;
|
||
}
|
||
}
|
||
|
||
if (allowStatic && this.isContextual("static")) {
|
||
const lookahead = this.lookahead();
|
||
|
||
if (lookahead.type !== _types.types.colon && lookahead.type !== _types.types.question) {
|
||
this.next();
|
||
isStatic = true;
|
||
}
|
||
}
|
||
|
||
const variance = this.flowParseVariance();
|
||
|
||
if (this.eat(_types.types.bracketL)) {
|
||
if (protoStart != null) {
|
||
this.unexpected(protoStart);
|
||
}
|
||
|
||
if (this.eat(_types.types.bracketL)) {
|
||
if (variance) {
|
||
this.unexpected(variance.start);
|
||
}
|
||
|
||
nodeStart.internalSlots.push(this.flowParseObjectTypeInternalSlot(node, isStatic));
|
||
} else {
|
||
nodeStart.indexers.push(this.flowParseObjectTypeIndexer(node, isStatic, variance));
|
||
}
|
||
} else if (this.match(_types.types.parenL) || this.isRelational("<")) {
|
||
if (protoStart != null) {
|
||
this.unexpected(protoStart);
|
||
}
|
||
|
||
if (variance) {
|
||
this.unexpected(variance.start);
|
||
}
|
||
|
||
nodeStart.callProperties.push(this.flowParseObjectTypeCallProperty(node, isStatic));
|
||
} else {
|
||
let kind = "init";
|
||
|
||
if (this.isContextual("get") || this.isContextual("set")) {
|
||
const lookahead = this.lookahead();
|
||
|
||
if (lookahead.type === _types.types.name || lookahead.type === _types.types.string || lookahead.type === _types.types.num) {
|
||
kind = this.state.value;
|
||
this.next();
|
||
}
|
||
}
|
||
|
||
const propOrInexact = this.flowParseObjectTypeProperty(node, isStatic, protoStart, variance, kind, allowSpread, allowInexact != null ? allowInexact : !exact);
|
||
|
||
if (propOrInexact === null) {
|
||
inexact = true;
|
||
inexactStart = this.state.lastTokStart;
|
||
} else {
|
||
nodeStart.properties.push(propOrInexact);
|
||
}
|
||
}
|
||
|
||
this.flowObjectTypeSemicolon();
|
||
|
||
if (inexactStart && !this.match(_types.types.braceR) && !this.match(_types.types.braceBarR)) {
|
||
this.raise(inexactStart, "Explicit inexact syntax must appear at the end of an inexact object");
|
||
}
|
||
}
|
||
|
||
this.expect(endDelim);
|
||
|
||
if (allowSpread) {
|
||
nodeStart.inexact = inexact;
|
||
}
|
||
|
||
const out = this.finishNode(nodeStart, "ObjectTypeAnnotation");
|
||
this.state.inType = oldInType;
|
||
return out;
|
||
}
|
||
|
||
flowParseObjectTypeProperty(node, isStatic, protoStart, variance, kind, allowSpread, allowInexact) {
|
||
if (this.eat(_types.types.ellipsis)) {
|
||
const isInexactToken = this.match(_types.types.comma) || this.match(_types.types.semi) || this.match(_types.types.braceR) || this.match(_types.types.braceBarR);
|
||
|
||
if (isInexactToken) {
|
||
if (!allowSpread) {
|
||
this.raise(this.state.lastTokStart, "Explicit inexact syntax cannot appear in class or interface definitions");
|
||
} else if (!allowInexact) {
|
||
this.raise(this.state.lastTokStart, "Explicit inexact syntax cannot appear inside an explicit exact object type");
|
||
}
|
||
|
||
if (variance) {
|
||
this.raise(variance.start, "Explicit inexact syntax cannot have variance");
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
if (!allowSpread) {
|
||
this.raise(this.state.lastTokStart, "Spread operator cannot appear in class or interface definitions");
|
||
}
|
||
|
||
if (protoStart != null) {
|
||
this.unexpected(protoStart);
|
||
}
|
||
|
||
if (variance) {
|
||
this.raise(variance.start, "Spread properties cannot have variance");
|
||
}
|
||
|
||
node.argument = this.flowParseType();
|
||
return this.finishNode(node, "ObjectTypeSpreadProperty");
|
||
} else {
|
||
node.key = this.flowParseObjectPropertyKey();
|
||
node.static = isStatic;
|
||
node.proto = protoStart != null;
|
||
node.kind = kind;
|
||
let optional = false;
|
||
|
||
if (this.isRelational("<") || this.match(_types.types.parenL)) {
|
||
node.method = true;
|
||
|
||
if (protoStart != null) {
|
||
this.unexpected(protoStart);
|
||
}
|
||
|
||
if (variance) {
|
||
this.unexpected(variance.start);
|
||
}
|
||
|
||
node.value = this.flowParseObjectTypeMethodish(this.startNodeAt(node.start, node.loc.start));
|
||
|
||
if (kind === "get" || kind === "set") {
|
||
this.flowCheckGetterSetterParams(node);
|
||
}
|
||
} else {
|
||
if (kind !== "init") this.unexpected();
|
||
node.method = false;
|
||
|
||
if (this.eat(_types.types.question)) {
|
||
optional = true;
|
||
}
|
||
|
||
node.value = this.flowParseTypeInitialiser();
|
||
node.variance = variance;
|
||
}
|
||
|
||
node.optional = optional;
|
||
return this.finishNode(node, "ObjectTypeProperty");
|
||
}
|
||
}
|
||
|
||
flowCheckGetterSetterParams(property) {
|
||
const paramCount = property.kind === "get" ? 0 : 1;
|
||
const start = property.start;
|
||
const length = property.value.params.length + (property.value.rest ? 1 : 0);
|
||
|
||
if (length !== paramCount) {
|
||
if (property.kind === "get") {
|
||
this.raise(start, "getter must not have any formal parameters");
|
||
} else {
|
||
this.raise(start, "setter must have exactly one formal parameter");
|
||
}
|
||
}
|
||
|
||
if (property.kind === "set" && property.value.rest) {
|
||
this.raise(start, "setter function argument must not be a rest parameter");
|
||
}
|
||
}
|
||
|
||
flowObjectTypeSemicolon() {
|
||
if (!this.eat(_types.types.semi) && !this.eat(_types.types.comma) && !this.match(_types.types.braceR) && !this.match(_types.types.braceBarR)) {
|
||
this.unexpected();
|
||
}
|
||
}
|
||
|
||
flowParseQualifiedTypeIdentifier(startPos, startLoc, id) {
|
||
startPos = startPos || this.state.start;
|
||
startLoc = startLoc || this.state.startLoc;
|
||
let node = id || this.flowParseRestrictedIdentifier(true);
|
||
|
||
while (this.eat(_types.types.dot)) {
|
||
const node2 = this.startNodeAt(startPos, startLoc);
|
||
node2.qualification = node;
|
||
node2.id = this.flowParseRestrictedIdentifier(true);
|
||
node = this.finishNode(node2, "QualifiedTypeIdentifier");
|
||
}
|
||
|
||
return node;
|
||
}
|
||
|
||
flowParseGenericType(startPos, startLoc, id) {
|
||
const node = this.startNodeAt(startPos, startLoc);
|
||
node.typeParameters = null;
|
||
node.id = this.flowParseQualifiedTypeIdentifier(startPos, startLoc, id);
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterInstantiation();
|
||
}
|
||
|
||
return this.finishNode(node, "GenericTypeAnnotation");
|
||
}
|
||
|
||
flowParseTypeofType() {
|
||
const node = this.startNode();
|
||
this.expect(_types.types._typeof);
|
||
node.argument = this.flowParsePrimaryType();
|
||
return this.finishNode(node, "TypeofTypeAnnotation");
|
||
}
|
||
|
||
flowParseTupleType() {
|
||
const node = this.startNode();
|
||
node.types = [];
|
||
this.expect(_types.types.bracketL);
|
||
|
||
while (this.state.pos < this.length && !this.match(_types.types.bracketR)) {
|
||
node.types.push(this.flowParseType());
|
||
if (this.match(_types.types.bracketR)) break;
|
||
this.expect(_types.types.comma);
|
||
}
|
||
|
||
this.expect(_types.types.bracketR);
|
||
return this.finishNode(node, "TupleTypeAnnotation");
|
||
}
|
||
|
||
flowParseFunctionTypeParam() {
|
||
let name = null;
|
||
let optional = false;
|
||
let typeAnnotation = null;
|
||
const node = this.startNode();
|
||
const lh = this.lookahead();
|
||
|
||
if (lh.type === _types.types.colon || lh.type === _types.types.question) {
|
||
name = this.parseIdentifier();
|
||
|
||
if (this.eat(_types.types.question)) {
|
||
optional = true;
|
||
}
|
||
|
||
typeAnnotation = this.flowParseTypeInitialiser();
|
||
} else {
|
||
typeAnnotation = this.flowParseType();
|
||
}
|
||
|
||
node.name = name;
|
||
node.optional = optional;
|
||
node.typeAnnotation = typeAnnotation;
|
||
return this.finishNode(node, "FunctionTypeParam");
|
||
}
|
||
|
||
reinterpretTypeAsFunctionTypeParam(type) {
|
||
const node = this.startNodeAt(type.start, type.loc.start);
|
||
node.name = null;
|
||
node.optional = false;
|
||
node.typeAnnotation = type;
|
||
return this.finishNode(node, "FunctionTypeParam");
|
||
}
|
||
|
||
flowParseFunctionTypeParams(params = []) {
|
||
let rest = null;
|
||
|
||
while (!this.match(_types.types.parenR) && !this.match(_types.types.ellipsis)) {
|
||
params.push(this.flowParseFunctionTypeParam());
|
||
|
||
if (!this.match(_types.types.parenR)) {
|
||
this.expect(_types.types.comma);
|
||
}
|
||
}
|
||
|
||
if (this.eat(_types.types.ellipsis)) {
|
||
rest = this.flowParseFunctionTypeParam();
|
||
}
|
||
|
||
return {
|
||
params,
|
||
rest
|
||
};
|
||
}
|
||
|
||
flowIdentToTypeAnnotation(startPos, startLoc, node, id) {
|
||
switch (id.name) {
|
||
case "any":
|
||
return this.finishNode(node, "AnyTypeAnnotation");
|
||
|
||
case "bool":
|
||
case "boolean":
|
||
return this.finishNode(node, "BooleanTypeAnnotation");
|
||
|
||
case "mixed":
|
||
return this.finishNode(node, "MixedTypeAnnotation");
|
||
|
||
case "empty":
|
||
return this.finishNode(node, "EmptyTypeAnnotation");
|
||
|
||
case "number":
|
||
return this.finishNode(node, "NumberTypeAnnotation");
|
||
|
||
case "string":
|
||
return this.finishNode(node, "StringTypeAnnotation");
|
||
|
||
default:
|
||
this.checkNotUnderscore(id.name);
|
||
return this.flowParseGenericType(startPos, startLoc, id);
|
||
}
|
||
}
|
||
|
||
flowParsePrimaryType() {
|
||
const startPos = this.state.start;
|
||
const startLoc = this.state.startLoc;
|
||
const node = this.startNode();
|
||
let tmp;
|
||
let type;
|
||
let isGroupedType = false;
|
||
const oldNoAnonFunctionType = this.state.noAnonFunctionType;
|
||
|
||
switch (this.state.type) {
|
||
case _types.types.name:
|
||
if (this.isContextual("interface")) {
|
||
return this.flowParseInterfaceType();
|
||
}
|
||
|
||
return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdentifier());
|
||
|
||
case _types.types.braceL:
|
||
return this.flowParseObjectType({
|
||
allowStatic: false,
|
||
allowExact: false,
|
||
allowSpread: true,
|
||
allowProto: false,
|
||
allowInexact: true
|
||
});
|
||
|
||
case _types.types.braceBarL:
|
||
return this.flowParseObjectType({
|
||
allowStatic: false,
|
||
allowExact: true,
|
||
allowSpread: true,
|
||
allowProto: false,
|
||
allowInexact: false
|
||
});
|
||
|
||
case _types.types.bracketL:
|
||
this.state.noAnonFunctionType = false;
|
||
type = this.flowParseTupleType();
|
||
this.state.noAnonFunctionType = oldNoAnonFunctionType;
|
||
return type;
|
||
|
||
case _types.types.relational:
|
||
if (this.state.value === "<") {
|
||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
this.expect(_types.types.parenL);
|
||
tmp = this.flowParseFunctionTypeParams();
|
||
node.params = tmp.params;
|
||
node.rest = tmp.rest;
|
||
this.expect(_types.types.parenR);
|
||
this.expect(_types.types.arrow);
|
||
node.returnType = this.flowParseType();
|
||
return this.finishNode(node, "FunctionTypeAnnotation");
|
||
}
|
||
|
||
break;
|
||
|
||
case _types.types.parenL:
|
||
this.next();
|
||
|
||
if (!this.match(_types.types.parenR) && !this.match(_types.types.ellipsis)) {
|
||
if (this.match(_types.types.name)) {
|
||
const token = this.lookahead().type;
|
||
isGroupedType = token !== _types.types.question && token !== _types.types.colon;
|
||
} else {
|
||
isGroupedType = true;
|
||
}
|
||
}
|
||
|
||
if (isGroupedType) {
|
||
this.state.noAnonFunctionType = false;
|
||
type = this.flowParseType();
|
||
this.state.noAnonFunctionType = oldNoAnonFunctionType;
|
||
|
||
if (this.state.noAnonFunctionType || !(this.match(_types.types.comma) || this.match(_types.types.parenR) && this.lookahead().type === _types.types.arrow)) {
|
||
this.expect(_types.types.parenR);
|
||
return type;
|
||
} else {
|
||
this.eat(_types.types.comma);
|
||
}
|
||
}
|
||
|
||
if (type) {
|
||
tmp = this.flowParseFunctionTypeParams([this.reinterpretTypeAsFunctionTypeParam(type)]);
|
||
} else {
|
||
tmp = this.flowParseFunctionTypeParams();
|
||
}
|
||
|
||
node.params = tmp.params;
|
||
node.rest = tmp.rest;
|
||
this.expect(_types.types.parenR);
|
||
this.expect(_types.types.arrow);
|
||
node.returnType = this.flowParseType();
|
||
node.typeParameters = null;
|
||
return this.finishNode(node, "FunctionTypeAnnotation");
|
||
|
||
case _types.types.string:
|
||
return this.parseLiteral(this.state.value, "StringLiteralTypeAnnotation");
|
||
|
||
case _types.types._true:
|
||
case _types.types._false:
|
||
node.value = this.match(_types.types._true);
|
||
this.next();
|
||
return this.finishNode(node, "BooleanLiteralTypeAnnotation");
|
||
|
||
case _types.types.plusMin:
|
||
if (this.state.value === "-") {
|
||
this.next();
|
||
|
||
if (this.match(_types.types.num)) {
|
||
return this.parseLiteral(-this.state.value, "NumberLiteralTypeAnnotation", node.start, node.loc.start);
|
||
}
|
||
|
||
if (this.match(_types.types.bigint)) {
|
||
return this.parseLiteral(-this.state.value, "BigIntLiteralTypeAnnotation", node.start, node.loc.start);
|
||
}
|
||
|
||
throw this.raise(this.state.start, `Unexpected token, expected "number" or "bigint"`);
|
||
}
|
||
|
||
this.unexpected();
|
||
|
||
case _types.types.num:
|
||
return this.parseLiteral(this.state.value, "NumberLiteralTypeAnnotation");
|
||
|
||
case _types.types.bigint:
|
||
return this.parseLiteral(this.state.value, "BigIntLiteralTypeAnnotation");
|
||
|
||
case _types.types._void:
|
||
this.next();
|
||
return this.finishNode(node, "VoidTypeAnnotation");
|
||
|
||
case _types.types._null:
|
||
this.next();
|
||
return this.finishNode(node, "NullLiteralTypeAnnotation");
|
||
|
||
case _types.types._this:
|
||
this.next();
|
||
return this.finishNode(node, "ThisTypeAnnotation");
|
||
|
||
case _types.types.star:
|
||
this.next();
|
||
return this.finishNode(node, "ExistsTypeAnnotation");
|
||
|
||
default:
|
||
if (this.state.type.keyword === "typeof") {
|
||
return this.flowParseTypeofType();
|
||
} else if (this.state.type.keyword) {
|
||
const label = this.state.type.label;
|
||
this.next();
|
||
return super.createIdentifier(node, label);
|
||
}
|
||
|
||
}
|
||
|
||
throw this.unexpected();
|
||
}
|
||
|
||
flowParsePostfixType() {
|
||
const startPos = this.state.start,
|
||
startLoc = this.state.startLoc;
|
||
let type = this.flowParsePrimaryType();
|
||
|
||
while (this.match(_types.types.bracketL) && !this.canInsertSemicolon()) {
|
||
const node = this.startNodeAt(startPos, startLoc);
|
||
node.elementType = type;
|
||
this.expect(_types.types.bracketL);
|
||
this.expect(_types.types.bracketR);
|
||
type = this.finishNode(node, "ArrayTypeAnnotation");
|
||
}
|
||
|
||
return type;
|
||
}
|
||
|
||
flowParsePrefixType() {
|
||
const node = this.startNode();
|
||
|
||
if (this.eat(_types.types.question)) {
|
||
node.typeAnnotation = this.flowParsePrefixType();
|
||
return this.finishNode(node, "NullableTypeAnnotation");
|
||
} else {
|
||
return this.flowParsePostfixType();
|
||
}
|
||
}
|
||
|
||
flowParseAnonFunctionWithoutParens() {
|
||
const param = this.flowParsePrefixType();
|
||
|
||
if (!this.state.noAnonFunctionType && this.eat(_types.types.arrow)) {
|
||
const node = this.startNodeAt(param.start, param.loc.start);
|
||
node.params = [this.reinterpretTypeAsFunctionTypeParam(param)];
|
||
node.rest = null;
|
||
node.returnType = this.flowParseType();
|
||
node.typeParameters = null;
|
||
return this.finishNode(node, "FunctionTypeAnnotation");
|
||
}
|
||
|
||
return param;
|
||
}
|
||
|
||
flowParseIntersectionType() {
|
||
const node = this.startNode();
|
||
this.eat(_types.types.bitwiseAND);
|
||
const type = this.flowParseAnonFunctionWithoutParens();
|
||
node.types = [type];
|
||
|
||
while (this.eat(_types.types.bitwiseAND)) {
|
||
node.types.push(this.flowParseAnonFunctionWithoutParens());
|
||
}
|
||
|
||
return node.types.length === 1 ? type : this.finishNode(node, "IntersectionTypeAnnotation");
|
||
}
|
||
|
||
flowParseUnionType() {
|
||
const node = this.startNode();
|
||
this.eat(_types.types.bitwiseOR);
|
||
const type = this.flowParseIntersectionType();
|
||
node.types = [type];
|
||
|
||
while (this.eat(_types.types.bitwiseOR)) {
|
||
node.types.push(this.flowParseIntersectionType());
|
||
}
|
||
|
||
return node.types.length === 1 ? type : this.finishNode(node, "UnionTypeAnnotation");
|
||
}
|
||
|
||
flowParseType() {
|
||
const oldInType = this.state.inType;
|
||
this.state.inType = true;
|
||
const type = this.flowParseUnionType();
|
||
this.state.inType = oldInType;
|
||
this.state.exprAllowed = this.state.exprAllowed || this.state.noAnonFunctionType;
|
||
return type;
|
||
}
|
||
|
||
flowParseTypeOrImplicitInstantiation() {
|
||
if (this.state.type === _types.types.name && this.state.value === "_") {
|
||
const startPos = this.state.start;
|
||
const startLoc = this.state.startLoc;
|
||
const node = this.parseIdentifier();
|
||
return this.flowParseGenericType(startPos, startLoc, node);
|
||
} else {
|
||
return this.flowParseType();
|
||
}
|
||
}
|
||
|
||
flowParseTypeAnnotation() {
|
||
const node = this.startNode();
|
||
node.typeAnnotation = this.flowParseTypeInitialiser();
|
||
return this.finishNode(node, "TypeAnnotation");
|
||
}
|
||
|
||
flowParseTypeAnnotatableIdentifier(allowPrimitiveOverride) {
|
||
const ident = allowPrimitiveOverride ? this.parseIdentifier() : this.flowParseRestrictedIdentifier();
|
||
|
||
if (this.match(_types.types.colon)) {
|
||
ident.typeAnnotation = this.flowParseTypeAnnotation();
|
||
this.resetEndLocation(ident);
|
||
}
|
||
|
||
return ident;
|
||
}
|
||
|
||
typeCastToParameter(node) {
|
||
node.expression.typeAnnotation = node.typeAnnotation;
|
||
this.resetEndLocation(node.expression, node.typeAnnotation.end, node.typeAnnotation.loc.end);
|
||
return node.expression;
|
||
}
|
||
|
||
flowParseVariance() {
|
||
let variance = null;
|
||
|
||
if (this.match(_types.types.plusMin)) {
|
||
variance = this.startNode();
|
||
|
||
if (this.state.value === "+") {
|
||
variance.kind = "plus";
|
||
} else {
|
||
variance.kind = "minus";
|
||
}
|
||
|
||
this.next();
|
||
this.finishNode(variance, "Variance");
|
||
}
|
||
|
||
return variance;
|
||
}
|
||
|
||
parseFunctionBody(node, allowExpressionBody, isMethod = false) {
|
||
if (allowExpressionBody) {
|
||
return this.forwardNoArrowParamsConversionAt(node, () => super.parseFunctionBody(node, true, isMethod));
|
||
}
|
||
|
||
return super.parseFunctionBody(node, false, isMethod);
|
||
}
|
||
|
||
parseFunctionBodyAndFinish(node, type, isMethod = false) {
|
||
if (this.match(_types.types.colon)) {
|
||
const typeNode = this.startNode();
|
||
[typeNode.typeAnnotation, node.predicate] = this.flowParseTypeAndPredicateInitialiser();
|
||
node.returnType = typeNode.typeAnnotation ? this.finishNode(typeNode, "TypeAnnotation") : null;
|
||
}
|
||
|
||
super.parseFunctionBodyAndFinish(node, type, isMethod);
|
||
}
|
||
|
||
parseStatement(context, topLevel) {
|
||
if (this.state.strict && this.match(_types.types.name) && this.state.value === "interface") {
|
||
const node = this.startNode();
|
||
this.next();
|
||
return this.flowParseInterface(node);
|
||
} else if (this.shouldParseEnums() && this.isContextual("enum")) {
|
||
const node = this.startNode();
|
||
this.next();
|
||
return this.flowParseEnumDeclaration(node);
|
||
} else {
|
||
const stmt = super.parseStatement(context, topLevel);
|
||
|
||
if (this.flowPragma === undefined && !this.isValidDirective(stmt)) {
|
||
this.flowPragma = null;
|
||
}
|
||
|
||
return stmt;
|
||
}
|
||
}
|
||
|
||
parseExpressionStatement(node, expr) {
|
||
if (expr.type === "Identifier") {
|
||
if (expr.name === "declare") {
|
||
if (this.match(_types.types._class) || this.match(_types.types.name) || this.match(_types.types._function) || this.match(_types.types._var) || this.match(_types.types._export)) {
|
||
return this.flowParseDeclare(node);
|
||
}
|
||
} else if (this.match(_types.types.name)) {
|
||
if (expr.name === "interface") {
|
||
return this.flowParseInterface(node);
|
||
} else if (expr.name === "type") {
|
||
return this.flowParseTypeAlias(node);
|
||
} else if (expr.name === "opaque") {
|
||
return this.flowParseOpaqueType(node, false);
|
||
}
|
||
}
|
||
}
|
||
|
||
return super.parseExpressionStatement(node, expr);
|
||
}
|
||
|
||
shouldParseExportDeclaration() {
|
||
return this.isContextual("type") || this.isContextual("interface") || this.isContextual("opaque") || this.shouldParseEnums() && this.isContextual("enum") || super.shouldParseExportDeclaration();
|
||
}
|
||
|
||
isExportDefaultSpecifier() {
|
||
if (this.match(_types.types.name) && (this.state.value === "type" || this.state.value === "interface" || this.state.value === "opaque" || this.shouldParseEnums() && this.state.value === "enum")) {
|
||
return false;
|
||
}
|
||
|
||
return super.isExportDefaultSpecifier();
|
||
}
|
||
|
||
parseExportDefaultExpression() {
|
||
if (this.shouldParseEnums() && this.isContextual("enum")) {
|
||
const node = this.startNode();
|
||
this.next();
|
||
return this.flowParseEnumDeclaration(node);
|
||
}
|
||
|
||
return super.parseExportDefaultExpression();
|
||
}
|
||
|
||
parseConditional(expr, noIn, startPos, startLoc, refNeedsArrowPos) {
|
||
if (!this.match(_types.types.question)) return expr;
|
||
|
||
if (refNeedsArrowPos) {
|
||
const result = this.tryParse(() => super.parseConditional(expr, noIn, startPos, startLoc));
|
||
|
||
if (!result.node) {
|
||
refNeedsArrowPos.start = result.error.pos || this.state.start;
|
||
return expr;
|
||
}
|
||
|
||
if (result.error) this.state = result.failState;
|
||
return result.node;
|
||
}
|
||
|
||
this.expect(_types.types.question);
|
||
const state = this.state.clone();
|
||
const originalNoArrowAt = this.state.noArrowAt;
|
||
const node = this.startNodeAt(startPos, startLoc);
|
||
let {
|
||
consequent,
|
||
failed
|
||
} = this.tryParseConditionalConsequent();
|
||
let [valid, invalid] = this.getArrowLikeExpressions(consequent);
|
||
|
||
if (failed || invalid.length > 0) {
|
||
const noArrowAt = [...originalNoArrowAt];
|
||
|
||
if (invalid.length > 0) {
|
||
this.state = state;
|
||
this.state.noArrowAt = noArrowAt;
|
||
|
||
for (let i = 0; i < invalid.length; i++) {
|
||
noArrowAt.push(invalid[i].start);
|
||
}
|
||
|
||
({
|
||
consequent,
|
||
failed
|
||
} = this.tryParseConditionalConsequent());
|
||
[valid, invalid] = this.getArrowLikeExpressions(consequent);
|
||
}
|
||
|
||
if (failed && valid.length > 1) {
|
||
this.raise(state.start, "Ambiguous expression: wrap the arrow functions in parentheses to disambiguate.");
|
||
}
|
||
|
||
if (failed && valid.length === 1) {
|
||
this.state = state;
|
||
this.state.noArrowAt = noArrowAt.concat(valid[0].start);
|
||
({
|
||
consequent,
|
||
failed
|
||
} = this.tryParseConditionalConsequent());
|
||
}
|
||
}
|
||
|
||
this.getArrowLikeExpressions(consequent, true);
|
||
this.state.noArrowAt = originalNoArrowAt;
|
||
this.expect(_types.types.colon);
|
||
node.test = expr;
|
||
node.consequent = consequent;
|
||
node.alternate = this.forwardNoArrowParamsConversionAt(node, () => this.parseMaybeAssign(noIn, undefined, undefined, undefined));
|
||
return this.finishNode(node, "ConditionalExpression");
|
||
}
|
||
|
||
tryParseConditionalConsequent() {
|
||
this.state.noArrowParamsConversionAt.push(this.state.start);
|
||
const consequent = this.parseMaybeAssign();
|
||
const failed = !this.match(_types.types.colon);
|
||
this.state.noArrowParamsConversionAt.pop();
|
||
return {
|
||
consequent,
|
||
failed
|
||
};
|
||
}
|
||
|
||
getArrowLikeExpressions(node, disallowInvalid) {
|
||
const stack = [node];
|
||
const arrows = [];
|
||
|
||
while (stack.length !== 0) {
|
||
const node = stack.pop();
|
||
|
||
if (node.type === "ArrowFunctionExpression") {
|
||
if (node.typeParameters || !node.returnType) {
|
||
this.finishArrowValidation(node);
|
||
} else {
|
||
arrows.push(node);
|
||
}
|
||
|
||
stack.push(node.body);
|
||
} else if (node.type === "ConditionalExpression") {
|
||
stack.push(node.consequent);
|
||
stack.push(node.alternate);
|
||
}
|
||
}
|
||
|
||
if (disallowInvalid) {
|
||
arrows.forEach(node => this.finishArrowValidation(node));
|
||
return [arrows, []];
|
||
}
|
||
|
||
return partition(arrows, node => node.params.every(param => this.isAssignable(param, true)));
|
||
}
|
||
|
||
finishArrowValidation(node) {
|
||
var _node$extra;
|
||
|
||
this.toAssignableList(node.params, true, "arrow function parameters", (_node$extra = node.extra) == null ? void 0 : _node$extra.trailingComma);
|
||
this.scope.enter((0, _scopeflags.functionFlags)(false, false) | _scopeflags.SCOPE_ARROW);
|
||
super.checkParams(node, false, true);
|
||
this.scope.exit();
|
||
}
|
||
|
||
forwardNoArrowParamsConversionAt(node, parse) {
|
||
let result;
|
||
|
||
if (this.state.noArrowParamsConversionAt.indexOf(node.start) !== -1) {
|
||
this.state.noArrowParamsConversionAt.push(this.state.start);
|
||
result = parse();
|
||
this.state.noArrowParamsConversionAt.pop();
|
||
} else {
|
||
result = parse();
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
parseParenItem(node, startPos, startLoc) {
|
||
node = super.parseParenItem(node, startPos, startLoc);
|
||
|
||
if (this.eat(_types.types.question)) {
|
||
node.optional = true;
|
||
this.resetEndLocation(node);
|
||
}
|
||
|
||
if (this.match(_types.types.colon)) {
|
||
const typeCastNode = this.startNodeAt(startPos, startLoc);
|
||
typeCastNode.expression = node;
|
||
typeCastNode.typeAnnotation = this.flowParseTypeAnnotation();
|
||
return this.finishNode(typeCastNode, "TypeCastExpression");
|
||
}
|
||
|
||
return node;
|
||
}
|
||
|
||
assertModuleNodeAllowed(node) {
|
||
if (node.type === "ImportDeclaration" && (node.importKind === "type" || node.importKind === "typeof") || node.type === "ExportNamedDeclaration" && node.exportKind === "type" || node.type === "ExportAllDeclaration" && node.exportKind === "type") {
|
||
return;
|
||
}
|
||
|
||
super.assertModuleNodeAllowed(node);
|
||
}
|
||
|
||
parseExport(node) {
|
||
const decl = super.parseExport(node);
|
||
|
||
if (decl.type === "ExportNamedDeclaration" || decl.type === "ExportAllDeclaration") {
|
||
decl.exportKind = decl.exportKind || "value";
|
||
}
|
||
|
||
return decl;
|
||
}
|
||
|
||
parseExportDeclaration(node) {
|
||
if (this.isContextual("type")) {
|
||
node.exportKind = "type";
|
||
const declarationNode = this.startNode();
|
||
this.next();
|
||
|
||
if (this.match(_types.types.braceL)) {
|
||
node.specifiers = this.parseExportSpecifiers();
|
||
this.parseExportFrom(node);
|
||
return null;
|
||
} else {
|
||
return this.flowParseTypeAlias(declarationNode);
|
||
}
|
||
} else if (this.isContextual("opaque")) {
|
||
node.exportKind = "type";
|
||
const declarationNode = this.startNode();
|
||
this.next();
|
||
return this.flowParseOpaqueType(declarationNode, false);
|
||
} else if (this.isContextual("interface")) {
|
||
node.exportKind = "type";
|
||
const declarationNode = this.startNode();
|
||
this.next();
|
||
return this.flowParseInterface(declarationNode);
|
||
} else if (this.shouldParseEnums() && this.isContextual("enum")) {
|
||
node.exportKind = "value";
|
||
const declarationNode = this.startNode();
|
||
this.next();
|
||
return this.flowParseEnumDeclaration(declarationNode);
|
||
} else {
|
||
return super.parseExportDeclaration(node);
|
||
}
|
||
}
|
||
|
||
eatExportStar(node) {
|
||
if (super.eatExportStar(...arguments)) return true;
|
||
|
||
if (this.isContextual("type") && this.lookahead().type === _types.types.star) {
|
||
node.exportKind = "type";
|
||
this.next();
|
||
this.next();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
maybeParseExportNamespaceSpecifier(node) {
|
||
const pos = this.state.start;
|
||
const hasNamespace = super.maybeParseExportNamespaceSpecifier(node);
|
||
|
||
if (hasNamespace && node.exportKind === "type") {
|
||
this.unexpected(pos);
|
||
}
|
||
|
||
return hasNamespace;
|
||
}
|
||
|
||
parseClassId(node, isStatement, optionalId) {
|
||
super.parseClassId(node, isStatement, optionalId);
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
}
|
||
}
|
||
|
||
getTokenFromCode(code) {
|
||
const next = this.input.charCodeAt(this.state.pos + 1);
|
||
|
||
if (code === 123 && next === 124) {
|
||
return this.finishOp(_types.types.braceBarL, 2);
|
||
} else if (this.state.inType && (code === 62 || code === 60)) {
|
||
return this.finishOp(_types.types.relational, 1);
|
||
} else if ((0, _identifier.isIteratorStart)(code, next)) {
|
||
this.state.isIterator = true;
|
||
return super.readWord();
|
||
} else {
|
||
return super.getTokenFromCode(code);
|
||
}
|
||
}
|
||
|
||
isAssignable(node, isBinding) {
|
||
switch (node.type) {
|
||
case "Identifier":
|
||
case "ObjectPattern":
|
||
case "ArrayPattern":
|
||
case "AssignmentPattern":
|
||
return true;
|
||
|
||
case "ObjectExpression":
|
||
{
|
||
const last = node.properties.length - 1;
|
||
return node.properties.every((prop, i) => {
|
||
return prop.type !== "ObjectMethod" && (i === last || prop.type === "SpreadElement") && this.isAssignable(prop);
|
||
});
|
||
}
|
||
|
||
case "ObjectProperty":
|
||
return this.isAssignable(node.value);
|
||
|
||
case "SpreadElement":
|
||
return this.isAssignable(node.argument);
|
||
|
||
case "ArrayExpression":
|
||
return node.elements.every(element => this.isAssignable(element));
|
||
|
||
case "AssignmentExpression":
|
||
return node.operator === "=";
|
||
|
||
case "ParenthesizedExpression":
|
||
case "TypeCastExpression":
|
||
return this.isAssignable(node.expression);
|
||
|
||
case "MemberExpression":
|
||
case "OptionalMemberExpression":
|
||
return !isBinding;
|
||
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
toAssignable(node, isBinding, contextDescription) {
|
||
if (node.type === "TypeCastExpression") {
|
||
return super.toAssignable(this.typeCastToParameter(node), isBinding, contextDescription);
|
||
} else {
|
||
return super.toAssignable(node, isBinding, contextDescription);
|
||
}
|
||
}
|
||
|
||
toAssignableList(exprList, isBinding, contextDescription, trailingCommaPos) {
|
||
for (let i = 0; i < exprList.length; i++) {
|
||
const expr = exprList[i];
|
||
|
||
if (expr && expr.type === "TypeCastExpression") {
|
||
exprList[i] = this.typeCastToParameter(expr);
|
||
}
|
||
}
|
||
|
||
return super.toAssignableList(exprList, isBinding, contextDescription, trailingCommaPos);
|
||
}
|
||
|
||
toReferencedList(exprList, isParenthesizedExpr) {
|
||
for (let i = 0; i < exprList.length; i++) {
|
||
const expr = exprList[i];
|
||
|
||
if (expr && expr.type === "TypeCastExpression" && (!expr.extra || !expr.extra.parenthesized) && (exprList.length > 1 || !isParenthesizedExpr)) {
|
||
this.raise(expr.typeAnnotation.start, "The type cast expression is expected to be wrapped with parenthesis");
|
||
}
|
||
}
|
||
|
||
return exprList;
|
||
}
|
||
|
||
checkLVal(expr, bindingType = _scopeflags.BIND_NONE, checkClashes, contextDescription) {
|
||
if (expr.type !== "TypeCastExpression") {
|
||
return super.checkLVal(expr, bindingType, checkClashes, contextDescription);
|
||
}
|
||
}
|
||
|
||
parseClassProperty(node) {
|
||
if (this.match(_types.types.colon)) {
|
||
node.typeAnnotation = this.flowParseTypeAnnotation();
|
||
}
|
||
|
||
return super.parseClassProperty(node);
|
||
}
|
||
|
||
parseClassPrivateProperty(node) {
|
||
if (this.match(_types.types.colon)) {
|
||
node.typeAnnotation = this.flowParseTypeAnnotation();
|
||
}
|
||
|
||
return super.parseClassPrivateProperty(node);
|
||
}
|
||
|
||
isClassMethod() {
|
||
return this.isRelational("<") || super.isClassMethod();
|
||
}
|
||
|
||
isClassProperty() {
|
||
return this.match(_types.types.colon) || super.isClassProperty();
|
||
}
|
||
|
||
isNonstaticConstructor(method) {
|
||
return !this.match(_types.types.colon) && super.isNonstaticConstructor(method);
|
||
}
|
||
|
||
pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper) {
|
||
if (method.variance) {
|
||
this.unexpected(method.variance.start);
|
||
}
|
||
|
||
delete method.variance;
|
||
|
||
if (this.isRelational("<")) {
|
||
method.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
}
|
||
|
||
super.pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper);
|
||
}
|
||
|
||
pushClassPrivateMethod(classBody, method, isGenerator, isAsync) {
|
||
if (method.variance) {
|
||
this.unexpected(method.variance.start);
|
||
}
|
||
|
||
delete method.variance;
|
||
|
||
if (this.isRelational("<")) {
|
||
method.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
}
|
||
|
||
super.pushClassPrivateMethod(classBody, method, isGenerator, isAsync);
|
||
}
|
||
|
||
parseClassSuper(node) {
|
||
super.parseClassSuper(node);
|
||
|
||
if (node.superClass && this.isRelational("<")) {
|
||
node.superTypeParameters = this.flowParseTypeParameterInstantiation();
|
||
}
|
||
|
||
if (this.isContextual("implements")) {
|
||
this.next();
|
||
const implemented = node.implements = [];
|
||
|
||
do {
|
||
const node = this.startNode();
|
||
node.id = this.flowParseRestrictedIdentifier(true);
|
||
|
||
if (this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterInstantiation();
|
||
} else {
|
||
node.typeParameters = null;
|
||
}
|
||
|
||
implemented.push(this.finishNode(node, "ClassImplements"));
|
||
} while (this.eat(_types.types.comma));
|
||
}
|
||
}
|
||
|
||
parsePropertyName(node, isPrivateNameAllowed) {
|
||
const variance = this.flowParseVariance();
|
||
const key = super.parsePropertyName(node, isPrivateNameAllowed);
|
||
node.variance = variance;
|
||
return key;
|
||
}
|
||
|
||
parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos, containsEsc) {
|
||
if (prop.variance) {
|
||
this.unexpected(prop.variance.start);
|
||
}
|
||
|
||
delete prop.variance;
|
||
let typeParameters;
|
||
|
||
if (this.isRelational("<")) {
|
||
typeParameters = this.flowParseTypeParameterDeclaration();
|
||
if (!this.match(_types.types.parenL)) this.unexpected();
|
||
}
|
||
|
||
super.parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos, containsEsc);
|
||
|
||
if (typeParameters) {
|
||
(prop.value || prop).typeParameters = typeParameters;
|
||
}
|
||
}
|
||
|
||
parseAssignableListItemTypes(param) {
|
||
if (this.eat(_types.types.question)) {
|
||
if (param.type !== "Identifier") {
|
||
this.raise(param.start, "A binding pattern parameter cannot be optional in an implementation signature.");
|
||
}
|
||
|
||
param.optional = true;
|
||
}
|
||
|
||
if (this.match(_types.types.colon)) {
|
||
param.typeAnnotation = this.flowParseTypeAnnotation();
|
||
}
|
||
|
||
this.resetEndLocation(param);
|
||
return param;
|
||
}
|
||
|
||
parseMaybeDefault(startPos, startLoc, left) {
|
||
const node = super.parseMaybeDefault(startPos, startLoc, left);
|
||
|
||
if (node.type === "AssignmentPattern" && node.typeAnnotation && node.right.start < node.typeAnnotation.start) {
|
||
this.raise(node.typeAnnotation.start, "Type annotations must come before default assignments, " + "e.g. instead of `age = 25: number` use `age: number = 25`");
|
||
}
|
||
|
||
return node;
|
||
}
|
||
|
||
shouldParseDefaultImport(node) {
|
||
if (!hasTypeImportKind(node)) {
|
||
return super.shouldParseDefaultImport(node);
|
||
}
|
||
|
||
return isMaybeDefaultImport(this.state);
|
||
}
|
||
|
||
parseImportSpecifierLocal(node, specifier, type, contextDescription) {
|
||
specifier.local = hasTypeImportKind(node) ? this.flowParseRestrictedIdentifier(true, true) : this.parseIdentifier();
|
||
this.checkLVal(specifier.local, _scopeflags.BIND_LEXICAL, undefined, contextDescription);
|
||
node.specifiers.push(this.finishNode(specifier, type));
|
||
}
|
||
|
||
maybeParseDefaultImportSpecifier(node) {
|
||
node.importKind = "value";
|
||
let kind = null;
|
||
|
||
if (this.match(_types.types._typeof)) {
|
||
kind = "typeof";
|
||
} else if (this.isContextual("type")) {
|
||
kind = "type";
|
||
}
|
||
|
||
if (kind) {
|
||
const lh = this.lookahead();
|
||
|
||
if (kind === "type" && lh.type === _types.types.star) {
|
||
this.unexpected(lh.start);
|
||
}
|
||
|
||
if (isMaybeDefaultImport(lh) || lh.type === _types.types.braceL || lh.type === _types.types.star) {
|
||
this.next();
|
||
node.importKind = kind;
|
||
}
|
||
}
|
||
|
||
return super.maybeParseDefaultImportSpecifier(node);
|
||
}
|
||
|
||
parseImportSpecifier(node) {
|
||
const specifier = this.startNode();
|
||
const firstIdentLoc = this.state.start;
|
||
const firstIdent = this.parseIdentifier(true);
|
||
let specifierTypeKind = null;
|
||
|
||
if (firstIdent.name === "type") {
|
||
specifierTypeKind = "type";
|
||
} else if (firstIdent.name === "typeof") {
|
||
specifierTypeKind = "typeof";
|
||
}
|
||
|
||
let isBinding = false;
|
||
|
||
if (this.isContextual("as") && !this.isLookaheadContextual("as")) {
|
||
const as_ident = this.parseIdentifier(true);
|
||
|
||
if (specifierTypeKind !== null && !this.match(_types.types.name) && !this.state.type.keyword) {
|
||
specifier.imported = as_ident;
|
||
specifier.importKind = specifierTypeKind;
|
||
specifier.local = as_ident.__clone();
|
||
} else {
|
||
specifier.imported = firstIdent;
|
||
specifier.importKind = null;
|
||
specifier.local = this.parseIdentifier();
|
||
}
|
||
} else if (specifierTypeKind !== null && (this.match(_types.types.name) || this.state.type.keyword)) {
|
||
specifier.imported = this.parseIdentifier(true);
|
||
specifier.importKind = specifierTypeKind;
|
||
|
||
if (this.eatContextual("as")) {
|
||
specifier.local = this.parseIdentifier();
|
||
} else {
|
||
isBinding = true;
|
||
specifier.local = specifier.imported.__clone();
|
||
}
|
||
} else {
|
||
isBinding = true;
|
||
specifier.imported = firstIdent;
|
||
specifier.importKind = null;
|
||
specifier.local = specifier.imported.__clone();
|
||
}
|
||
|
||
const nodeIsTypeImport = hasTypeImportKind(node);
|
||
const specifierIsTypeImport = hasTypeImportKind(specifier);
|
||
|
||
if (nodeIsTypeImport && specifierIsTypeImport) {
|
||
this.raise(firstIdentLoc, "The `type` and `typeof` keywords on named imports can only be used on regular " + "`import` statements. It cannot be used with `import type` or `import typeof` statements");
|
||
}
|
||
|
||
if (nodeIsTypeImport || specifierIsTypeImport) {
|
||
this.checkReservedType(specifier.local.name, specifier.local.start, true);
|
||
}
|
||
|
||
if (isBinding && !nodeIsTypeImport && !specifierIsTypeImport) {
|
||
this.checkReservedWord(specifier.local.name, specifier.start, true, true);
|
||
}
|
||
|
||
this.checkLVal(specifier.local, _scopeflags.BIND_LEXICAL, undefined, "import specifier");
|
||
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
|
||
}
|
||
|
||
parseFunctionParams(node, allowModifiers) {
|
||
const kind = node.kind;
|
||
|
||
if (kind !== "get" && kind !== "set" && this.isRelational("<")) {
|
||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||
}
|
||
|
||
super.parseFunctionParams(node, allowModifiers);
|
||
}
|
||
|
||
parseVarId(decl, kind) {
|
||
super.parseVarId(decl, kind);
|
||
|
||
if (this.match(_types.types.colon)) {
|
||
decl.id.typeAnnotation = this.flowParseTypeAnnotation();
|
||
this.resetEndLocation(decl.id);
|
||
}
|
||
}
|
||
|
||
parseAsyncArrowFromCallExpression(node, call) {
|
||
if (this.match(_types.types.colon)) {
|
||
const oldNoAnonFunctionType = this.state.noAnonFunctionType;
|
||
this.state.noAnonFunctionType = true;
|
||
node.returnType = this.flowParseTypeAnnotation();
|
||
this.state.noAnonFunctionType = oldNoAnonFunctionType;
|
||
}
|
||
|
||
return super.parseAsyncArrowFromCallExpression(node, call);
|
||
}
|
||
|
||
shouldParseAsyncArrow() {
|
||
return this.match(_types.types.colon) || super.shouldParseAsyncArrow();
|
||
}
|
||
|
||
parseMaybeAssign(noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos) {
|
||
let state = null;
|
||
let jsx;
|
||
|
||
if (this.hasPlugin("jsx") && (this.match(_types.types.jsxTagStart) || this.isRelational("<"))) {
|
||
state = this.state.clone();
|
||
jsx = this.tryParse(() => super.parseMaybeAssign(noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos), state);
|
||
if (!jsx.error) return jsx.node;
|
||
const {
|
||
context
|
||
} = this.state;
|
||
|
||
if (context[context.length - 1] === _context.types.j_oTag) {
|
||
context.length -= 2;
|
||
} else if (context[context.length - 1] === _context.types.j_expr) {
|
||
context.length -= 1;
|
||
}
|
||
}
|
||
|
||
if (jsx && jsx.error || this.isRelational("<")) {
|
||
state = state || this.state.clone();
|
||
let typeParameters;
|
||
const arrow = this.tryParse(() => {
|
||
typeParameters = this.flowParseTypeParameterDeclaration();
|
||
const arrowExpression = this.forwardNoArrowParamsConversionAt(typeParameters, () => super.parseMaybeAssign(noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos));
|
||
arrowExpression.typeParameters = typeParameters;
|
||
this.resetStartLocationFromNode(arrowExpression, typeParameters);
|
||
return arrowExpression;
|
||
}, state);
|
||
const arrowExpression = arrow.node && arrow.node.type === "ArrowFunctionExpression" ? arrow.node : null;
|
||
if (!arrow.error && arrowExpression) return arrowExpression;
|
||
|
||
if (jsx && jsx.node) {
|
||
this.state = jsx.failState;
|
||
return jsx.node;
|
||
}
|
||
|
||
if (arrowExpression) {
|
||
this.state = arrow.failState;
|
||
return arrowExpression;
|
||
}
|
||
|
||
if (jsx && jsx.thrown) throw jsx.error;
|
||
if (arrow.thrown) throw arrow.error;
|
||
throw this.raise(typeParameters.start, "Expected an arrow function after this type parameter declaration");
|
||
}
|
||
|
||
return super.parseMaybeAssign(noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos);
|
||
}
|
||
|
||
parseArrow(node) {
|
||
if (this.match(_types.types.colon)) {
|
||
const result = this.tryParse(() => {
|
||
const oldNoAnonFunctionType = this.state.noAnonFunctionType;
|
||
this.state.noAnonFunctionType = true;
|
||
const typeNode = this.startNode();
|
||
[typeNode.typeAnnotation, node.predicate] = this.flowParseTypeAndPredicateInitialiser();
|
||
this.state.noAnonFunctionType = oldNoAnonFunctionType;
|
||
if (this.canInsertSemicolon()) this.unexpected();
|
||
if (!this.match(_types.types.arrow)) this.unexpected();
|
||
return typeNode;
|
||
});
|
||
if (result.thrown) return null;
|
||
if (result.error) this.state = result.failState;
|
||
node.returnType = result.node.typeAnnotation ? this.finishNode(result.node, "TypeAnnotation") : null;
|
||
}
|
||
|
||
return super.parseArrow(node);
|
||
}
|
||
|
||
shouldParseArrow() {
|
||
return this.match(_types.types.colon) || super.shouldParseArrow();
|
||
}
|
||
|
||
setArrowFunctionParameters(node, params) {
|
||
if (this.state.noArrowParamsConversionAt.indexOf(node.start) !== -1) {
|
||
node.params = params;
|
||
} else {
|
||
super.setArrowFunctionParameters(node, params);
|
||
}
|
||
}
|
||
|
||
checkParams(node, allowDuplicates, isArrowFunction) {
|
||
if (isArrowFunction && this.state.noArrowParamsConversionAt.indexOf(node.start) !== -1) {
|
||
return;
|
||
}
|
||
|
||
return super.checkParams(...arguments);
|
||
}
|
||
|
||
parseParenAndDistinguishExpression(canBeArrow) {
|
||
return super.parseParenAndDistinguishExpression(canBeArrow && this.state.noArrowAt.indexOf(this.state.start) === -1);
|
||
}
|
||
|
||
parseSubscripts(base, startPos, startLoc, noCalls) {
|
||
if (base.type === "Identifier" && base.name === "async" && this.state.noArrowAt.indexOf(startPos) !== -1) {
|
||
this.next();
|
||
const node = this.startNodeAt(startPos, startLoc);
|
||
node.callee = base;
|
||
node.arguments = this.parseCallExpressionArguments(_types.types.parenR, false);
|
||
base = this.finishNode(node, "CallExpression");
|
||
} else if (base.type === "Identifier" && base.name === "async" && this.isRelational("<")) {
|
||
const state = this.state.clone();
|
||
const arrow = this.tryParse(abort => this.parseAsyncArrowWithTypeParameters(startPos, startLoc) || abort(), state);
|
||
if (!arrow.error && !arrow.aborted) return arrow.node;
|
||
const result = this.tryParse(() => super.parseSubscripts(base, startPos, startLoc, noCalls), state);
|
||
if (result.node && !result.error) return result.node;
|
||
|
||
if (arrow.node) {
|
||
this.state = arrow.failState;
|
||
return arrow.node;
|
||
}
|
||
|
||
if (result.node) {
|
||
this.state = result.failState;
|
||
return result.node;
|
||
}
|
||
|
||
throw arrow.error || result.error;
|
||
}
|
||
|
||
return super.parseSubscripts(base, startPos, startLoc, noCalls);
|
||
}
|
||
|
||
parseSubscript(base, startPos, startLoc, noCalls, subscriptState) {
|
||
if (this.match(_types.types.questionDot) && this.isLookaheadRelational("<")) {
|
||
subscriptState.optionalChainMember = true;
|
||
|
||
if (noCalls) {
|
||
subscriptState.stop = true;
|
||
return base;
|
||
}
|
||
|
||
this.next();
|
||
const node = this.startNodeAt(startPos, startLoc);
|
||
node.callee = base;
|
||
node.typeArguments = this.flowParseTypeParameterInstantiation();
|
||
this.expect(_types.types.parenL);
|
||
node.arguments = this.parseCallExpressionArguments(_types.types.parenR, false);
|
||
node.optional = true;
|
||
return this.finishCallExpression(node, true);
|
||
} else if (!noCalls && this.shouldParseTypes() && this.isRelational("<")) {
|
||
const node = this.startNodeAt(startPos, startLoc);
|
||
node.callee = base;
|
||
const result = this.tryParse(() => {
|
||
node.typeArguments = this.flowParseTypeParameterInstantiationCallOrNew();
|
||
this.expect(_types.types.parenL);
|
||
node.arguments = this.parseCallExpressionArguments(_types.types.parenR, false);
|
||
if (subscriptState.optionalChainMember) node.optional = false;
|
||
return this.finishCallExpression(node, subscriptState.optionalChainMember);
|
||
});
|
||
|
||
if (result.node) {
|
||
if (result.error) this.state = result.failState;
|
||
return result.node;
|
||
}
|
||
}
|
||
|
||
return super.parseSubscript(base, startPos, startLoc, noCalls, subscriptState);
|
||
}
|
||
|
||
parseNewArguments(node) {
|
||
let targs = null;
|
||
|
||
if (this.shouldParseTypes() && this.isRelational("<")) {
|
||
targs = this.tryParse(() => this.flowParseTypeParameterInstantiationCallOrNew()).node;
|
||
}
|
||
|
||
node.typeArguments = targs;
|
||
super.parseNewArguments(node);
|
||
}
|
||
|
||
parseAsyncArrowWithTypeParameters(startPos, startLoc) {
|
||
const node = this.startNodeAt(startPos, startLoc);
|
||
this.parseFunctionParams(node);
|
||
if (!this.parseArrow(node)) return;
|
||
return this.parseArrowExpression(node, undefined, true);
|
||
}
|
||
|
||
readToken_mult_modulo(code) {
|
||
const next = this.input.charCodeAt(this.state.pos + 1);
|
||
|
||
if (code === 42 && next === 47 && this.state.hasFlowComment) {
|
||
this.state.hasFlowComment = false;
|
||
this.state.pos += 2;
|
||
this.nextToken();
|
||
return;
|
||
}
|
||
|
||
super.readToken_mult_modulo(code);
|
||
}
|
||
|
||
readToken_pipe_amp(code) {
|
||
const next = this.input.charCodeAt(this.state.pos + 1);
|
||
|
||
if (code === 124 && next === 125) {
|
||
this.finishOp(_types.types.braceBarR, 2);
|
||
return;
|
||
}
|
||
|
||
super.readToken_pipe_amp(code);
|
||
}
|
||
|
||
parseTopLevel(file, program) {
|
||
const fileNode = super.parseTopLevel(file, program);
|
||
|
||
if (this.state.hasFlowComment) {
|
||
this.raise(this.state.pos, "Unterminated flow-comment");
|
||
}
|
||
|
||
return fileNode;
|
||
}
|
||
|
||
skipBlockComment() {
|
||
if (this.hasPlugin("flowComments") && this.skipFlowComment()) {
|
||
if (this.state.hasFlowComment) {
|
||
this.unexpected(null, "Cannot have a flow comment inside another flow comment");
|
||
}
|
||
|
||
this.hasFlowCommentCompletion();
|
||
this.state.pos += this.skipFlowComment();
|
||
this.state.hasFlowComment = true;
|
||
return;
|
||
}
|
||
|
||
if (this.state.hasFlowComment) {
|
||
const end = this.input.indexOf("*-/", this.state.pos += 2);
|
||
|
||
if (end === -1) {
|
||
throw this.raise(this.state.pos - 2, "Unterminated comment");
|
||
}
|
||
|
||
this.state.pos = end + 3;
|
||
return;
|
||
}
|
||
|
||
super.skipBlockComment();
|
||
}
|
||
|
||
skipFlowComment() {
|
||
const {
|
||
pos
|
||
} = this.state;
|
||
let shiftToFirstNonWhiteSpace = 2;
|
||
|
||
while ([32, 9].includes(this.input.charCodeAt(pos + shiftToFirstNonWhiteSpace))) {
|
||
shiftToFirstNonWhiteSpace++;
|
||
}
|
||
|
||
const ch2 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos);
|
||
const ch3 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos + 1);
|
||
|
||
if (ch2 === 58 && ch3 === 58) {
|
||
return shiftToFirstNonWhiteSpace + 2;
|
||
}
|
||
|
||
if (this.input.slice(shiftToFirstNonWhiteSpace + pos, shiftToFirstNonWhiteSpace + pos + 12) === "flow-include") {
|
||
return shiftToFirstNonWhiteSpace + 12;
|
||
}
|
||
|
||
if (ch2 === 58 && ch3 !== 58) {
|
||
return shiftToFirstNonWhiteSpace;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
hasFlowCommentCompletion() {
|
||
const end = this.input.indexOf("*/", this.state.pos);
|
||
|
||
if (end === -1) {
|
||
throw this.raise(this.state.pos, "Unterminated comment");
|
||
}
|
||
}
|
||
|
||
flowEnumErrorBooleanMemberNotInitialized(pos, {
|
||
enumName,
|
||
memberName
|
||
}) {
|
||
this.raise(pos, `Boolean enum members need to be initialized. Use either \`${memberName} = true,\` ` + `or \`${memberName} = false,\` in enum \`${enumName}\`.`);
|
||
}
|
||
|
||
flowEnumErrorInvalidMemberName(pos, {
|
||
enumName,
|
||
memberName
|
||
}) {
|
||
const suggestion = memberName[0].toUpperCase() + memberName.slice(1);
|
||
this.raise(pos, `Enum member names cannot start with lowercase 'a' through 'z'. Instead of using ` + `\`${memberName}\`, consider using \`${suggestion}\`, in enum \`${enumName}\`.`);
|
||
}
|
||
|
||
flowEnumErrorDuplicateMemberName(pos, {
|
||
enumName,
|
||
memberName
|
||
}) {
|
||
this.raise(pos, `Enum member names need to be unique, but the name \`${memberName}\` has already been used ` + `before in enum \`${enumName}\`.`);
|
||
}
|
||
|
||
flowEnumErrorInconsistentMemberValues(pos, {
|
||
enumName
|
||
}) {
|
||
this.raise(pos, `Enum \`${enumName}\` has inconsistent member initializers. Either use no initializers, or ` + `consistently use literals (either booleans, numbers, or strings) for all member initializers.`);
|
||
}
|
||
|
||
flowEnumErrorInvalidExplicitType(pos, {
|
||
enumName,
|
||
suppliedType
|
||
}) {
|
||
const suggestion = `Use one of \`boolean\`, \`number\`, \`string\`, or \`symbol\` in ` + `enum \`${enumName}\`.`;
|
||
const message = suppliedType === null ? `Supplied enum type is not valid. ${suggestion}` : `Enum type \`${suppliedType}\` is not valid. ${suggestion}`;
|
||
return this.raise(pos, message);
|
||
}
|
||
|
||
flowEnumErrorInvalidMemberInitializer(pos, {
|
||
enumName,
|
||
explicitType,
|
||
memberName
|
||
}) {
|
||
let message = null;
|
||
|
||
switch (explicitType) {
|
||
case "boolean":
|
||
case "number":
|
||
case "string":
|
||
message = `Enum \`${enumName}\` has type \`${explicitType}\`, so the initializer of ` + `\`${memberName}\` needs to be a ${explicitType} literal.`;
|
||
break;
|
||
|
||
case "symbol":
|
||
message = `Symbol enum members cannot be initialized. Use \`${memberName},\` in ` + `enum \`${enumName}\`.`;
|
||
break;
|
||
|
||
default:
|
||
message = `The enum member initializer for \`${memberName}\` needs to be a literal (either ` + `a boolean, number, or string) in enum \`${enumName}\`.`;
|
||
}
|
||
|
||
return this.raise(pos, message);
|
||
}
|
||
|
||
flowEnumErrorNumberMemberNotInitialized(pos, {
|
||
enumName,
|
||
memberName
|
||
}) {
|
||
this.raise(pos, `Number enum members need to be initialized, e.g. \`${memberName} = 1\` in enum \`${enumName}\`.`);
|
||
}
|
||
|
||
flowEnumErrorStringMemberInconsistentlyInitailized(pos, {
|
||
enumName
|
||
}) {
|
||
this.raise(pos, `String enum members need to consistently either all use initializers, or use no initializers, ` + `in enum \`${enumName}\`.`);
|
||
}
|
||
|
||
flowEnumMemberInit() {
|
||
const startPos = this.state.start;
|
||
|
||
const endOfInit = () => this.match(_types.types.comma) || this.match(_types.types.braceR);
|
||
|
||
switch (this.state.type) {
|
||
case _types.types.num:
|
||
{
|
||
const literal = this.parseLiteral(this.state.value, "NumericLiteral");
|
||
|
||
if (endOfInit()) {
|
||
return {
|
||
type: "number",
|
||
pos: literal.start,
|
||
value: literal
|
||
};
|
||
}
|
||
|
||
return {
|
||
type: "invalid",
|
||
pos: startPos
|
||
};
|
||
}
|
||
|
||
case _types.types.string:
|
||
{
|
||
const literal = this.parseLiteral(this.state.value, "StringLiteral");
|
||
|
||
if (endOfInit()) {
|
||
return {
|
||
type: "string",
|
||
pos: literal.start,
|
||
value: literal
|
||
};
|
||
}
|
||
|
||
return {
|
||
type: "invalid",
|
||
pos: startPos
|
||
};
|
||
}
|
||
|
||
case _types.types._true:
|
||
case _types.types._false:
|
||
{
|
||
const literal = this.parseBooleanLiteral();
|
||
|
||
if (endOfInit()) {
|
||
return {
|
||
type: "boolean",
|
||
pos: literal.start,
|
||
value: literal
|
||
};
|
||
}
|
||
|
||
return {
|
||
type: "invalid",
|
||
pos: startPos
|
||
};
|
||
}
|
||
|
||
default:
|
||
return {
|
||
type: "invalid",
|
||
pos: startPos
|
||
};
|
||
}
|
||
}
|
||
|
||
flowEnumMemberRaw() {
|
||
const pos = this.state.start;
|
||
const id = this.parseIdentifier(true);
|
||
const init = this.eat(_types.types.eq) ? this.flowEnumMemberInit() : {
|
||
type: "none",
|
||
pos
|
||
};
|
||
return {
|
||
id,
|
||
init
|
||
};
|
||
}
|
||
|
||
flowEnumCheckExplicitTypeMismatch(pos, context, expectedType) {
|
||
const {
|
||
explicitType
|
||
} = context;
|
||
|
||
if (explicitType === null) {
|
||
return;
|
||
}
|
||
|
||
if (explicitType !== expectedType) {
|
||
this.flowEnumErrorInvalidMemberInitializer(pos, context);
|
||
}
|
||
}
|
||
|
||
flowEnumMembers({
|
||
enumName,
|
||
explicitType
|
||
}) {
|
||
const seenNames = new Set();
|
||
const members = {
|
||
booleanMembers: [],
|
||
numberMembers: [],
|
||
stringMembers: [],
|
||
defaultedMembers: []
|
||
};
|
||
|
||
while (!this.match(_types.types.braceR)) {
|
||
const memberNode = this.startNode();
|
||
const {
|
||
id,
|
||
init
|
||
} = this.flowEnumMemberRaw();
|
||
const memberName = id.name;
|
||
|
||
if (memberName === "") {
|
||
continue;
|
||
}
|
||
|
||
if (/^[a-z]/.test(memberName)) {
|
||
this.flowEnumErrorInvalidMemberName(id.start, {
|
||
enumName,
|
||
memberName
|
||
});
|
||
}
|
||
|
||
if (seenNames.has(memberName)) {
|
||
this.flowEnumErrorDuplicateMemberName(id.start, {
|
||
enumName,
|
||
memberName
|
||
});
|
||
}
|
||
|
||
seenNames.add(memberName);
|
||
const context = {
|
||
enumName,
|
||
explicitType,
|
||
memberName
|
||
};
|
||
memberNode.id = id;
|
||
|
||
switch (init.type) {
|
||
case "boolean":
|
||
{
|
||
this.flowEnumCheckExplicitTypeMismatch(init.pos, context, "boolean");
|
||
memberNode.init = init.value;
|
||
members.booleanMembers.push(this.finishNode(memberNode, "EnumBooleanMember"));
|
||
break;
|
||
}
|
||
|
||
case "number":
|
||
{
|
||
this.flowEnumCheckExplicitTypeMismatch(init.pos, context, "number");
|
||
memberNode.init = init.value;
|
||
members.numberMembers.push(this.finishNode(memberNode, "EnumNumberMember"));
|
||
break;
|
||
}
|
||
|
||
case "string":
|
||
{
|
||
this.flowEnumCheckExplicitTypeMismatch(init.pos, context, "string");
|
||
memberNode.init = init.value;
|
||
members.stringMembers.push(this.finishNode(memberNode, "EnumStringMember"));
|
||
break;
|
||
}
|
||
|
||
case "invalid":
|
||
{
|
||
throw this.flowEnumErrorInvalidMemberInitializer(init.pos, context);
|
||
}
|
||
|
||
case "none":
|
||
{
|
||
switch (explicitType) {
|
||
case "boolean":
|
||
this.flowEnumErrorBooleanMemberNotInitialized(init.pos, context);
|
||
break;
|
||
|
||
case "number":
|
||
this.flowEnumErrorNumberMemberNotInitialized(init.pos, context);
|
||
break;
|
||
|
||
default:
|
||
members.defaultedMembers.push(this.finishNode(memberNode, "EnumDefaultedMember"));
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!this.match(_types.types.braceR)) {
|
||
this.expect(_types.types.comma);
|
||
}
|
||
}
|
||
|
||
return members;
|
||
}
|
||
|
||
flowEnumStringMembers(initializedMembers, defaultedMembers, {
|
||
enumName
|
||
}) {
|
||
if (initializedMembers.length === 0) {
|
||
return defaultedMembers;
|
||
} else if (defaultedMembers.length === 0) {
|
||
return initializedMembers;
|
||
} else if (defaultedMembers.length > initializedMembers.length) {
|
||
for (let _i = 0; _i < initializedMembers.length; _i++) {
|
||
const member = initializedMembers[_i];
|
||
this.flowEnumErrorStringMemberInconsistentlyInitailized(member.start, {
|
||
enumName
|
||
});
|
||
}
|
||
|
||
return defaultedMembers;
|
||
} else {
|
||
for (let _i2 = 0; _i2 < defaultedMembers.length; _i2++) {
|
||
const member = defaultedMembers[_i2];
|
||
this.flowEnumErrorStringMemberInconsistentlyInitailized(member.start, {
|
||
enumName
|
||
});
|
||
}
|
||
|
||
return initializedMembers;
|
||
}
|
||
}
|
||
|
||
flowEnumParseExplicitType({
|
||
enumName
|
||
}) {
|
||
if (this.eatContextual("of")) {
|
||
if (!this.match(_types.types.name)) {
|
||
throw this.flowEnumErrorInvalidExplicitType(this.state.start, {
|
||
enumName,
|
||
suppliedType: null
|
||
});
|
||
}
|
||
|
||
const {
|
||
value
|
||
} = this.state;
|
||
this.next();
|
||
|
||
if (value !== "boolean" && value !== "number" && value !== "string" && value !== "symbol") {
|
||
this.flowEnumErrorInvalidExplicitType(this.state.start, {
|
||
enumName,
|
||
suppliedType: value
|
||
});
|
||
}
|
||
|
||
return value;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
flowEnumBody(node, {
|
||
enumName,
|
||
nameLoc
|
||
}) {
|
||
const explicitType = this.flowEnumParseExplicitType({
|
||
enumName
|
||
});
|
||
this.expect(_types.types.braceL);
|
||
const members = this.flowEnumMembers({
|
||
enumName,
|
||
explicitType
|
||
});
|
||
|
||
switch (explicitType) {
|
||
case "boolean":
|
||
node.explicitType = true;
|
||
node.members = members.booleanMembers;
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumBooleanBody");
|
||
|
||
case "number":
|
||
node.explicitType = true;
|
||
node.members = members.numberMembers;
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumNumberBody");
|
||
|
||
case "string":
|
||
node.explicitType = true;
|
||
node.members = this.flowEnumStringMembers(members.stringMembers, members.defaultedMembers, {
|
||
enumName
|
||
});
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumStringBody");
|
||
|
||
case "symbol":
|
||
node.members = members.defaultedMembers;
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumSymbolBody");
|
||
|
||
default:
|
||
{
|
||
const empty = () => {
|
||
node.members = [];
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumStringBody");
|
||
};
|
||
|
||
node.explicitType = false;
|
||
const boolsLen = members.booleanMembers.length;
|
||
const numsLen = members.numberMembers.length;
|
||
const strsLen = members.stringMembers.length;
|
||
const defaultedLen = members.defaultedMembers.length;
|
||
|
||
if (!boolsLen && !numsLen && !strsLen && !defaultedLen) {
|
||
return empty();
|
||
} else if (!boolsLen && !numsLen) {
|
||
node.members = this.flowEnumStringMembers(members.stringMembers, members.defaultedMembers, {
|
||
enumName
|
||
});
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumStringBody");
|
||
} else if (!numsLen && !strsLen && boolsLen >= defaultedLen) {
|
||
for (let _i3 = 0, _members$defaultedMem = members.defaultedMembers; _i3 < _members$defaultedMem.length; _i3++) {
|
||
const member = _members$defaultedMem[_i3];
|
||
this.flowEnumErrorBooleanMemberNotInitialized(member.start, {
|
||
enumName,
|
||
memberName: member.id.name
|
||
});
|
||
}
|
||
|
||
node.members = members.booleanMembers;
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumBooleanBody");
|
||
} else if (!boolsLen && !strsLen && numsLen >= defaultedLen) {
|
||
for (let _i4 = 0, _members$defaultedMem2 = members.defaultedMembers; _i4 < _members$defaultedMem2.length; _i4++) {
|
||
const member = _members$defaultedMem2[_i4];
|
||
this.flowEnumErrorNumberMemberNotInitialized(member.start, {
|
||
enumName,
|
||
memberName: member.id.name
|
||
});
|
||
}
|
||
|
||
node.members = members.numberMembers;
|
||
this.expect(_types.types.braceR);
|
||
return this.finishNode(node, "EnumNumberBody");
|
||
} else {
|
||
this.flowEnumErrorInconsistentMemberValues(nameLoc, {
|
||
enumName
|
||
});
|
||
return empty();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
flowParseEnumDeclaration(node) {
|
||
const id = this.parseIdentifier();
|
||
node.id = id;
|
||
node.body = this.flowEnumBody(this.startNode(), {
|
||
enumName: id.name,
|
||
nameLoc: id.start
|
||
});
|
||
return this.finishNode(node, "EnumDeclaration");
|
||
}
|
||
|
||
};
|
||
|
||
exports.default = _default; |