UNPKG

@agoric/babel-parser

Version:

A JavaScript parser

1,692 lines (1,337 loc) 63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _types = require("../../tokenizer/types"); var _context = require("../../tokenizer/context"); var N = _interopRequireWildcard(require("../../types")); var _scopeflags = require("../../util/scopeflags"); var _scope = _interopRequireDefault(require("./scope")); var _productionParameter = require("../../util/production-parameter"); var _location = require("../../parser/location"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 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; } function nonNull(x) { if (x == null) { throw new Error(`Unexpected ${x} value.`); } return x; } function assert(x) { if (!x) { throw new Error("Assert fail"); } } const TSErrors = Object.freeze({ ClassMethodHasDeclare: "Class methods cannot have the 'declare' modifier", ClassMethodHasReadonly: "Class methods cannot have the 'readonly' modifier", DeclareClassFieldHasInitializer: "'declare' class fields cannot have an initializer", DuplicateModifier: "Duplicate modifier: '%0'", EmptyHeritageClauseType: "'%0' list cannot be empty.", IndexSignatureHasAbstract: "Index signatures cannot have the 'abstract' modifier", IndexSignatureHasAccessibility: "Index signatures cannot have an accessibility modifier ('%0')", IndexSignatureHasStatic: "Index signatures cannot have the 'static' modifier", OptionalTypeBeforeRequired: "A required element cannot follow an optional element.", PatternIsOptional: "A binding pattern parameter cannot be optional in an implementation signature.", PrivateElementHasAbstract: "Private elements cannot have the 'abstract' modifier.", PrivateElementHasAccessibility: "Private elements cannot have an accessibility modifier ('%0')", TemplateTypeHasSubstitution: "Template literal types cannot have any substitution", TypeAnnotationAfterAssign: "Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`", UnexpectedReadonly: "'readonly' type modifier is only permitted on array and tuple literal types.", UnexpectedTypeAnnotation: "Did not expect a type annotation here.", UnexpectedTypeCastInParameter: "Unexpected type cast in parameter position.", UnsupportedImportTypeArgument: "Argument in a type import must be a string literal", UnsupportedParameterPropertyKind: "A parameter property may not be declared using a binding pattern.", UnsupportedSignatureParameterKind: "Name in a signature must be an Identifier, ObjectPattern or ArrayPattern, instead got %0" }); function keywordTypeFromName(value) { switch (value) { case "any": return "TSAnyKeyword"; case "boolean": return "TSBooleanKeyword"; case "bigint": return "TSBigIntKeyword"; case "never": return "TSNeverKeyword"; case "number": return "TSNumberKeyword"; case "object": return "TSObjectKeyword"; case "string": return "TSStringKeyword"; case "symbol": return "TSSymbolKeyword"; case "undefined": return "TSUndefinedKeyword"; case "unknown": return "TSUnknownKeyword"; default: return undefined; } } var _default = superClass => class extends superClass { getScopeHandler() { return _scope.default; } tsIsIdentifier() { return this.match(_types.types.name); } tsNextTokenCanFollowModifier() { this.next(); return !this.hasPrecedingLineBreak() && !this.match(_types.types.parenL) && !this.match(_types.types.parenR) && !this.match(_types.types.colon) && !this.match(_types.types.eq) && !this.match(_types.types.question) && !this.match(_types.types.bang); } tsParseModifier(allowedModifiers) { if (!this.match(_types.types.name)) { return undefined; } const modifier = this.state.value; if (allowedModifiers.indexOf(modifier) !== -1 && this.tsTryParse(this.tsNextTokenCanFollowModifier.bind(this))) { return modifier; } return undefined; } tsParseModifiers(modified, allowedModifiers) { for (;;) { const startPos = this.state.start; const modifier = this.tsParseModifier(allowedModifiers); if (!modifier) break; if (Object.hasOwnProperty.call(modified, modifier)) { this.raise(startPos, TSErrors.DuplicateModifier, modifier); } modified[modifier] = true; } } tsIsListTerminator(kind) { switch (kind) { case "EnumMembers": case "TypeMembers": return this.match(_types.types.braceR); case "HeritageClauseElement": return this.match(_types.types.braceL); case "TupleElementTypes": return this.match(_types.types.bracketR); case "TypeParametersOrArguments": return this.isRelational(">"); } throw new Error("Unreachable"); } tsParseList(kind, parseElement) { const result = []; while (!this.tsIsListTerminator(kind)) { result.push(parseElement()); } return result; } tsParseDelimitedList(kind, parseElement) { return nonNull(this.tsParseDelimitedListWorker(kind, parseElement, true)); } tsParseDelimitedListWorker(kind, parseElement, expectSuccess) { const result = []; for (;;) { if (this.tsIsListTerminator(kind)) { break; } const element = parseElement(); if (element == null) { return undefined; } result.push(element); if (this.eat(_types.types.comma)) { continue; } if (this.tsIsListTerminator(kind)) { break; } if (expectSuccess) { this.expect(_types.types.comma); } return undefined; } return result; } tsParseBracketedList(kind, parseElement, bracket, skipFirstToken) { if (!skipFirstToken) { if (bracket) { this.expect(_types.types.bracketL); } else { this.expectRelational("<"); } } const result = this.tsParseDelimitedList(kind, parseElement); if (bracket) { this.expect(_types.types.bracketR); } else { this.expectRelational(">"); } return result; } tsParseImportType() { const node = this.startNode(); this.expect(_types.types._import); this.expect(_types.types.parenL); if (!this.match(_types.types.string)) { this.raise(this.state.start, TSErrors.UnsupportedImportTypeArgument); } node.argument = this.parseExprAtom(); this.expect(_types.types.parenR); if (this.eat(_types.types.dot)) { node.qualifier = this.tsParseEntityName(true); } if (this.isRelational("<")) { node.typeParameters = this.tsParseTypeArguments(); } return this.finishNode(node, "TSImportType"); } tsParseEntityName(allowReservedWords) { let entity = this.parseIdentifier(); while (this.eat(_types.types.dot)) { const node = this.startNodeAtNode(entity); node.left = entity; node.right = this.parseIdentifier(allowReservedWords); entity = this.finishNode(node, "TSQualifiedName"); } return entity; } tsParseTypeReference() { const node = this.startNode(); node.typeName = this.tsParseEntityName(false); if (!this.hasPrecedingLineBreak() && this.isRelational("<")) { node.typeParameters = this.tsParseTypeArguments(); } return this.finishNode(node, "TSTypeReference"); } tsParseThisTypePredicate(lhs) { this.next(); const node = this.startNodeAtNode(lhs); node.parameterName = lhs; node.typeAnnotation = this.tsParseTypeAnnotation(false); return this.finishNode(node, "TSTypePredicate"); } tsParseThisTypeNode() { const node = this.startNode(); this.next(); return this.finishNode(node, "TSThisType"); } tsParseTypeQuery() { const node = this.startNode(); this.expect(_types.types._typeof); if (this.match(_types.types._import)) { node.exprName = this.tsParseImportType(); } else { node.exprName = this.tsParseEntityName(true); } return this.finishNode(node, "TSTypeQuery"); } tsParseTypeParameter() { const node = this.startNode(); node.name = this.parseIdentifierName(node.start); node.constraint = this.tsEatThenParseType(_types.types._extends); node.default = this.tsEatThenParseType(_types.types.eq); return this.finishNode(node, "TSTypeParameter"); } tsTryParseTypeParameters() { if (this.isRelational("<")) { return this.tsParseTypeParameters(); } } tsParseTypeParameters() { const node = this.startNode(); if (this.isRelational("<") || this.match(_types.types.jsxTagStart)) { this.next(); } else { this.unexpected(); } node.params = this.tsParseBracketedList("TypeParametersOrArguments", this.tsParseTypeParameter.bind(this), false, true); return this.finishNode(node, "TSTypeParameterDeclaration"); } tsTryNextParseConstantContext() { if (this.lookahead().type === _types.types._const) { this.next(); return this.tsParseTypeReference(); } return null; } tsFillSignature(returnToken, signature) { const returnTokenRequired = returnToken === _types.types.arrow; signature.typeParameters = this.tsTryParseTypeParameters(); this.expect(_types.types.parenL); signature.parameters = this.tsParseBindingListForSignature(); if (returnTokenRequired) { signature.typeAnnotation = this.tsParseTypeOrTypePredicateAnnotation(returnToken); } else if (this.match(returnToken)) { signature.typeAnnotation = this.tsParseTypeOrTypePredicateAnnotation(returnToken); } } tsParseBindingListForSignature() { return this.parseBindingList(_types.types.parenR, 41).map(pattern => { if (pattern.type !== "Identifier" && pattern.type !== "RestElement" && pattern.type !== "ObjectPattern" && pattern.type !== "ArrayPattern") { this.raise(pattern.start, TSErrors.UnsupportedSignatureParameterKind, pattern.type); } return pattern; }); } tsParseTypeMemberSemicolon() { if (!this.eat(_types.types.comma)) { this.semicolon(); } } tsParseSignatureMember(kind, node) { this.tsFillSignature(_types.types.colon, node); this.tsParseTypeMemberSemicolon(); return this.finishNode(node, kind); } tsIsUnambiguouslyIndexSignature() { this.next(); return this.eat(_types.types.name) && this.match(_types.types.colon); } tsTryParseIndexSignature(node) { if (!(this.match(_types.types.bracketL) && this.tsLookAhead(this.tsIsUnambiguouslyIndexSignature.bind(this)))) { return undefined; } this.expect(_types.types.bracketL); const id = this.parseIdentifier(); id.typeAnnotation = this.tsParseTypeAnnotation(); this.resetEndLocation(id); this.expect(_types.types.bracketR); node.parameters = [id]; const type = this.tsTryParseTypeAnnotation(); if (type) node.typeAnnotation = type; this.tsParseTypeMemberSemicolon(); return this.finishNode(node, "TSIndexSignature"); } tsParsePropertyOrMethodSignature(node, readonly) { if (this.eat(_types.types.question)) node.optional = true; const nodeAny = node; if (!readonly && (this.match(_types.types.parenL) || this.isRelational("<"))) { const method = nodeAny; this.tsFillSignature(_types.types.colon, method); this.tsParseTypeMemberSemicolon(); return this.finishNode(method, "TSMethodSignature"); } else { const property = nodeAny; if (readonly) property.readonly = true; const type = this.tsTryParseTypeAnnotation(); if (type) property.typeAnnotation = type; this.tsParseTypeMemberSemicolon(); return this.finishNode(property, "TSPropertySignature"); } } tsParseTypeMember() { const node = this.startNode(); if (this.match(_types.types.parenL) || this.isRelational("<")) { return this.tsParseSignatureMember("TSCallSignatureDeclaration", node); } if (this.match(_types.types._new)) { const id = this.startNode(); this.next(); if (this.match(_types.types.parenL) || this.isRelational("<")) { return this.tsParseSignatureMember("TSConstructSignatureDeclaration", node); } else { node.key = this.createIdentifier(id, "new"); return this.tsParsePropertyOrMethodSignature(node, false); } } const readonly = !!this.tsParseModifier(["readonly"]); const idx = this.tsTryParseIndexSignature(node); if (idx) { if (readonly) node.readonly = true; return idx; } this.parsePropertyName(node, false); return this.tsParsePropertyOrMethodSignature(node, readonly); } tsParseTypeLiteral() { const node = this.startNode(); node.members = this.tsParseObjectTypeMembers(); return this.finishNode(node, "TSTypeLiteral"); } tsParseObjectTypeMembers() { this.expect(_types.types.braceL); const members = this.tsParseList("TypeMembers", this.tsParseTypeMember.bind(this)); this.expect(_types.types.braceR); return members; } tsIsStartOfMappedType() { this.next(); if (this.eat(_types.types.plusMin)) { return this.isContextual("readonly"); } if (this.isContextual("readonly")) { this.next(); } if (!this.match(_types.types.bracketL)) { return false; } this.next(); if (!this.tsIsIdentifier()) { return false; } this.next(); return this.match(_types.types._in); } tsParseMappedTypeParameter() { const node = this.startNode(); node.name = this.parseIdentifierName(node.start); node.constraint = this.tsExpectThenParseType(_types.types._in); return this.finishNode(node, "TSTypeParameter"); } tsParseMappedType() { const node = this.startNode(); this.expect(_types.types.braceL); if (this.match(_types.types.plusMin)) { node.readonly = this.state.value; this.next(); this.expectContextual("readonly"); } else if (this.eatContextual("readonly")) { node.readonly = true; } this.expect(_types.types.bracketL); node.typeParameter = this.tsParseMappedTypeParameter(); this.expect(_types.types.bracketR); if (this.match(_types.types.plusMin)) { node.optional = this.state.value; this.next(); this.expect(_types.types.question); } else if (this.eat(_types.types.question)) { node.optional = true; } node.typeAnnotation = this.tsTryParseType(); this.semicolon(); this.expect(_types.types.braceR); return this.finishNode(node, "TSMappedType"); } tsParseTupleType() { const node = this.startNode(); node.elementTypes = this.tsParseBracketedList("TupleElementTypes", this.tsParseTupleElementType.bind(this), true, false); let seenOptionalElement = false; node.elementTypes.forEach(elementNode => { if (elementNode.type === "TSOptionalType") { seenOptionalElement = true; } else if (seenOptionalElement && elementNode.type !== "TSRestType") { this.raise(elementNode.start, TSErrors.OptionalTypeBeforeRequired); } }); return this.finishNode(node, "TSTupleType"); } tsParseTupleElementType() { if (this.match(_types.types.ellipsis)) { const restNode = this.startNode(); this.next(); restNode.typeAnnotation = this.tsParseType(); if (this.match(_types.types.comma) && this.lookaheadCharCode() !== 93) { this.raiseRestNotLast(this.state.start); } return this.finishNode(restNode, "TSRestType"); } const type = this.tsParseType(); if (this.eat(_types.types.question)) { const optionalTypeNode = this.startNodeAtNode(type); optionalTypeNode.typeAnnotation = type; return this.finishNode(optionalTypeNode, "TSOptionalType"); } return type; } tsParseParenthesizedType() { const node = this.startNode(); this.expect(_types.types.parenL); node.typeAnnotation = this.tsParseType(); this.expect(_types.types.parenR); return this.finishNode(node, "TSParenthesizedType"); } tsParseFunctionOrConstructorType(type) { const node = this.startNode(); if (type === "TSConstructorType") { this.expect(_types.types._new); } this.tsFillSignature(_types.types.arrow, node); return this.finishNode(node, type); } tsParseLiteralTypeNode() { const node = this.startNode(); node.literal = (() => { switch (this.state.type) { case _types.types.num: case _types.types.string: case _types.types._true: case _types.types._false: return this.parseExprAtom(); default: throw this.unexpected(); } })(); return this.finishNode(node, "TSLiteralType"); } tsParseTemplateLiteralType() { const node = this.startNode(); const templateNode = this.parseTemplate(false); if (templateNode.expressions.length > 0) { this.raise(templateNode.expressions[0].start, TSErrors.TemplateTypeHasSubstitution); } node.literal = templateNode; return this.finishNode(node, "TSLiteralType"); } tsParseThisTypeOrThisTypePredicate() { const thisKeyword = this.tsParseThisTypeNode(); if (this.isContextual("is") && !this.hasPrecedingLineBreak()) { return this.tsParseThisTypePredicate(thisKeyword); } else { return thisKeyword; } } tsParseNonArrayType() { switch (this.state.type) { case _types.types.name: case _types.types._void: case _types.types._null: { const type = this.match(_types.types._void) ? "TSVoidKeyword" : this.match(_types.types._null) ? "TSNullKeyword" : keywordTypeFromName(this.state.value); if (type !== undefined && this.lookaheadCharCode() !== 46) { const node = this.startNode(); this.next(); return this.finishNode(node, type); } return this.tsParseTypeReference(); } case _types.types.string: case _types.types.num: case _types.types._true: case _types.types._false: return this.tsParseLiteralTypeNode(); case _types.types.plusMin: if (this.state.value === "-") { const node = this.startNode(); if (this.lookahead().type !== _types.types.num) { throw this.unexpected(); } node.literal = this.parseMaybeUnary(); return this.finishNode(node, "TSLiteralType"); } break; case _types.types._this: return this.tsParseThisTypeOrThisTypePredicate(); case _types.types._typeof: return this.tsParseTypeQuery(); case _types.types._import: return this.tsParseImportType(); case _types.types.braceL: return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this)) ? this.tsParseMappedType() : this.tsParseTypeLiteral(); case _types.types.bracketL: return this.tsParseTupleType(); case _types.types.parenL: return this.tsParseParenthesizedType(); case _types.types.backQuote: return this.tsParseTemplateLiteralType(); } throw this.unexpected(); } tsParseArrayTypeOrHigher() { let type = this.tsParseNonArrayType(); while (!this.hasPrecedingLineBreak() && this.eat(_types.types.bracketL)) { if (this.match(_types.types.bracketR)) { const node = this.startNodeAtNode(type); node.elementType = type; this.expect(_types.types.bracketR); type = this.finishNode(node, "TSArrayType"); } else { const node = this.startNodeAtNode(type); node.objectType = type; node.indexType = this.tsParseType(); this.expect(_types.types.bracketR); type = this.finishNode(node, "TSIndexedAccessType"); } } return type; } tsParseTypeOperator(operator) { const node = this.startNode(); this.expectContextual(operator); node.operator = operator; node.typeAnnotation = this.tsParseTypeOperatorOrHigher(); if (operator === "readonly") { this.tsCheckTypeAnnotationForReadOnly(node); } return this.finishNode(node, "TSTypeOperator"); } tsCheckTypeAnnotationForReadOnly(node) { switch (node.typeAnnotation.type) { case "TSTupleType": case "TSArrayType": return; default: this.raise(node.start, TSErrors.UnexpectedReadonly); } } tsParseInferType() { const node = this.startNode(); this.expectContextual("infer"); const typeParameter = this.startNode(); typeParameter.name = this.parseIdentifierName(typeParameter.start); node.typeParameter = this.finishNode(typeParameter, "TSTypeParameter"); return this.finishNode(node, "TSInferType"); } tsParseTypeOperatorOrHigher() { const operator = ["keyof", "unique", "readonly"].find(kw => this.isContextual(kw)); return operator ? this.tsParseTypeOperator(operator) : this.isContextual("infer") ? this.tsParseInferType() : this.tsParseArrayTypeOrHigher(); } tsParseUnionOrIntersectionType(kind, parseConstituentType, operator) { this.eat(operator); let type = parseConstituentType(); if (this.match(operator)) { const types = [type]; while (this.eat(operator)) { types.push(parseConstituentType()); } const node = this.startNodeAtNode(type); node.types = types; type = this.finishNode(node, kind); } return type; } tsParseIntersectionTypeOrHigher() { return this.tsParseUnionOrIntersectionType("TSIntersectionType", this.tsParseTypeOperatorOrHigher.bind(this), _types.types.bitwiseAND); } tsParseUnionTypeOrHigher() { return this.tsParseUnionOrIntersectionType("TSUnionType", this.tsParseIntersectionTypeOrHigher.bind(this), _types.types.bitwiseOR); } tsIsStartOfFunctionType() { if (this.isRelational("<")) { return true; } return this.match(_types.types.parenL) && this.tsLookAhead(this.tsIsUnambiguouslyStartOfFunctionType.bind(this)); } tsSkipParameterStart() { if (this.match(_types.types.name) || this.match(_types.types._this)) { this.next(); return true; } if (this.match(_types.types.braceL)) { let braceStackCounter = 1; this.next(); while (braceStackCounter > 0) { if (this.match(_types.types.braceL)) { ++braceStackCounter; } else if (this.match(_types.types.braceR)) { --braceStackCounter; } this.next(); } return true; } if (this.match(_types.types.bracketL)) { let braceStackCounter = 1; this.next(); while (braceStackCounter > 0) { if (this.match(_types.types.bracketL)) { ++braceStackCounter; } else if (this.match(_types.types.bracketR)) { --braceStackCounter; } this.next(); } return true; } return false; } tsIsUnambiguouslyStartOfFunctionType() { this.next(); if (this.match(_types.types.parenR) || this.match(_types.types.ellipsis)) { return true; } if (this.tsSkipParameterStart()) { if (this.match(_types.types.colon) || this.match(_types.types.comma) || this.match(_types.types.question) || this.match(_types.types.eq)) { return true; } if (this.match(_types.types.parenR)) { this.next(); if (this.match(_types.types.arrow)) { return true; } } } return false; } tsParseTypeOrTypePredicateAnnotation(returnToken) { return this.tsInType(() => { const t = this.startNode(); this.expect(returnToken); const asserts = this.tsTryParse(this.tsParseTypePredicateAsserts.bind(this)); if (asserts && this.match(_types.types._this)) { let thisTypePredicate = this.tsParseThisTypeOrThisTypePredicate(); if (thisTypePredicate.type === "TSThisType") { const node = this.startNodeAtNode(t); node.parameterName = thisTypePredicate; node.asserts = true; thisTypePredicate = this.finishNode(node, "TSTypePredicate"); } else { thisTypePredicate.asserts = true; } t.typeAnnotation = thisTypePredicate; return this.finishNode(t, "TSTypeAnnotation"); } const typePredicateVariable = this.tsIsIdentifier() && this.tsTryParse(this.tsParseTypePredicatePrefix.bind(this)); if (!typePredicateVariable) { if (!asserts) { return this.tsParseTypeAnnotation(false, t); } const node = this.startNodeAtNode(t); node.parameterName = this.parseIdentifier(); node.asserts = asserts; t.typeAnnotation = this.finishNode(node, "TSTypePredicate"); return this.finishNode(t, "TSTypeAnnotation"); } const type = this.tsParseTypeAnnotation(false); const node = this.startNodeAtNode(t); node.parameterName = typePredicateVariable; node.typeAnnotation = type; node.asserts = asserts; t.typeAnnotation = this.finishNode(node, "TSTypePredicate"); return this.finishNode(t, "TSTypeAnnotation"); }); } tsTryParseTypeOrTypePredicateAnnotation() { return this.match(_types.types.colon) ? this.tsParseTypeOrTypePredicateAnnotation(_types.types.colon) : undefined; } tsTryParseTypeAnnotation() { return this.match(_types.types.colon) ? this.tsParseTypeAnnotation() : undefined; } tsTryParseType() { return this.tsEatThenParseType(_types.types.colon); } tsParseTypePredicatePrefix() { const id = this.parseIdentifier(); if (this.isContextual("is") && !this.hasPrecedingLineBreak()) { this.next(); return id; } } tsParseTypePredicateAsserts() { if (!this.match(_types.types.name) || this.state.value !== "asserts" || this.hasPrecedingLineBreak()) { return false; } const containsEsc = this.state.containsEsc; this.next(); if (!this.match(_types.types.name) && !this.match(_types.types._this)) { return false; } if (containsEsc) { this.raise(this.state.lastTokStart, _location.Errors.InvalidEscapedReservedWord, "asserts"); } return true; } tsParseTypeAnnotation(eatColon = true, t = this.startNode()) { this.tsInType(() => { if (eatColon) this.expect(_types.types.colon); t.typeAnnotation = this.tsParseType(); }); return this.finishNode(t, "TSTypeAnnotation"); } tsParseType() { assert(this.state.inType); const type = this.tsParseNonConditionalType(); if (this.hasPrecedingLineBreak() || !this.eat(_types.types._extends)) { return type; } const node = this.startNodeAtNode(type); node.checkType = type; node.extendsType = this.tsParseNonConditionalType(); this.expect(_types.types.question); node.trueType = this.tsParseType(); this.expect(_types.types.colon); node.falseType = this.tsParseType(); return this.finishNode(node, "TSConditionalType"); } tsParseNonConditionalType() { if (this.tsIsStartOfFunctionType()) { return this.tsParseFunctionOrConstructorType("TSFunctionType"); } if (this.match(_types.types._new)) { return this.tsParseFunctionOrConstructorType("TSConstructorType"); } return this.tsParseUnionTypeOrHigher(); } tsParseTypeAssertion() { const node = this.startNode(); const _const = this.tsTryNextParseConstantContext(); node.typeAnnotation = _const || this.tsNextThenParseType(); this.expectRelational(">"); node.expression = this.parseMaybeUnary(); return this.finishNode(node, "TSTypeAssertion"); } tsParseHeritageClause(descriptor) { const originalStart = this.state.start; const delimitedList = this.tsParseDelimitedList("HeritageClauseElement", this.tsParseExpressionWithTypeArguments.bind(this)); if (!delimitedList.length) { this.raise(originalStart, TSErrors.EmptyHeritageClauseType, descriptor); } return delimitedList; } tsParseExpressionWithTypeArguments() { const node = this.startNode(); node.expression = this.tsParseEntityName(false); if (this.isRelational("<")) { node.typeParameters = this.tsParseTypeArguments(); } return this.finishNode(node, "TSExpressionWithTypeArguments"); } tsParseInterfaceDeclaration(node) { node.id = this.parseIdentifier(); this.checkLVal(node.id, _scopeflags.BIND_TS_INTERFACE, undefined, "typescript interface declaration"); node.typeParameters = this.tsTryParseTypeParameters(); if (this.eat(_types.types._extends)) { node.extends = this.tsParseHeritageClause("extends"); } const body = this.startNode(); body.body = this.tsInType(this.tsParseObjectTypeMembers.bind(this)); node.body = this.finishNode(body, "TSInterfaceBody"); return this.finishNode(node, "TSInterfaceDeclaration"); } tsParseTypeAliasDeclaration(node) { node.id = this.parseIdentifier(); this.checkLVal(node.id, _scopeflags.BIND_TS_TYPE, undefined, "typescript type alias"); node.typeParameters = this.tsTryParseTypeParameters(); node.typeAnnotation = this.tsExpectThenParseType(_types.types.eq); this.semicolon(); return this.finishNode(node, "TSTypeAliasDeclaration"); } tsInNoContext(cb) { const oldContext = this.state.context; this.state.context = [oldContext[0]]; try { return cb(); } finally { this.state.context = oldContext; } } tsInType(cb) { const oldInType = this.state.inType; this.state.inType = true; try { return cb(); } finally { this.state.inType = oldInType; } } tsEatThenParseType(token) { return !this.match(token) ? undefined : this.tsNextThenParseType(); } tsExpectThenParseType(token) { return this.tsDoThenParseType(() => this.expect(token)); } tsNextThenParseType() { return this.tsDoThenParseType(() => this.next()); } tsDoThenParseType(cb) { return this.tsInType(() => { cb(); return this.tsParseType(); }); } tsParseEnumMember() { const node = this.startNode(); node.id = this.match(_types.types.string) ? this.parseExprAtom() : this.parseIdentifier(true); if (this.eat(_types.types.eq)) { node.initializer = this.parseMaybeAssign(); } return this.finishNode(node, "TSEnumMember"); } tsParseEnumDeclaration(node, isConst) { if (isConst) node.const = true; node.id = this.parseIdentifier(); this.checkLVal(node.id, isConst ? _scopeflags.BIND_TS_CONST_ENUM : _scopeflags.BIND_TS_ENUM, undefined, "typescript enum declaration"); this.expect(_types.types.braceL); node.members = this.tsParseDelimitedList("EnumMembers", this.tsParseEnumMember.bind(this)); this.expect(_types.types.braceR); return this.finishNode(node, "TSEnumDeclaration"); } tsParseModuleBlock() { const node = this.startNode(); this.scope.enter(_scopeflags.SCOPE_OTHER); this.expect(_types.types.braceL); this.parseBlockOrModuleBlockBody(node.body = [], undefined, true, _types.types.braceR); this.scope.exit(); return this.finishNode(node, "TSModuleBlock"); } tsParseModuleOrNamespaceDeclaration(node, nested = false) { node.id = this.parseIdentifier(); if (!nested) { this.checkLVal(node.id, _scopeflags.BIND_TS_NAMESPACE, null, "module or namespace declaration"); } if (this.eat(_types.types.dot)) { const inner = this.startNode(); this.tsParseModuleOrNamespaceDeclaration(inner, true); node.body = inner; } else { this.scope.enter(_scopeflags.SCOPE_TS_MODULE); this.prodParam.enter(_productionParameter.PARAM); node.body = this.tsParseModuleBlock(); this.prodParam.exit(); this.scope.exit(); } return this.finishNode(node, "TSModuleDeclaration"); } tsParseAmbientExternalModuleDeclaration(node) { if (this.isContextual("global")) { node.global = true; node.id = this.parseIdentifier(); } else if (this.match(_types.types.string)) { node.id = this.parseExprAtom(); } else { this.unexpected(); } if (this.match(_types.types.braceL)) { this.scope.enter(_scopeflags.SCOPE_TS_MODULE); this.prodParam.enter(_productionParameter.PARAM); node.body = this.tsParseModuleBlock(); this.prodParam.exit(); this.scope.exit(); } else { this.semicolon(); } return this.finishNode(node, "TSModuleDeclaration"); } tsParseImportEqualsDeclaration(node, isExport) { node.isExport = isExport || false; node.id = this.parseIdentifier(); this.checkLVal(node.id, _scopeflags.BIND_LEXICAL, undefined, "import equals declaration"); this.expect(_types.types.eq); node.moduleReference = this.tsParseModuleReference(); this.semicolon(); return this.finishNode(node, "TSImportEqualsDeclaration"); } tsIsExternalModuleReference() { return this.isContextual("require") && this.lookaheadCharCode() === 40; } tsParseModuleReference() { return this.tsIsExternalModuleReference() ? this.tsParseExternalModuleReference() : this.tsParseEntityName(false); } tsParseExternalModuleReference() { const node = this.startNode(); this.expectContextual("require"); this.expect(_types.types.parenL); if (!this.match(_types.types.string)) { throw this.unexpected(); } node.expression = this.parseExprAtom(); this.expect(_types.types.parenR); return this.finishNode(node, "TSExternalModuleReference"); } tsLookAhead(f) { const state = this.state.clone(); const res = f(); this.state = state; return res; } tsTryParseAndCatch(f) { const result = this.tryParse(abort => f() || abort()); if (result.aborted || !result.node) return undefined; if (result.error) this.state = result.failState; return result.node; } tsTryParse(f) { const state = this.state.clone(); const result = f(); if (result !== undefined && result !== false) { return result; } else { this.state = state; return undefined; } } tsTryParseDeclare(nany) { if (this.isLineTerminator()) { return; } let starttype = this.state.type; let kind; if (this.isContextual("let")) { starttype = _types.types._var; kind = "let"; } switch (starttype) { case _types.types._function: return this.parseFunctionStatement(nany, false, true); case _types.types._class: nany.declare = true; return this.parseClass(nany, true, false); case _types.types._const: if (this.match(_types.types._const) && this.isLookaheadContextual("enum")) { this.expect(_types.types._const); this.expectContextual("enum"); return this.tsParseEnumDeclaration(nany, true); } case _types.types._var: kind = kind || this.state.value; return this.parseVarStatement(nany, kind); case _types.types.name: { const value = this.state.value; if (value === "global") { return this.tsParseAmbientExternalModuleDeclaration(nany); } else { return this.tsParseDeclaration(nany, value, true); } } } } tsTryParseExportDeclaration() { return this.tsParseDeclaration(this.startNode(), this.state.value, true); } tsParseExpressionStatement(node, expr) { switch (expr.name) { case "declare": { const declaration = this.tsTryParseDeclare(node); if (declaration) { declaration.declare = true; return declaration; } break; } case "global": if (this.match(_types.types.braceL)) { this.scope.enter(_scopeflags.SCOPE_TS_MODULE); this.prodParam.enter(_productionParameter.PARAM); const mod = node; mod.global = true; mod.id = expr; mod.body = this.tsParseModuleBlock(); this.scope.exit(); this.prodParam.exit(); return this.finishNode(mod, "TSModuleDeclaration"); } break; default: return this.tsParseDeclaration(node, expr.name, false); } } tsParseDeclaration(node, value, next) { switch (value) { case "abstract": if (this.tsCheckLineTerminatorAndMatch(_types.types._class, next)) { const cls = node; cls.abstract = true; if (next) { this.next(); if (!this.match(_types.types._class)) { this.unexpected(null, _types.types._class); } } return this.parseClass(cls, true, false); } break; case "enum": if (next || this.match(_types.types.name)) { if (next) this.next(); return this.tsParseEnumDeclaration(node, false); } break; case "interface": if (this.tsCheckLineTerminatorAndMatch(_types.types.name, next)) { if (next) this.next(); return this.tsParseInterfaceDeclaration(node); } break; case "module": if (next) this.next(); if (this.match(_types.types.string)) { return this.tsParseAmbientExternalModuleDeclaration(node); } else if (this.tsCheckLineTerminatorAndMatch(_types.types.name, next)) { return this.tsParseModuleOrNamespaceDeclaration(node); } break; case "namespace": if (this.tsCheckLineTerminatorAndMatch(_types.types.name, next)) { if (next) this.next(); return this.tsParseModuleOrNamespaceDeclaration(node); } break; case "type": if (this.tsCheckLineTerminatorAndMatch(_types.types.name, next)) { if (next) this.next(); return this.tsParseTypeAliasDeclaration(node); } break; } } tsCheckLineTerminatorAndMatch(tokenType, next) { return (next || this.match(tokenType)) && !this.isLineTerminator(); } tsTryParseGenericAsyncArrowFunction(startPos, startLoc) { if (!this.isRelational("<")) { return undefined; } const oldMaybeInArrowParameters = this.state.maybeInArrowParameters; const oldYieldPos = this.state.yieldPos; const oldAwaitPos = this.state.awaitPos; this.state.maybeInArrowParameters = true; this.state.yieldPos = -1; this.state.awaitPos = -1; const res = this.tsTryParseAndCatch(() => { const node = this.startNodeAt(startPos, startLoc); node.typeParameters = this.tsParseTypeParameters(); super.parseFunctionParams(node); node.returnType = this.tsTryParseTypeOrTypePredicateAnnotation(); this.expect(_types.types.arrow); return node; }); this.state.maybeInArrowParameters = oldMaybeInArrowParameters; this.state.yieldPos = oldYieldPos; this.state.awaitPos = oldAwaitPos; if (!res) { return undefined; } return this.parseArrowExpression(res, null, true); } tsParseTypeArguments() { const node = this.startNode(); node.params = this.tsInType(() => this.tsInNoContext(() => { this.expectRelational("<"); return this.tsParseDelimitedList("TypeParametersOrArguments", this.tsParseType.bind(this)); })); this.state.exprAllowed = false; this.expectRelational(">"); return this.finishNode(node, "TSTypeParameterInstantiation"); } tsIsDeclarationStart() { if (this.match(_types.types.name)) { switch (this.state.value) { case "abstract": case "declare": case "enum": case "interface": case "module": case "namespace": case "type": return true; } } return false; } isExportDefaultSpecifier() { if (this.tsIsDeclarationStart()) return false; return super.isExportDefaultSpecifier(); } parseAssignableListItem(allowModifiers, decorators) { const startPos = this.state.start; const startLoc = this.state.startLoc; let accessibility; let readonly = false; if (allowModifiers) { accessibility = this.parseAccessModifier(); readonly = !!this.tsParseModifier(["readonly"]); } const left = this.parseMaybeDefault(); this.parseAssignableListItemTypes(left); const elt = this.parseMaybeDefault(left.start, left.loc.start, left); if (accessibility || readonly) { const pp = this.startNodeAt(startPos, startLoc); if (decorators.length) { pp.decorators = decorators; } if (accessibility) pp.accessibility = accessibility; if (readonly) pp.readonly = readonly; if (elt.type !== "Identifier" && elt.type !== "AssignmentPattern") { this.raise(pp.start, TSErrors.UnsupportedParameterPropertyKind); } pp.parameter = elt; return this.finishNode(pp, "TSParameterProperty"); } if (decorators.length) { left.decorators = decorators; } return elt; } parseFunctionBodyAndFinish(node, type, isMethod = false) { if (this.match(_types.types.colon)) { node.returnType = this.tsParseTypeOrTypePredicateAnnotation(_types.types.colon); } const bodilessType = type === "FunctionDeclaration" ? "TSDeclareFunction" : type === "ClassMethod" ? "TSDeclareMethod" : undefined; if (bodilessType && !this.match(_types.types.braceL) && this.isLineTerminator()) { this.finishNode(node, bodilessType); return; } super.parseFunctionBodyAndFinish(node, type, isMethod); } registerFunctionStatementId(node) { if (!node.body && node.id) { this.checkLVal(node.id, _scopeflags.BIND_TS_AMBIENT, null, "function name"); } else { super.registerFunctionStatementId(...arguments); } } parseSubscript(base, startPos, startLoc, noCalls, state) { if (!this.hasPrecedingLineBreak() && this.match(_types.types.bang)) { this.state.exprAllowed = false; this.next(); const nonNullExpression = this.startNodeAt(startPos, startLoc); nonNullExpression.expression = base; return this.finishNode(nonNullExpression, "TSNonNullExpression"); } if (this.isRelational("<")) { const result = this.tsTryParseAndCatch(() => { if (!noCalls && this.atPossibleAsyncArrow(base)) { const asyncArrowFn = this.tsTryParseGenericAsyncArrowFunction(startPos, startLoc); if (asyncArrowFn) { return asyncArrowFn; } } const node = this.startNodeAt(startPos, startLoc); node.callee = base; const typeArguments = this.tsParseTypeArguments(); if (typeArguments) { if (!noCalls && this.eat(_types.types.parenL)) { node.arguments = this.parseCallExpressionArguments(_types.types.parenR, false); node.typeParameters = typeArguments; return this.finishCallExpression(node, state.optionalChainMember); } else if (this.match(_types.types.backQuote)) { return this.parseTaggedTemplateExpression(startPos, startLoc, base, state, typeArguments); } } this.unexpected(); }); if (result) return result; } return super.parseSubscript(base, startPos, startLoc, noCalls, state); } parseNewArguments(node) { if (this.isRelational("<")) { const typeParameters = this.tsTryParseAndCatch(() => { const args = this.tsParseTypeArguments(); if (!this.match(_types.types.parenL)) this.unexpected(); return args; }); if (typeParameters) { node.typeParameters = typeParameters; } } super.parseNewArguments(node); } parseExprOp(left, leftStartPos, leftStartLoc, minPrec, noIn) { if (nonNull(_types.types._in.binop) > minPrec && !this.hasPrecedingLineBreak() && this.isContextual("as")) { const node = this.startNodeAt(leftStartPos, leftStartLoc); node.expression = left; const _const = this.tsTryNextParseConstantContext(); if (_const) { node.typeAnnotation = _const; } else { node.typeAnnotation = this.tsNextThenParseType(); } this.finishNode(node, "TSAsExpression"); return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); } return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec, noIn); } checkReservedWord(word, startLoc, checkKeywords, isBinding) {} checkDuplicateExports() {} parseImport(node) { if (this.match(_types.types.name) || this.match(_types.types.star) || this.match(_types.types.braceL)) { const ahead = this.lookahead(); if (this.match(_types.types.name) && ahead.type === _types.types.eq) { return this.tsParseImportEqualsDeclaration(node); } if (this.isContextual("type") && ahead.type !== _types.types.comma && !(ahead.type === _types.types.name && ahead.value === "from")) { node.importKind = "type"; this.next(); } else { node.importKind = "value"; } } const importNode = super.parseImport(node); if (importNode.importKind === "type" && importNode.specifiers.length > 1 && importNode.specifiers[0].type === "ImportDefaultSpecifier") { this.raise(importNode.start, "A type-only import can specify a default import or named bindings, but not both."); } return importNode; } parseExport(node) { if (this.match(_types.types._import)) { this.expect(_types.types._import); return this.tsParseImportEqualsDeclaration(node, true); } else if (this.eat(_types.types.eq)) { const assign = node; assign.expression = this.parseExpression(); this.semicolon(); return this.finishNode(assign, "TSExportAssignment"); } else if (this.eatContextual("as")) { const decl = node; this.expectContextual("namespace"); decl.id = this.parseIdentifier(); this.semicolon(); return this.finishNode(decl, "TSNamespaceExportDeclaration"); } else { if (this.isContextual("type") && this.lookahead().type === _types.types.braceL) { this.next(); node.exportKind = "type"; } else { node.exportKind = "value"; } return super.parseExport(node); } } isAbstractClass() { return this.isContextual("abstract") && this.lookahead().type === _types.types._class; } parseExportDefaultExpression() { if (this.isAbstractClass()) { const cls = this.startNode(); this.next(); this.parseClass(cls, true, true); cls.abstract = true; return cls; } if (this.state.value === "interface") { const result = this.tsParseDeclaration(this.startNode(), this.state.value, true); if (result) return result; } return super.parseExportDefaultExpression(); } parseStatementContent(context, topLevel) { if (this.state.type === _types.types._const) { const ahead = this.lookahead(); if (ahead.type === _types.types.name && ahead.value === "enum") { const node = this.startNode(); this.expect(_types.types._const); this.expectContextual("enum"); return this.tsParseEnumDeclaration(node, true); } } return super.parseStatementContent(context, topLevel); } parseAccessModifier() { return this.tsParseModifier(["public", "protected", "private"]); } parseClassMember(classBody, member, state, constructorAllowsSuper) { this.tsParseModifiers(member, ["declare"]); const accessibility = this.parseAccessModifier(); if (accessibility) member.accessibility = accessibility; this.tsParseModifiers(member, ["declare"]); super.parseClassMember(classBody, member, state, constructorAllowsSuper); } parseClassMemberWithIsStatic(classBody, member, state, isStatic, constructorAllowsSuper) { this.tsParseModifiers(member, ["abstract", "readonly", "declare"]); const idx = this.tsTryParseIndexSignature(member); if (idx) { classBody.body.push(idx); if (member.abstract) { this.raise(member.start, TSErrors.IndexSignatureHasAbstract); } if (isStatic) { this.raise(member.start, TSErrors.IndexSignatureHasStatic); } if (member.accessibility) { this.raise(member.start, TSErrors.IndexSignatureHasAccessibility, member.accessibility); } return; } super.parseClassMemberWithIsStatic(classBody, member, state, isStatic, constructorAllowsSuper); } parsePostMemberNameModifiers(methodOrProp) { const optional = this.eat(_types.types.question); if (optional) methodOrProp.optional = true; if (methodOrProp.readonly && this.match(_types.types.parenL)) { this.raise(methodOrProp.start, TSErrors.ClassMethodHasReadonly); } if (methodOrProp.declare && this.match(_types.types.parenL)) { this.raise(methodOrProp.start, TSErrors.ClassMetho