sucrase
Version:
Super-fast alternative to Babel for when you can target modern JS runtimes
1,347 lines (1,165 loc) • 47.3 kB
JavaScript
Object.defineProperty(exports, "__esModule", {value: true});
var _index = require('../tokenizer/index');
var _keywords = require('../tokenizer/keywords');
var _types = require('../tokenizer/types');
var _base = require('../traverser/base');
var _expression = require('../traverser/expression');
var _lval = require('../traverser/lval');
var _statement = require('../traverser/statement');
var _util = require('../traverser/util');
var _jsx = require('./jsx');
function tsIsIdentifier() {
// TODO: actually a bit more complex in TypeScript, but shouldn't matter.
// See https://github.com/Microsoft/TypeScript/issues/15008
return _index.match.call(void 0, _types.TokenType.name);
}
function tsNextTokenCanFollowModifier() {
// Note: TypeScript's implementation is much more complicated because
// more things are considered modifiers there.
// This implementation only handles modifiers not handled by babylon itself. And "static".
// TODO: Would be nice to avoid lookahead. Want a hasLineBreakUpNext() method...
const snapshot = _base.state.snapshot();
_index.next.call(void 0, );
const canFollowModifier =
!_util.hasPrecedingLineBreak.call(void 0, ) &&
!_index.match.call(void 0, _types.TokenType.parenL) &&
!_index.match.call(void 0, _types.TokenType.parenR) &&
!_index.match.call(void 0, _types.TokenType.colon) &&
!_index.match.call(void 0, _types.TokenType.eq) &&
!_index.match.call(void 0, _types.TokenType.question);
if (canFollowModifier) {
return true;
} else {
_base.state.restoreFromSnapshot(snapshot);
return false;
}
}
/** Parses a modifier matching one the given modifier names. */
function tsParseModifier(
allowedModifiers,
) {
if (!_index.match.call(void 0, _types.TokenType.name)) {
return null;
}
const modifier = _base.state.contextualKeyword;
if (allowedModifiers.indexOf(modifier) !== -1 && tsNextTokenCanFollowModifier()) {
switch (modifier) {
case _keywords.ContextualKeyword._readonly:
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._readonly;
break;
case _keywords.ContextualKeyword._abstract:
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._abstract;
break;
case _keywords.ContextualKeyword._static:
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._static;
break;
case _keywords.ContextualKeyword._public:
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._public;
break;
case _keywords.ContextualKeyword._private:
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._private;
break;
case _keywords.ContextualKeyword._protected:
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._protected;
break;
default:
break;
}
return modifier;
}
return null;
} exports.tsParseModifier = tsParseModifier;
function tsParseEntityName() {
_expression.parseIdentifier.call(void 0, );
while (_index.eat.call(void 0, _types.TokenType.dot)) {
_expression.parseIdentifier.call(void 0, );
}
}
function tsParseTypeReference() {
tsParseEntityName();
if (!_util.hasPrecedingLineBreak.call(void 0, ) && _index.match.call(void 0, _types.TokenType.lessThan)) {
tsParseTypeArguments();
}
}
function tsParseThisTypePredicate() {
_index.next.call(void 0, );
tsParseTypeAnnotation();
}
function tsParseThisTypeNode() {
_index.next.call(void 0, );
}
function tsParseTypeQuery() {
_util.expect.call(void 0, _types.TokenType._typeof);
if (_index.match.call(void 0, _types.TokenType._import)) {
tsParseImportType();
} else {
tsParseEntityName();
}
}
function tsParseImportType() {
_util.expect.call(void 0, _types.TokenType._import);
_util.expect.call(void 0, _types.TokenType.parenL);
_util.expect.call(void 0, _types.TokenType.string);
_util.expect.call(void 0, _types.TokenType.parenR);
if (_index.eat.call(void 0, _types.TokenType.dot)) {
tsParseEntityName();
}
if (_index.match.call(void 0, _types.TokenType.lessThan)) {
tsParseTypeArguments();
}
}
function tsParseTypeParameter() {
_expression.parseIdentifier.call(void 0, );
if (_index.eat.call(void 0, _types.TokenType._extends)) {
tsParseType();
}
if (_index.eat.call(void 0, _types.TokenType.eq)) {
tsParseType();
}
}
function tsTryParseTypeParameters() {
if (_index.match.call(void 0, _types.TokenType.lessThan)) {
tsParseTypeParameters();
}
} exports.tsTryParseTypeParameters = tsTryParseTypeParameters;
function tsParseTypeParameters() {
const oldIsType = _index.pushTypeContext.call(void 0, 0);
if (_index.match.call(void 0, _types.TokenType.lessThan) || _index.match.call(void 0, _types.TokenType.typeParameterStart)) {
_index.next.call(void 0, );
} else {
_util.unexpected.call(void 0, );
}
while (!_index.eat.call(void 0, _types.TokenType.greaterThan) && !_base.state.error) {
tsParseTypeParameter();
_index.eat.call(void 0, _types.TokenType.comma);
}
_index.popTypeContext.call(void 0, oldIsType);
}
// Note: In TypeScript implementation we must provide `yieldContext` and `awaitContext`,
// but here it's always false, because this is only used for types.
function tsFillSignature(returnToken) {
// Arrow fns *must* have return token (`=>`). Normal functions can omit it.
const returnTokenRequired = returnToken === _types.TokenType.arrow;
tsTryParseTypeParameters();
_util.expect.call(void 0, _types.TokenType.parenL);
tsParseBindingListForSignature(false /* isBlockScope */);
if (returnTokenRequired) {
tsParseTypeOrTypePredicateAnnotation(returnToken);
} else if (_index.match.call(void 0, returnToken)) {
tsParseTypeOrTypePredicateAnnotation(returnToken);
}
}
function tsParseBindingListForSignature(isBlockScope) {
_lval.parseBindingList.call(void 0, _types.TokenType.parenR, isBlockScope);
}
function tsParseTypeMemberSemicolon() {
if (!_index.eat.call(void 0, _types.TokenType.comma)) {
_util.semicolon.call(void 0, );
}
}
var SignatureMemberKind; (function (SignatureMemberKind) {
const TSCallSignatureDeclaration = 0; SignatureMemberKind[SignatureMemberKind["TSCallSignatureDeclaration"] = TSCallSignatureDeclaration] = "TSCallSignatureDeclaration";
const TSConstructSignatureDeclaration = TSCallSignatureDeclaration + 1; SignatureMemberKind[SignatureMemberKind["TSConstructSignatureDeclaration"] = TSConstructSignatureDeclaration] = "TSConstructSignatureDeclaration";
})(SignatureMemberKind || (SignatureMemberKind = {}));
function tsParseSignatureMember(kind) {
if (kind === SignatureMemberKind.TSConstructSignatureDeclaration) {
_util.expect.call(void 0, _types.TokenType._new);
}
tsFillSignature(_types.TokenType.colon);
tsParseTypeMemberSemicolon();
}
function tsIsUnambiguouslyIndexSignature() {
const snapshot = _base.state.snapshot();
_index.next.call(void 0, ); // Skip '{'
const isIndexSignature = _index.eat.call(void 0, _types.TokenType.name) && _index.match.call(void 0, _types.TokenType.colon);
_base.state.restoreFromSnapshot(snapshot);
return isIndexSignature;
}
function tsTryParseIndexSignature() {
if (!(_index.match.call(void 0, _types.TokenType.bracketL) && tsIsUnambiguouslyIndexSignature())) {
return false;
}
const oldIsType = _index.pushTypeContext.call(void 0, 0);
_util.expect.call(void 0, _types.TokenType.bracketL);
_expression.parseIdentifier.call(void 0, );
tsParseTypeAnnotation();
_util.expect.call(void 0, _types.TokenType.bracketR);
tsTryParseTypeAnnotation();
tsParseTypeMemberSemicolon();
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
function tsParsePropertyOrMethodSignature(isReadonly) {
_expression.parsePropertyName.call(void 0, -1 /* Types don't need context IDs. */);
_index.eat.call(void 0, _types.TokenType.question);
if (!isReadonly && (_index.match.call(void 0, _types.TokenType.parenL) || _index.match.call(void 0, _types.TokenType.lessThan))) {
tsFillSignature(_types.TokenType.colon);
tsParseTypeMemberSemicolon();
} else {
tsTryParseTypeAnnotation();
tsParseTypeMemberSemicolon();
}
}
function tsParseTypeMember() {
if (_index.match.call(void 0, _types.TokenType.parenL) || _index.match.call(void 0, _types.TokenType.lessThan)) {
tsParseSignatureMember(SignatureMemberKind.TSCallSignatureDeclaration);
return;
}
if (_index.match.call(void 0, _types.TokenType._new) && tsIsStartOfConstructSignature()) {
tsParseSignatureMember(SignatureMemberKind.TSConstructSignatureDeclaration);
return;
}
const readonly = !!tsParseModifier([_keywords.ContextualKeyword._readonly]);
const found = tsTryParseIndexSignature();
if (found) {
return;
}
tsParsePropertyOrMethodSignature(readonly);
}
function tsIsStartOfConstructSignature() {
const lookahead = _index.lookaheadType.call(void 0, );
return lookahead === _types.TokenType.parenL || lookahead === _types.TokenType.lessThan;
}
function tsParseTypeLiteral() {
tsParseObjectTypeMembers();
}
function tsParseObjectTypeMembers() {
_util.expect.call(void 0, _types.TokenType.braceL);
while (!_index.eat.call(void 0, _types.TokenType.braceR) && !_base.state.error) {
tsParseTypeMember();
}
}
function tsLookaheadIsStartOfMappedType() {
const snapshot = _base.state.snapshot();
const isStartOfMappedType = tsIsStartOfMappedType();
_base.state.restoreFromSnapshot(snapshot);
return isStartOfMappedType;
}
function tsIsStartOfMappedType() {
_index.next.call(void 0, );
if (_index.eat.call(void 0, _types.TokenType.plus) || _index.eat.call(void 0, _types.TokenType.minus)) {
return _util.isContextual.call(void 0, _keywords.ContextualKeyword._readonly);
}
if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._readonly)) {
_index.next.call(void 0, );
}
if (!_index.match.call(void 0, _types.TokenType.bracketL)) {
return false;
}
_index.next.call(void 0, );
if (!tsIsIdentifier()) {
return false;
}
_index.next.call(void 0, );
return _index.match.call(void 0, _types.TokenType._in);
}
function tsParseMappedTypeParameter() {
_expression.parseIdentifier.call(void 0, );
_util.expect.call(void 0, _types.TokenType._in);
tsParseType();
}
function tsParseMappedType() {
_util.expect.call(void 0, _types.TokenType.braceL);
if (_index.match.call(void 0, _types.TokenType.plus) || _index.match.call(void 0, _types.TokenType.minus)) {
_index.next.call(void 0, );
_util.expectContextual.call(void 0, _keywords.ContextualKeyword._readonly);
} else {
_util.eatContextual.call(void 0, _keywords.ContextualKeyword._readonly);
}
_util.expect.call(void 0, _types.TokenType.bracketL);
tsParseMappedTypeParameter();
_util.expect.call(void 0, _types.TokenType.bracketR);
if (_index.match.call(void 0, _types.TokenType.plus) || _index.match.call(void 0, _types.TokenType.minus)) {
_index.next.call(void 0, );
_util.expect.call(void 0, _types.TokenType.question);
} else {
_index.eat.call(void 0, _types.TokenType.question);
}
tsTryParseType();
_util.semicolon.call(void 0, );
_util.expect.call(void 0, _types.TokenType.braceR);
}
function tsParseTupleType() {
_util.expect.call(void 0, _types.TokenType.bracketL);
while (!_index.eat.call(void 0, _types.TokenType.bracketR) && !_base.state.error) {
tsParseTupleElementType();
_index.eat.call(void 0, _types.TokenType.comma);
}
}
function tsParseTupleElementType() {
// parses `...TsType[]`
if (_index.eat.call(void 0, _types.TokenType.ellipsis)) {
tsParseType();
return;
}
// parses `TsType?`
tsParseType();
_index.eat.call(void 0, _types.TokenType.question);
}
function tsParseParenthesizedType() {
_util.expect.call(void 0, _types.TokenType.parenL);
tsParseType();
_util.expect.call(void 0, _types.TokenType.parenR);
}
var FunctionType; (function (FunctionType) {
const TSFunctionType = 0; FunctionType[FunctionType["TSFunctionType"] = TSFunctionType] = "TSFunctionType";
const TSConstructorType = TSFunctionType + 1; FunctionType[FunctionType["TSConstructorType"] = TSConstructorType] = "TSConstructorType";
})(FunctionType || (FunctionType = {}));
function tsParseFunctionOrConstructorType(type) {
if (type === FunctionType.TSConstructorType) {
_util.expect.call(void 0, _types.TokenType._new);
}
tsFillSignature(_types.TokenType.arrow);
}
function tsParseNonArrayType() {
switch (_base.state.type) {
case _types.TokenType.name:
tsParseTypeReference();
return;
case _types.TokenType._void:
case _types.TokenType._null:
_index.next.call(void 0, );
return;
case _types.TokenType.string:
case _types.TokenType.num:
case _types.TokenType._true:
case _types.TokenType._false:
_expression.parseLiteral.call(void 0, );
return;
case _types.TokenType.minus:
_index.next.call(void 0, );
_expression.parseLiteral.call(void 0, );
return;
case _types.TokenType._this: {
tsParseThisTypeNode();
if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._is) && !_util.hasPrecedingLineBreak.call(void 0, )) {
tsParseThisTypePredicate();
}
return;
}
case _types.TokenType._typeof:
tsParseTypeQuery();
return;
case _types.TokenType._import:
tsParseImportType();
return;
case _types.TokenType.braceL:
if (tsLookaheadIsStartOfMappedType()) {
tsParseMappedType();
} else {
tsParseTypeLiteral();
}
return;
case _types.TokenType.bracketL:
tsParseTupleType();
return;
case _types.TokenType.parenL:
tsParseParenthesizedType();
return;
default:
break;
}
_util.unexpected.call(void 0, );
}
function tsParseArrayTypeOrHigher() {
tsParseNonArrayType();
while (!_util.hasPrecedingLineBreak.call(void 0, ) && _index.eat.call(void 0, _types.TokenType.bracketL)) {
if (!_index.eat.call(void 0, _types.TokenType.bracketR)) {
// If we hit ] immediately, this is an array type, otherwise it's an indexed access type.
tsParseType();
_util.expect.call(void 0, _types.TokenType.bracketR);
}
}
}
function tsParseInferType() {
_util.expectContextual.call(void 0, _keywords.ContextualKeyword._infer);
_expression.parseIdentifier.call(void 0, );
}
function tsParseTypeOperatorOrHigher() {
if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._keyof) || _util.isContextual.call(void 0, _keywords.ContextualKeyword._unique)) {
_index.next.call(void 0, );
tsParseTypeOperatorOrHigher();
} else if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._infer)) {
tsParseInferType();
} else {
tsParseArrayTypeOrHigher();
}
}
function tsParseIntersectionTypeOrHigher() {
_index.eat.call(void 0, _types.TokenType.bitwiseAND);
tsParseTypeOperatorOrHigher();
if (_index.match.call(void 0, _types.TokenType.bitwiseAND)) {
while (_index.eat.call(void 0, _types.TokenType.bitwiseAND)) {
tsParseTypeOperatorOrHigher();
}
}
}
function tsParseUnionTypeOrHigher() {
_index.eat.call(void 0, _types.TokenType.bitwiseOR);
tsParseIntersectionTypeOrHigher();
if (_index.match.call(void 0, _types.TokenType.bitwiseOR)) {
while (_index.eat.call(void 0, _types.TokenType.bitwiseOR)) {
tsParseIntersectionTypeOrHigher();
}
}
}
function tsIsStartOfFunctionType() {
if (_index.match.call(void 0, _types.TokenType.lessThan)) {
return true;
}
return _index.match.call(void 0, _types.TokenType.parenL) && tsLookaheadIsUnambiguouslyStartOfFunctionType();
}
function tsSkipParameterStart() {
if (_index.match.call(void 0, _types.TokenType.name) || _index.match.call(void 0, _types.TokenType._this)) {
_index.next.call(void 0, );
return true;
}
// If this is a possible array/object destructure, walk to the matching bracket/brace.
// The next token after will tell us definitively whether this is a function param.
if (_index.match.call(void 0, _types.TokenType.braceL) || _index.match.call(void 0, _types.TokenType.bracketL)) {
let depth = 1;
_index.next.call(void 0, );
while (depth > 0 && !_base.state.error) {
if (_index.match.call(void 0, _types.TokenType.braceL) || _index.match.call(void 0, _types.TokenType.bracketL)) {
depth++;
} else if (_index.match.call(void 0, _types.TokenType.braceR) || _index.match.call(void 0, _types.TokenType.bracketR)) {
depth--;
}
_index.next.call(void 0, );
}
return true;
}
return false;
}
function tsLookaheadIsUnambiguouslyStartOfFunctionType() {
const snapshot = _base.state.snapshot();
const isUnambiguouslyStartOfFunctionType = tsIsUnambiguouslyStartOfFunctionType();
_base.state.restoreFromSnapshot(snapshot);
return isUnambiguouslyStartOfFunctionType;
}
function tsIsUnambiguouslyStartOfFunctionType() {
_index.next.call(void 0, );
if (_index.match.call(void 0, _types.TokenType.parenR) || _index.match.call(void 0, _types.TokenType.ellipsis)) {
// ( )
// ( ...
return true;
}
if (tsSkipParameterStart()) {
if (_index.match.call(void 0, _types.TokenType.colon) || _index.match.call(void 0, _types.TokenType.comma) || _index.match.call(void 0, _types.TokenType.question) || _index.match.call(void 0, _types.TokenType.eq)) {
// ( xxx :
// ( xxx ,
// ( xxx ?
// ( xxx =
return true;
}
if (_index.match.call(void 0, _types.TokenType.parenR)) {
_index.next.call(void 0, );
if (_index.match.call(void 0, _types.TokenType.arrow)) {
// ( xxx ) =>
return true;
}
}
}
return false;
}
function tsParseTypeOrTypePredicateAnnotation(returnToken) {
const oldIsType = _index.pushTypeContext.call(void 0, 0);
_util.expect.call(void 0, returnToken);
tsParseTypePredicatePrefix();
// Regardless of whether we found an "is" token, there's now just a regular type in front of
// us.
tsParseType();
_index.popTypeContext.call(void 0, oldIsType);
}
function tsTryParseTypeOrTypePredicateAnnotation() {
if (_index.match.call(void 0, _types.TokenType.colon)) {
tsParseTypeOrTypePredicateAnnotation(_types.TokenType.colon);
}
}
function tsTryParseTypeAnnotation() {
if (_index.match.call(void 0, _types.TokenType.colon)) {
tsParseTypeAnnotation();
}
} exports.tsTryParseTypeAnnotation = tsTryParseTypeAnnotation;
function tsTryParseType() {
if (_index.eat.call(void 0, _types.TokenType.colon)) {
tsParseType();
}
}
function tsParseTypePredicatePrefix() {
const snapshot = _base.state.snapshot();
_expression.parseIdentifier.call(void 0, );
if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._is) && !_util.hasPrecedingLineBreak.call(void 0, )) {
_index.next.call(void 0, );
} else {
_base.state.restoreFromSnapshot(snapshot);
}
}
function tsParseTypeAnnotation() {
const oldIsType = _index.pushTypeContext.call(void 0, 0);
_util.expect.call(void 0, _types.TokenType.colon);
tsParseType();
_index.popTypeContext.call(void 0, oldIsType);
} exports.tsParseTypeAnnotation = tsParseTypeAnnotation;
function tsParseType() {
tsParseNonConditionalType();
if (_util.hasPrecedingLineBreak.call(void 0, ) || !_index.eat.call(void 0, _types.TokenType._extends)) {
return;
}
// extends type
tsParseNonConditionalType();
_util.expect.call(void 0, _types.TokenType.question);
// true type
tsParseType();
_util.expect.call(void 0, _types.TokenType.colon);
// false type
tsParseType();
} exports.tsParseType = tsParseType;
function tsParseNonConditionalType() {
if (tsIsStartOfFunctionType()) {
tsParseFunctionOrConstructorType(FunctionType.TSFunctionType);
return;
}
if (_index.match.call(void 0, _types.TokenType._new)) {
// As in `new () => Date`
tsParseFunctionOrConstructorType(FunctionType.TSConstructorType);
return;
}
tsParseUnionTypeOrHigher();
} exports.tsParseNonConditionalType = tsParseNonConditionalType;
function tsParseTypeAssertion() {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
tsParseType();
_util.expect.call(void 0, _types.TokenType.greaterThan);
_index.popTypeContext.call(void 0, oldIsType);
_expression.parseMaybeUnary.call(void 0, );
} exports.tsParseTypeAssertion = tsParseTypeAssertion;
function tsTryParseJSXTypeArgument() {
if (_index.eat.call(void 0, _types.TokenType.jsxTagStart)) {
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType.typeParameterStart;
const oldIsType = _index.pushTypeContext.call(void 0, 1);
while (!_index.match.call(void 0, _types.TokenType.greaterThan) && !_base.state.error) {
tsParseType();
_index.eat.call(void 0, _types.TokenType.comma);
}
// Process >, but the one after needs to be parsed JSX-style.
_jsx.nextJSXTagToken.call(void 0, );
_index.popTypeContext.call(void 0, oldIsType);
}
} exports.tsTryParseJSXTypeArgument = tsTryParseJSXTypeArgument;
function tsParseHeritageClause() {
while (!_index.match.call(void 0, _types.TokenType.braceL) && !_base.state.error) {
tsParseExpressionWithTypeArguments();
_index.eat.call(void 0, _types.TokenType.comma);
}
}
function tsParseExpressionWithTypeArguments() {
// Note: TS uses parseLeftHandSideExpressionOrHigher,
// then has grammar errors later if it's not an EntityName.
tsParseEntityName();
if (_index.match.call(void 0, _types.TokenType.lessThan)) {
tsParseTypeArguments();
}
}
function tsParseInterfaceDeclaration() {
_expression.parseIdentifier.call(void 0, );
tsTryParseTypeParameters();
if (_index.eat.call(void 0, _types.TokenType._extends)) {
tsParseHeritageClause();
}
tsParseObjectTypeMembers();
}
function tsParseTypeAliasDeclaration() {
_expression.parseIdentifier.call(void 0, );
tsTryParseTypeParameters();
_util.expect.call(void 0, _types.TokenType.eq);
tsParseType();
_util.semicolon.call(void 0, );
}
function tsParseEnumMember() {
// Computed property names are grammar errors in an enum, so accept just string literal or identifier.
if (_index.match.call(void 0, _types.TokenType.string)) {
_expression.parseLiteral.call(void 0, );
} else {
_expression.parseIdentifier.call(void 0, );
}
if (_index.eat.call(void 0, _types.TokenType.eq)) {
const eqIndex = _base.state.tokens.length - 1;
_expression.parseMaybeAssign.call(void 0, );
_base.state.tokens[eqIndex].rhsEndIndex = _base.state.tokens.length;
}
}
function tsParseEnumDeclaration() {
_expression.parseIdentifier.call(void 0, );
_util.expect.call(void 0, _types.TokenType.braceL);
while (!_index.eat.call(void 0, _types.TokenType.braceR) && !_base.state.error) {
tsParseEnumMember();
_index.eat.call(void 0, _types.TokenType.comma);
}
}
function tsParseModuleBlock() {
_util.expect.call(void 0, _types.TokenType.braceL);
_statement.parseBlockBody.call(void 0, /* end */ _types.TokenType.braceR);
}
function tsParseModuleOrNamespaceDeclaration() {
_expression.parseIdentifier.call(void 0, );
if (_index.eat.call(void 0, _types.TokenType.dot)) {
tsParseModuleOrNamespaceDeclaration();
} else {
tsParseModuleBlock();
}
}
function tsParseAmbientExternalModuleDeclaration() {
if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._global)) {
_expression.parseIdentifier.call(void 0, );
} else if (_index.match.call(void 0, _types.TokenType.string)) {
_expression.parseExprAtom.call(void 0, );
} else {
_util.unexpected.call(void 0, );
}
if (_index.match.call(void 0, _types.TokenType.braceL)) {
tsParseModuleBlock();
} else {
_util.semicolon.call(void 0, );
}
}
function tsParseImportEqualsDeclaration() {
_expression.parseIdentifier.call(void 0, );
_util.expect.call(void 0, _types.TokenType.eq);
tsParseModuleReference();
_util.semicolon.call(void 0, );
} exports.tsParseImportEqualsDeclaration = tsParseImportEqualsDeclaration;
function tsIsExternalModuleReference() {
return _util.isContextual.call(void 0, _keywords.ContextualKeyword._require) && _index.lookaheadType.call(void 0, ) === _types.TokenType.parenL;
}
function tsParseModuleReference() {
if (tsIsExternalModuleReference()) {
tsParseExternalModuleReference();
} else {
tsParseEntityName();
}
}
function tsParseExternalModuleReference() {
_util.expectContextual.call(void 0, _keywords.ContextualKeyword._require);
_util.expect.call(void 0, _types.TokenType.parenL);
if (!_index.match.call(void 0, _types.TokenType.string)) {
_util.unexpected.call(void 0, );
}
_expression.parseLiteral.call(void 0, );
_util.expect.call(void 0, _types.TokenType.parenR);
}
// Utilities
// Returns true if a statement matched.
function tsTryParseDeclare() {
switch (_base.state.type) {
case _types.TokenType._function: {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
_index.next.call(void 0, );
// We don't need to precisely get the function start here, since it's only used to mark
// the function as a type if it's bodiless, and it's already a type here.
const functionStart = _base.state.start;
_statement.parseFunction.call(void 0, functionStart, /* isStatement */ true);
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
case _types.TokenType._class: {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
_statement.parseClass.call(void 0, /* isStatement */ true, /* optionalId */ false);
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
case _types.TokenType._const: {
if (_index.match.call(void 0, _types.TokenType._const) && _util.isLookaheadContextual.call(void 0, _keywords.ContextualKeyword._enum)) {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
// `const enum = 0;` not allowed because "enum" is a strict mode reserved word.
_util.expect.call(void 0, _types.TokenType._const);
_util.expectContextual.call(void 0, _keywords.ContextualKeyword._enum);
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._enum;
tsParseEnumDeclaration();
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
}
// falls through
case _types.TokenType._var:
case _types.TokenType._let: {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
_statement.parseVarStatement.call(void 0, _base.state.type);
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
case _types.TokenType.name: {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
const contextualKeyword = _base.state.contextualKeyword;
let matched = false;
if (contextualKeyword === _keywords.ContextualKeyword._global) {
tsParseAmbientExternalModuleDeclaration();
matched = true;
} else {
matched = tsParseDeclaration(contextualKeyword, /* isBeforeToken */ true);
}
_index.popTypeContext.call(void 0, oldIsType);
return matched;
}
default:
return false;
}
}
// Note: this won't be called unless the keyword is allowed in `shouldParseExportDeclaration`.
// Returns true if it matched a declaration.
function tsTryParseExportDeclaration() {
return tsParseDeclaration(_base.state.contextualKeyword, /* isBeforeToken */ true);
}
// Returns true if it matched a statement.
function tsParseExpressionStatement(contextualKeyword) {
switch (contextualKeyword) {
case _keywords.ContextualKeyword._declare: {
const declareTokenIndex = _base.state.tokens.length - 1;
const matched = tsTryParseDeclare();
if (matched) {
_base.state.tokens[declareTokenIndex].type = _types.TokenType._declare;
return true;
}
break;
}
case _keywords.ContextualKeyword._global:
// `global { }` (with no `declare`) may appear inside an ambient module declaration.
// Would like to use tsParseAmbientExternalModuleDeclaration here, but already ran past "global".
if (_index.match.call(void 0, _types.TokenType.braceL)) {
tsParseModuleBlock();
return true;
}
break;
default:
return tsParseDeclaration(contextualKeyword, /* isBeforeToken */ false);
}
return false;
}
// Common to tsTryParseDeclare, tsTryParseExportDeclaration, and tsParseExpressionStatement.
// Returns true if it matched a declaration.
function tsParseDeclaration(contextualKeyword, isBeforeToken) {
switch (contextualKeyword) {
case _keywords.ContextualKeyword._abstract:
if (isBeforeToken || _index.match.call(void 0, _types.TokenType._class)) {
if (isBeforeToken) _index.next.call(void 0, );
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._abstract;
_statement.parseClass.call(void 0, /* isStatement */ true, /* optionalId */ false);
return true;
}
break;
case _keywords.ContextualKeyword._enum:
if (isBeforeToken || _index.match.call(void 0, _types.TokenType.name)) {
if (isBeforeToken) _index.next.call(void 0, );
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._enum;
tsParseEnumDeclaration();
return true;
}
break;
case _keywords.ContextualKeyword._interface:
if (isBeforeToken || _index.match.call(void 0, _types.TokenType.name)) {
// `next` is true in "export" and "declare" contexts, so we want to remove that token
// as well.
const oldIsType = _index.pushTypeContext.call(void 0, 1);
if (isBeforeToken) _index.next.call(void 0, );
tsParseInterfaceDeclaration();
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
break;
case _keywords.ContextualKeyword._module:
if (isBeforeToken) _index.next.call(void 0, );
if (_index.match.call(void 0, _types.TokenType.string)) {
const oldIsType = _index.pushTypeContext.call(void 0, isBeforeToken ? 2 : 1);
tsParseAmbientExternalModuleDeclaration();
_index.popTypeContext.call(void 0, oldIsType);
return true;
} else if (_index.match.call(void 0, _types.TokenType.name)) {
const oldIsType = _index.pushTypeContext.call(void 0, isBeforeToken ? 2 : 1);
tsParseModuleOrNamespaceDeclaration();
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
break;
case _keywords.ContextualKeyword._namespace:
if (isBeforeToken || _index.match.call(void 0, _types.TokenType.name)) {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
if (isBeforeToken) _index.next.call(void 0, );
tsParseModuleOrNamespaceDeclaration();
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
break;
case _keywords.ContextualKeyword._type:
if (isBeforeToken || _index.match.call(void 0, _types.TokenType.name)) {
const oldIsType = _index.pushTypeContext.call(void 0, 1);
if (isBeforeToken) _index.next.call(void 0, );
tsParseTypeAliasDeclaration();
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
break;
default:
break;
}
return false;
}
// Returns true if there was a generic async arrow function.
function tsTryParseGenericAsyncArrowFunction() {
const snapshot = _base.state.snapshot();
tsParseTypeParameters();
_statement.parseFunctionParams.call(void 0, );
tsTryParseTypeOrTypePredicateAnnotation();
_util.expect.call(void 0, _types.TokenType.arrow);
if (_base.state.error) {
_base.state.restoreFromSnapshot(snapshot);
return false;
}
// We don't need to be precise about the function start since it's only used if this is a
// bodiless function, which isn't valid here.
const functionStart = _base.state.start;
_expression.parseFunctionBody.call(void 0, functionStart, false /* isGenerator */, true);
return true;
}
function tsParseTypeArguments() {
const oldIsType = _index.pushTypeContext.call(void 0, 0);
_util.expect.call(void 0, _types.TokenType.lessThan);
while (!_index.eat.call(void 0, _types.TokenType.greaterThan) && !_base.state.error) {
tsParseType();
_index.eat.call(void 0, _types.TokenType.comma);
}
_index.popTypeContext.call(void 0, oldIsType);
}
function tsIsDeclarationStart() {
if (_index.match.call(void 0, _types.TokenType.name)) {
switch (_base.state.contextualKeyword) {
case _keywords.ContextualKeyword._abstract:
case _keywords.ContextualKeyword._declare:
case _keywords.ContextualKeyword._enum:
case _keywords.ContextualKeyword._interface:
case _keywords.ContextualKeyword._module:
case _keywords.ContextualKeyword._namespace:
case _keywords.ContextualKeyword._type:
return true;
default:
break;
}
}
return false;
} exports.tsIsDeclarationStart = tsIsDeclarationStart;
// ======================================================
// OVERRIDES
// ======================================================
function tsParseFunctionBodyAndFinish(
functionStart,
isGenerator,
allowExpressionBody = false,
funcContextId,
) {
// For arrow functions, `parseArrow` handles the return type itself.
if (!allowExpressionBody && _index.match.call(void 0, _types.TokenType.colon)) {
tsParseTypeOrTypePredicateAnnotation(_types.TokenType.colon);
}
// The original code checked the node type to make sure this function type allows a missing
// body, but we skip that to avoid sending around the node type. We instead just use the
// allowExpressionBody boolean to make sure it's not an arrow function.
if (!allowExpressionBody && !_index.match.call(void 0, _types.TokenType.braceL) && _util.isLineTerminator.call(void 0, )) {
// Retroactively mark the function declaration as a type.
let i = _base.state.tokens.length - 1;
while (
i >= 0 &&
(_base.state.tokens[i].start >= functionStart ||
_base.state.tokens[i].type === _types.TokenType._default ||
_base.state.tokens[i].type === _types.TokenType._export)
) {
_base.state.tokens[i].isType = true;
i--;
}
return;
}
_expression.parseFunctionBody.call(void 0, functionStart, isGenerator, allowExpressionBody, funcContextId);
} exports.tsParseFunctionBodyAndFinish = tsParseFunctionBodyAndFinish;
function tsParseSubscript(startPos, noCalls, stopState) {
if (!_util.hasPrecedingLineBreak.call(void 0, ) && _index.eat.call(void 0, _types.TokenType.bang)) {
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType.nonNullAssertion;
return;
}
if (_index.match.call(void 0, _types.TokenType.lessThan)) {
// There are number of things we are going to "maybe" parse, like type arguments on
// tagged template expressions. If any of them fail, walk it back and continue.
const snapshot = _base.state.snapshot();
if (!noCalls && _expression.atPossibleAsync.call(void 0, )) {
// Almost certainly this is a generic async function `async <T>() => ...
// But it might be a call with a type argument `async<T>();`
const asyncArrowFn = tsTryParseGenericAsyncArrowFunction();
if (asyncArrowFn) {
return;
}
}
tsParseTypeArguments();
if (!noCalls && _index.eat.call(void 0, _types.TokenType.parenL)) {
_expression.parseCallExpressionArguments.call(void 0, );
} else if (_index.match.call(void 0, _types.TokenType.backQuote)) {
// Tagged template with a type argument.
_expression.parseTemplate.call(void 0, );
}
if (_base.state.error) {
_base.state.restoreFromSnapshot(snapshot);
} else {
return;
}
}
_expression.baseParseSubscript.call(void 0, startPos, noCalls, stopState);
} exports.tsParseSubscript = tsParseSubscript;
function tsStartParseNewArguments() {
if (_index.match.call(void 0, _types.TokenType.lessThan)) {
// 99% certain this is `new C<T>();`. But may be `new C < T;`, which is also legal.
const snapshot = _base.state.snapshot();
_base.state.type = _types.TokenType.typeParameterStart;
tsParseTypeArguments();
if (!_index.match.call(void 0, _types.TokenType.parenL)) {
_util.unexpected.call(void 0, );
}
if (_base.state.error) {
_base.state.restoreFromSnapshot(snapshot);
}
}
} exports.tsStartParseNewArguments = tsStartParseNewArguments;
function tsTryParseExport() {
if (_index.match.call(void 0, _types.TokenType._import)) {
// `export import A = B;`
_util.expect.call(void 0, _types.TokenType._import);
tsParseImportEqualsDeclaration();
return true;
} else if (_index.eat.call(void 0, _types.TokenType.eq)) {
// `export = x;`
_expression.parseExpression.call(void 0, );
_util.semicolon.call(void 0, );
return true;
} else if (_util.eatContextual.call(void 0, _keywords.ContextualKeyword._as)) {
// `export as namespace A;`
// See `parseNamespaceExportDeclaration` in TypeScript's own parser
_util.expectContextual.call(void 0, _keywords.ContextualKeyword._namespace);
_expression.parseIdentifier.call(void 0, );
_util.semicolon.call(void 0, );
return true;
} else {
return false;
}
} exports.tsTryParseExport = tsTryParseExport;
function tsTryParseExportDefaultExpression() {
if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._abstract) && _index.lookaheadType.call(void 0, ) === _types.TokenType._class) {
_base.state.type = _types.TokenType._abstract;
_index.next.call(void 0, ); // Skip "abstract"
_statement.parseClass.call(void 0, true, true);
return true;
}
if (_util.isContextual.call(void 0, _keywords.ContextualKeyword._interface)) {
// Make sure "export default" are considered type tokens so the whole thing is removed.
const oldIsType = _index.pushTypeContext.call(void 0, 2);
tsParseDeclaration(_keywords.ContextualKeyword._interface, true);
_index.popTypeContext.call(void 0, oldIsType);
return true;
}
return false;
} exports.tsTryParseExportDefaultExpression = tsTryParseExportDefaultExpression;
function tsTryParseStatementContent() {
if (_base.state.type === _types.TokenType._const) {
const ahead = _index.lookaheadTypeAndKeyword.call(void 0, );
if (ahead.type === _types.TokenType.name && ahead.contextualKeyword === _keywords.ContextualKeyword._enum) {
_util.expect.call(void 0, _types.TokenType._const);
_util.expectContextual.call(void 0, _keywords.ContextualKeyword._enum);
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._enum;
tsParseEnumDeclaration();
return true;
}
}
return false;
} exports.tsTryParseStatementContent = tsTryParseStatementContent;
function tsParseAccessModifier() {
tsParseModifier([
_keywords.ContextualKeyword._public,
_keywords.ContextualKeyword._protected,
_keywords.ContextualKeyword._private,
]);
} exports.tsParseAccessModifier = tsParseAccessModifier;
function tsTryParseClassMemberWithIsStatic(
isStatic,
classContextId,
) {
let isAbstract = false;
let isReadonly = false;
const mod = tsParseModifier([_keywords.ContextualKeyword._abstract, _keywords.ContextualKeyword._readonly]);
switch (mod) {
case _keywords.ContextualKeyword._readonly:
isReadonly = true;
isAbstract = !!tsParseModifier([_keywords.ContextualKeyword._abstract]);
break;
case _keywords.ContextualKeyword._abstract:
isAbstract = true;
isReadonly = !!tsParseModifier([_keywords.ContextualKeyword._readonly]);
break;
default:
break;
}
// We no longer check for public/private/etc, but tsTryParseIndexSignature should just return
// false in that case for valid code.
if (!isAbstract && !isStatic) {
const found = tsTryParseIndexSignature();
if (found) {
return true;
}
}
if (isReadonly) {
// Must be a property (if not an index signature).
_statement.parseClassPropertyName.call(void 0, classContextId);
_statement.parsePostMemberNameModifiers.call(void 0, );
_statement.parseClassProperty.call(void 0, );
return true;
}
return false;
} exports.tsTryParseClassMemberWithIsStatic = tsTryParseClassMemberWithIsStatic;
// Note: The reason we do this in `parseIdentifierStatement` and not `parseStatement`
// is that e.g. `type()` is valid JS, so we must try parsing that first.
// If it's really a type, we will parse `type` as the statement, and can correct it here
// by parsing the rest.
function tsParseIdentifierStatement(contextualKeyword) {
const matched = tsParseExpressionStatement(contextualKeyword);
if (!matched) {
_util.semicolon.call(void 0, );
}
} exports.tsParseIdentifierStatement = tsParseIdentifierStatement;
function tsParseExportDeclaration() {
// "export declare" is equivalent to just "export".
const isDeclare = _util.eatContextual.call(void 0, _keywords.ContextualKeyword._declare);
if (isDeclare) {
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._declare;
}
let matchedDeclaration = false;
if (_index.match.call(void 0, _types.TokenType.name)) {
if (isDeclare) {
const oldIsType = _index.pushTypeContext.call(void 0, 2);
matchedDeclaration = tsTryParseExportDeclaration();
_index.popTypeContext.call(void 0, oldIsType);
} else {
matchedDeclaration = tsTryParseExportDeclaration();
}
}
if (!matchedDeclaration) {
if (isDeclare) {
const oldIsType = _index.pushTypeContext.call(void 0, 2);
_statement.parseStatement.call(void 0, true);
_index.popTypeContext.call(void 0, oldIsType);
} else {
_statement.parseStatement.call(void 0, true);
}
}
} exports.tsParseExportDeclaration = tsParseExportDeclaration;
function tsAfterParseClassSuper(hasSuper) {
if (hasSuper && _index.match.call(void 0, _types.TokenType.lessThan)) {
tsParseTypeArguments();
}
if (_util.eatContextual.call(void 0, _keywords.ContextualKeyword._implements)) {
_base.state.tokens[_base.state.tokens.length - 1].type = _types.TokenType._implements;
const oldIsType = _index.pushTypeContext.call(void 0, 1);
tsParseHeritageClause();
_index.popTypeContext.call(void 0, oldIsType);
}
} exports.tsAfterParseClassSuper = tsAfterParseClassSuper;
function tsStartParseObjPropValue() {
tsTryParseTypeParameters();
} exports.tsStartParseObjPropValue = tsStartParseObjPropValue;
function tsStartParseFunctionParams() {
tsTryParseTypeParameters();
} exports.tsStartParseFunctionParams = tsStartParseFunctionParams;
// `let x: number;`
function tsAfterParseVarHead() {
const oldIsType = _index.pushTypeContext.call(void 0, 0);
_index.eat.call(void 0, _types.TokenType.bang);
tsTryParseTypeAnnotation();
_index.popTypeContext.call(void 0, oldIsType);
} exports.tsAfterParseVarHead = tsAfterParseVarHead;
// parse the return type of an async arrow function - let foo = (async (): number => {});
function tsStartParseAsyncArrowFromCallExpression() {
if (_index.match.call(void 0, _types.TokenType.colon)) {
tsParseTypeAnnotation();
}
} exports.tsStartParseAsyncArrowFromCallExpression = tsStartParseAsyncArrowFromCallExpression;
// Returns true if the expression was an arrow function.
function tsParseMaybeAssign(noIn, isWithinParens) {
// Note: When the JSX plugin is on, type assertions (`<T> x`) aren't valid syntax.
if (_base.isJSXEnabled) {
return tsParseMaybeAssignWithJSX(noIn, isWithinParens);
} else {
return tsParseMaybeAssignWithoutJSX(noIn, isWithinParens);
}
} exports.tsParseMaybeAssign = tsParseMaybeAssign;
function tsParseMaybeAssignWithJSX(noIn, isWithinParens) {
if (!_index.match.call(void 0, _types.TokenType.lessThan)) {
return _expression.baseParseMaybeAssign.call(void 0, noIn, isWithinParens);
}
// Prefer to parse JSX if possible. But may be an arrow fn.
const snapshot = _base.state.snapshot();
let wasArrow = _expression.baseParseMaybeAssign.call(void 0, noIn, isWithinParens);
if (_base.state.error) {
_base.state.restoreFromSnapshot(snapshot);
} else {
return wasArrow;
}
// Otherwise, try as type-parameterized arrow function.
_base.state.type = _types.TokenType.typeParameterStart;
// This is similar to TypeScript's `tryParseParenthesizedArrowFunctionExpression`.
tsParseTypeParameters();
wasArrow = _expression.baseParseMaybeAssign.call(void 0, noIn, isWithinParens);
if (!wasArrow) {
_util.unexpected.call(void 0, );
}
return wasArrow;
} exports.tsParseMaybeAssignWithJSX = tsParseMaybeAssignWithJSX;
function tsParseMaybeAssignWithoutJSX(noIn, isWithinParens) {
if (!_index.match.call(void 0, _types.TokenType.lessThan)) {
return _expression.baseParseMaybeAssign.call(void 0, noIn, isWithinParens);
}
const snapshot = _base.state.snapshot();
// This is similar to TypeScript's `tryParseParenthesizedArrowFunctionExpression`.
tsParseTypeParameters();
const wasArrow = _expression.baseParseMaybeAssign.call(void 0, noIn, isWithinParens);
if (!wasArrow) {
_util.unexpected.call(void 0, );
}
if (_base.state.error) {
_base.state.restoreFromSnapshot(snapshot);
} else {
return wasArrow;
}
// Try parsing a type cast instead of an arrow function.
// This will start with a type assertion (via parseMaybeUnary).
// But don't directly call `tsParseTypeAssertion` because we want to handle any binary after it.
return _expression.baseParseMaybeAssign.call(void 0, noIn, isWithinParens);
} exports.tsParseMaybeAssignWithoutJSX = tsParseMaybeAssignWithoutJSX;
function tsParseArrow() {
if (_index.match.call(void 0, _types.TokenType.colon)) {
// This is different from how the TS parser does it.
// TS uses lookahead. Babylon parses it as a parenthesized expression and converts.
const snapshot = _base.state.snapshot();
tsParseTypeOrTypePredicateAnnotation(_types.TokenType.colon);
if (_util.canInsertSemicolon.call(void 0, )) _util.unexpected.call(void 0, );
if (!_index.match.call(void 0, _types.TokenType.arrow)) _util.unexpected.call(void 0, );
if (_base.state.error) {
_base.state.restoreFromSnapshot(snapshot);
}
}
return _index.eat.call(void 0, _types.TokenType.arrow);
} exports.tsParseArrow = tsParseArrow;
// Allow type annotations inside of a parameter list.
function tsParseAssignableListItemTypes() {
const oldIsType = _index.pushTypeContext.call(void 0, 0);
_index.eat.call(void 0, _types.TokenType.question);
tsTryParseTypeAnnotation();
_index.popTypeContext.call(void 0, oldIsType);
} exports.tsParseAssignableListItemTypes = tsParseAssignableListItemTypes;
function tsParseMaybeDecoratorArguments() {
if (_index.match.call(void 0, _types.TokenType.lessThan)) {
tsParseTypeArguments();
}
_statement.baseParseMaybeDecoratorArguments.call(void 0, );
} exports.tsParseMaybeDecoratorArguments = tsParseMaybeDecoratorArguments;
;