UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

975 lines 41.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // Code taken from https://github.com/patternfly/patternfly-org/blob/main/packages/ast-helpers/acorn-typescript.js // Some cases such as arrow function expressions are not properly handled const acorn_1 = require("acorn"); // Taken from https://github.com/acornjs/acorn/blob/6770c2ecbf8e01470f6c9a2f59c786f014045baf/acorn/src/whitespace.js#L4C1-L5C1 const lineBreak = /\r\n?|\n|\u2028|\u2029/; class DestructuringErrors { constructor() { this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = this.doubleProto = -1; } } const tsPredefinedType = { any: 'TSAnyKeyword', bigint: 'TSBigIntKeyword', boolean: 'TSBooleanKeyword', never: 'TSNeverKeyword', null: 'TSNullKeyword', number: 'TSNumberKeyword', object: 'TSObjectKeyword', string: 'TSStringKeyword', symbol: 'TSSymbolKeyword', undefined: 'TSUndefinedKeyword', unknown: 'TSUnknownKeyword', void: 'TSVoidKeyword' }; const tsDeclaration = { interface: 1, type: 2, enum: 4, declare: 8 }; const tsTypeOperator = { typeof: 1, keyof: 2, infer: 4 }; const tsExprMarkup = { as: 1, '!': 2 }; const tsPlugin = (BaseParser) => { return class extends BaseParser { constructor(...args) { super(...args); // Allow 'interface' this.reservedWords = /^(?:enum)$/; this.reservedWordsStrict = this.reservedWords; } finishNode(node, type) { if (type.startsWith('TS')) { // Hack to not need acorn-walk to detect TS this.options.sourceType = 'ts'; } return this.finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc); } computeLocByOffset(offset) { // If `locations` option is off, do nothing for saving performance. if (this.options.locations) { return (0, acorn_1.getLineInfo)(this.input, offset); } else { return; } } startNodeAtNode(node) { return this.startNodeAt(node.start, this.computeLocByOffset(node.start)); } tsPreparePreview() { const { pos, curLine, type, value, end, start, endLoc, startLoc, scopeStack, lastTokStartLoc, lastTokEndLoc, lastTokEnd, lastTokStart, context } = this; return () => { this.pos = pos; this.curLine = curLine; this.type = type; this.value = value; this.end = end; this.start = start; this.endLoc = endLoc; this.startLoc = startLoc; this.scopeStack = scopeStack; this.lastTokStartLoc = lastTokStartLoc; this.lastTokEndLoc = lastTokEndLoc; this.lastTokEnd = lastTokEnd; this.lastTokStart = lastTokStart; this.context = context; }; } _isStartOfTypeParameters() { return this.value && this.value.charCodeAt(0) === 60; // < } _isEndOfTypeParameters() { return this.value && this.value.charCodeAt(0) === 62; // > } _hasPrecedingLineBreak() { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); } // Studied from Babel parseExpressionStatement(node, expr) { return expr.type === 'Identifier' ? this._parseTSDeclaration(node, expr) : super.parseExpressionStatement(node, expr); } parseBindingAtom() { const node = super.parseBindingAtom(); if (this.eat(acorn_1.tokTypes.colon)) { node.typeAnnotation = this.parseTSTypeAnnotation(false); node.end = node.typeAnnotation.end; if (this.options.locations) { node.loc.end = node.typeAnnotation.loc.end; } } return node; } parseMaybeDefault(startPos, startLoc, left) { if (!left) { left = this.parseBindingAtom(); if (this.eat(acorn_1.tokTypes.question)) { left.optional = true; } // `parseBindingAtom` is executed, // so we need to check type annotation again. if (this.eat(acorn_1.tokTypes.colon)) { left.typeAnnotation = this.parseTSTypeAnnotation(false); left.end = left.typeAnnotation.end; if (this.options.locations) { left.loc.end = left.typeAnnotation.loc.end; } } } return super.parseMaybeDefault(startPos, startLoc, left); } parseMaybeAssign(noIn, refDestructuringErrors, afterLeftParse) { let node = super.parseMaybeAssign(noIn, refDestructuringErrors, afterLeftParse); node = this._parseMaybeTSExpression(node); return node; } parseFunctionParams(node) { node.typeParameters = this.parseMaybeTSTypeParameterDeclaration(); return super.parseFunctionParams(node); } parseFunctionBody(node, isArrowFunction) { // I know, return type doesn't belong to function body, // but this will be less hacky. if (this.eat(acorn_1.tokTypes.colon)) { node.returnType = this.parseTSTypeAnnotation(false); } super.parseFunctionBody(node, isArrowFunction); } parseParenAndDistinguishExpression(canBeArrow) { const startPos = this.start; const startLoc = this.startLoc; const allowTrailingComma = this.options.ecmaVersion >= 8; let val; if (this.options.ecmaVersion >= 6) { this.next(); const innerStartPos = this.start, innerStartLoc = this.startLoc; const exprList = []; let first = true, lastIsComma = false; const refDestructuringErrors = new DestructuringErrors(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos; let spreadStart; this.yieldPos = 0; this.awaitPos = 0; // Do not save awaitIdentPos to allow checking awaits nested in parameters while (this.type !== acorn_1.tokTypes.parenR) { if (first) { first = false; } else { this.expect(acorn_1.tokTypes.comma); } if (allowTrailingComma && this.afterTrailingComma(acorn_1.tokTypes.parenR, true)) { lastIsComma = true; break; } else if (this.type === acorn_1.tokTypes.ellipsis) { spreadStart = this.start; exprList.push(this.parseParenItem(this.parseRestBinding())); if (this.type === acorn_1.tokTypes.comma) this.raise(this.start, 'Comma is not permitted after the rest element'); break; } else { exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); } if (this.type === acorn_1.tokTypes.colon) { this.parseTSTypeAnnotation(); // Part I added } } const innerEndPos = this.start; const innerEndLoc = this.startLoc; this.expect(acorn_1.tokTypes.parenR); if (canBeArrow && !this.canInsertSemicolon()) { const branch = this._branch(); try { if (branch.parseTSTypeAnnotation() && branch.eat(acorn_1.tokTypes.arrow)) { this.parseTSTypeAnnotation(); // throw away type } } catch { } if (this.eat(acorn_1.tokTypes.arrow)) { this.checkPatternErrors(refDestructuringErrors, false); this.checkYieldAwaitInDefaultParams(); this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; return this.parseParenArrowList(startPos, startLoc, exprList); } } if (!exprList.length || lastIsComma) this.unexpected(this.lastTokStart); if (spreadStart) this.unexpected(spreadStart); this.checkExpressionErrors(refDestructuringErrors, true); this.yieldPos = oldYieldPos || this.yieldPos; this.awaitPos = oldAwaitPos || this.awaitPos; if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc); val.expressions = exprList; this.finishNodeAt(val, 'SequenceExpression', innerEndPos, innerEndLoc); } else { val = exprList[0]; } } else { val = this.parseParenExpression(); } if (this.options.preserveParens) { const par = this.startNodeAt(startPos, startLoc); par.expression = val; return this.finishNode(par, 'ParenthesizedExpression'); } else { return val; } } // Fix ambiguity between BinaryExpressions and TSCallExpressions parseSubscript(base) { const branch = this._branch(); if (this._isStartOfTypeParameters()) { // < try { // will throw if no matching > const typeParameters = branch.parseTSTypeParameterInstantiation(); if (typeParameters && branch.eat(acorn_1.tokTypes.parenL)) { // Update parser to match branch base.typeParameters = this.parseTSTypeParameterInstantiation(); } } catch { } } return super.parseSubscript.apply(this, arguments); } parseExpression() { const parenthesized = this.type === acorn_1.tokTypes.parenL, parenStart = parenthesized ? this.start : -1; let expr = super.parseExpression(); if (parenthesized) { expr.extra = { parenthesized, parenStart }; return expr; } expr = this._parseMaybeTSExpression(expr); return expr; } parseParenItem(item) { item = super.parseParenItem(item); item = this._parseMaybeTSExpression(item); return item; } parseTSTypeAnnotation(eatColon = true) { if (eatColon) { this.expect(acorn_1.tokTypes.colon); } const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); this._parseTSTypeAnnotation(node); return this.finishNode(node, 'TSTypeAnnotation'); } _parseTSType() { const node = this._parseNonConditionalType(); if (this.type === acorn_1.tokTypes._extends && !this._hasPrecedingLineBreak()) { return this.parseTSConditionalType(node); } return node; } _parseTSTypeAnnotation(node) { node.typeAnnotation = this._parseTSType(); } _parsePrimaryType() { let node; switch (this.type) { case acorn_1.tokTypes.name: node = this.value in tsPredefinedType ? this.parseTSPredefinedType() : this.parseTSTypeReference(); break; case acorn_1.tokTypes.braceL: node = this.parseTSTypeLiteral(); break; case acorn_1.tokTypes._void: case acorn_1.tokTypes._null: node = this.parseTSPredefinedType(); break; case acorn_1.tokTypes.parenL: node = this.parseTSParenthesizedType(); break; case acorn_1.tokTypes.bracketL: node = this.parseTSTupleType(); break; case acorn_1.tokTypes.num: case acorn_1.tokTypes.string: case acorn_1.tokTypes._true: case acorn_1.tokTypes._false: node = this.parseTSLiteralType(this.type); break; case acorn_1.tokTypes._import: node = this.parseTSImportType(false); break; default: return; } while (this.type === acorn_1.tokTypes.bracketL) { node = this._parseMaybeTSArrayType(node); } return node; } _parseNonConditionalType() { let node; switch (this.type) { case acorn_1.tokTypes.name: switch (tsTypeOperator[this.value]) { case tsTypeOperator.infer: node = this.parseTSInferType(); break; case tsTypeOperator.keyof: node = this.parseTSKeyofType(); break; default: node = this._parseTSUnionTypeOrIntersectionType(); } break; case acorn_1.tokTypes._new: node = this.parseTSConstructorType(); break; case acorn_1.tokTypes.parenL: const recover = this.tsPreparePreview(); const isStartOfTSFunctionType = this._isStartOfTSFunctionType(); recover(); node = isStartOfTSFunctionType ? this.parseTSFunctionType() : this.parseTSParenthesizedType(); break; case acorn_1.tokTypes.relational: node = this._isStartOfTypeParameters() ? this.parseTSFunctionType() : this.unexpected(); break; case acorn_1.tokTypes._typeof: node = this.parseTSTypeofType(); break; default: node = this._parseTSUnionTypeOrIntersectionType(); break; } return node || this.unexpected(); } _parseTSDeclaration(node, expr) { const val = tsDeclaration[expr.name]; switch (val) { case tsDeclaration.interface: if (this.type === acorn_1.tokTypes.name) { return this.parseTSInterfaceDeclaration(); } break; case tsDeclaration.type: if (this.type === acorn_1.tokTypes.name) { return this.parseTSTypeAliasDeclaration(); } break; default: break; } return super.parseExpressionStatement(node, expr); } parseTSTypeReference() { const node = this.startNode(); let typeName = this.parseIdent(); if (this.type === acorn_1.tokTypes.dot) { typeName = this.parseTSQualifiedName(typeName); } node.typeName = typeName; if (this._isStartOfTypeParameters()) { node.typeParameters = this.parseTSTypeParameterInstantiation(); } this.finishNode(node, 'TSTypeReference'); return node; } parseTSPredefinedType() { const node = this.startNode(); const keyword = this.value; this.next(); this.finishNode(node, tsPredefinedType[keyword]); return node; } parseTSLiteralType(tokType) { const node = this.startNode(); const literal = this.parseLiteral(this.value); if (tokType === acorn_1.tokTypes._true || tokType === acorn_1.tokTypes._false) { literal.value = tokType === acorn_1.tokTypes._true; } node.literal = literal; return this.finishNode(node, 'TSLiteralType'); } parseTSTupleType() { const node = this.startNode(); const elementTypes = []; this.eat(acorn_1.tokTypes.bracketL); let first = true; while (!this.eat(acorn_1.tokTypes.bracketR)) { if (first) { first = false; } else { this.expect(acorn_1.tokTypes.comma); } switch (this.type) { case acorn_1.tokTypes.name: const elem = this.parseTSTypeReference(); if (this.type === acorn_1.tokTypes.question) { elementTypes.push(this.parseTSOptionalType(elem)); } else { elementTypes.push(elem); } break; case acorn_1.tokTypes.ellipsis: elementTypes.push(this.parseTSRestType()); break; case acorn_1.tokTypes.bracketR: break; default: this.unexpected(); } } node.elementTypes = elementTypes; return this.finishNode(node, 'TSTupleType'); } parseTSOptionalType(typeRef) { const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); this.expect(acorn_1.tokTypes.question); node.typeAnnotation = typeRef; return this.finishNode(node, 'TSOptionalType'); } parseTSRestType() { const node = this.startNode(); this.expect(acorn_1.tokTypes.ellipsis); this._parseTSTypeAnnotation(node); return this.finishNode(node, 'TSRestType'); } _parseMaybeTSArrayType(prev) { const node = this.startNodeAtNode(prev); this.expect(acorn_1.tokTypes.bracketL); if (this.eat(acorn_1.tokTypes.bracketR)) { return this.parseTSArrayType(node, prev); } return this.parseTSIndexedAccessType(node, prev); } parseTSArrayType(node, elementType) { node.elementType = elementType; return this.finishNode(node, 'TSArrayType'); } parseTSIndexedAccessType(node, objectType) { node.objectType = objectType; node.indexType = this._parseTSType(); this.expect(acorn_1.tokTypes.bracketR); if (this.type === acorn_1.tokTypes.bracketL) { return this._parseMaybeTSArrayType(node); } return this.finishNode(node, 'TSIndexedAccessType'); } _isStartOfTSFunctionType() { this.nextToken(); switch (this.type) { case acorn_1.tokTypes.parenR: case acorn_1.tokTypes.ellipsis: return true; case acorn_1.tokTypes.name: case acorn_1.tokTypes._this: this.nextToken(); switch (this.type) { case acorn_1.tokTypes.colon: case acorn_1.tokTypes.comma: case acorn_1.tokTypes.question: return true; case acorn_1.tokTypes.parenR: this.nextToken(); return this.type === acorn_1.tokTypes.arrow; default: return false; } case acorn_1.tokTypes.braceL: case acorn_1.tokTypes.bracketL: { if (this.type === acorn_1.tokTypes.braceL) { this.parseObj(/* isPattern */ true); } else { this.parseBindingAtom(); } switch (this.type) { case acorn_1.tokTypes.colon: case acorn_1.tokTypes.comma: case acorn_1.tokTypes.question: return true; case acorn_1.tokTypes.parenR: this.nextToken(); return this.type === acorn_1.tokTypes.arrow; default: return false; } } default: return false; } } parseTSFunctionType() { const node = this.startNode(); const temp = Object.create(null); node.typeParameters = this.parseMaybeTSTypeParameterDeclaration(); this.parseFunctionParams(temp); node.parameters = temp.params; this.expect(acorn_1.tokTypes.arrow); node.typeAnnotation = this.parseTSTypeAnnotation(false); return this.finishNode(node, 'TSFunctionType'); } parseTSParenthesizedType() { const node = this.startNode(); this.expect(acorn_1.tokTypes.parenL); this._parseTSTypeAnnotation(node); this.expect(acorn_1.tokTypes.parenR); while (this.eat(acorn_1.tokTypes.bracketL)) { this.expect(acorn_1.tokTypes.bracketR); } return this.finishNode(node, 'TSParenthesizedType'); } parseTSUnionType(first) { const node = first ? this.startNodeAtNode(first) : this.startNode(); const types = []; if (first) types.push(first); while (this.eat(acorn_1.tokTypes.bitwiseOR)) { types.push(this._parseTSIntersectionTypeOrPrimaryType()); } if (types.length === 1) { return first; } node.types = types; return this.finishNode(node, 'TSUnionType'); } parseTSIntersectionType(first) { const node = first ? this.startNodeAtNode(first) : this.startNode(); const types = []; if (first) types.push(first); while (this.eat(acorn_1.tokTypes.bitwiseAND)) { types.push(this._parsePrimaryType()); } if (types.length === 1) { return first; } node.types = types; return this.finishNode(node, 'TSIntersectionType'); } _parseTSIntersectionTypeOrPrimaryType() { this.eat(acorn_1.tokTypes.bitwiseAND); const node = this._parsePrimaryType(); if (this.type === acorn_1.tokTypes.bitwiseAND) { return this.parseTSIntersectionType(node); } return node; } _parseTSUnionTypeOrIntersectionType() { this.eat(acorn_1.tokTypes.bitwiseOR); const node = this._parseTSIntersectionTypeOrPrimaryType(); if (this.type === acorn_1.tokTypes.bitwiseOR) { return this.parseTSUnionType(node); } return node; } parseTSConditionalType(checkType) { const node = this.startNodeAtNode(checkType); node.checkType = checkType; this.expect(acorn_1.tokTypes._extends); node.extendsType = this._parseNonConditionalType(); this.expect(acorn_1.tokTypes.question); node.trueType = this._parseNonConditionalType(); this.expect(acorn_1.tokTypes.colon); node.falseType = this._parseNonConditionalType(); return this.finishNode(node, 'TSConditionalType'); } parseTSInferType() { const node = this.startNode(); this.next(); node.typeParameter = this.parseTSTypeParameter(); return this.finishNode(node, 'TSInferType'); } parseTSKeyofType() { const node = this.startNode(); this.next(); node.typeAnnotation = this.parseTSTypeAnnotation(false); return this.finishNode(node, 'TSTypeOperator'); } parseTSTypeQuery() { const node = this.startNode(); this.next(); node.exprName = this.parseIdent(); return this.finishNode(node, 'TSTypeQuery'); } parseTSTypeofType() { const typeQuery = this.parseTSTypeQuery(); if (this.eat(acorn_1.tokTypes.bracketL)) { const node = this.startNode(); return this.parseTSIndexedAccessType(node, typeQuery); } return typeQuery; } parseTSImportType(isTypeOf) { const node = this.startNode(); node.isTypeOf = isTypeOf; this.expect(acorn_1.tokTypes._import); this.expect(acorn_1.tokTypes.parenL); node.parameter = this.parseTSLiteralType(this.type); this.expect(acorn_1.tokTypes.parenR); if (this.eat(acorn_1.tokTypes.dot)) { let qualifier = this.parseIdent(); if (this.type === acorn_1.tokTypes.dot) { qualifier = this.parseTSQualifiedName(qualifier); } node.qualifier = qualifier; } return this.finishNode(node, 'TSImportType'); } parseTSQualifiedName(left) { let node = this.startNodeAtNode(left); node.left = left; this.expect(acorn_1.tokTypes.dot); node.right = this.parseIdent(); node = this.finishNode(node, 'TSQualifiedName'); if (this.type === acorn_1.tokTypes.dot) { node = this.parseTSQualifiedName(node); } return node; } parseTSConstructorType() { const node = this.startNode(); this.expect(acorn_1.tokTypes._new); node.typeParameters = this.parseMaybeTSTypeParameterDeclaration(); this.expect(acorn_1.tokTypes.parenL); node.parameters = this.parseBindingList(acorn_1.tokTypes.parenR, false, this.options.ecmaVersion >= 8); this.expect(acorn_1.tokTypes.arrow); node.typeAnnotation = this.parseTSTypeAnnotation(false); return this.finishNode(node, 'TSConstructorType'); } parseTSConstructSignatureDeclaration() { const node = this.startNode(); this.expect(acorn_1.tokTypes._new); node.typeParameters = this.parseMaybeTSTypeParameterDeclaration(); this.expect(acorn_1.tokTypes.parenL); node.parameters = this.parseBindingList(acorn_1.tokTypes.parenR, false, this.options.ecmaVersion >= 8); if (this.eat(acorn_1.tokTypes.colon)) { node.typeAnnotation = this.parseTSTypeAnnotation(false); } return this.finishNode(node, 'TSConstructSignatureDeclaration'); } parseTSTypeLiteral() { return this._parseObjectLikeType('TSTypeLiteral', 'members'); } parseTSTypeAliasDeclaration() { const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); node.id = this.parseIdent(); node.typeParameters = this.parseMaybeTSTypeParameterDeclaration(); this.expect(acorn_1.tokTypes.eq); this._parseTSTypeAnnotation(node); this.semicolon(); return this.finishNode(node, 'TSTypeAliasDeclaration'); } parseTSInterfaceDeclaration() { const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); node.id = this.parseIdent(); node.typeParameters = this.parseMaybeTSTypeParameterDeclaration(); if (this.eat(acorn_1.tokTypes._extends)) { const heritage = []; do { heritage.push(this.parseTSExpressionWithTypeArguments()); } while (this.eat(acorn_1.tokTypes.comma)); node.heritage = heritage; } node.body = this._parseObjectLikeType('TSInterfaceBody', 'body'); this.semicolon(); return this.finishNode(node, 'TSInterfaceDeclaration'); } parseTSExpressionWithTypeArguments() { const node = this.startNode(); let expr = this.parseIdent(); if (this.eat(acorn_1.tokTypes.dot)) { expr = this.parseTSQualifiedName(expr); } node.expr = expr; if (this._isStartOfTypeParameters()) { const typeParameters = this.parseTSTypeParameterInstantiation(); node.typeParameters = typeParameters; node.end = typeParameters.end; if (this.options.locations) { node.loc.end = typeParameters.loc.end; } } return this.finishNode(node, 'TSExpressionWithTypeArguments'); } parseTSTypeParameter() { const node = this.startNode(); if (this.type === acorn_1.tokTypes.name) { node.name = this.value; this.next(); } else { this.unexpected(); } if (this.eat(acorn_1.tokTypes._extends)) { node.constraint = this._parseTSType(); } if (this.eat(acorn_1.tokTypes.eq)) { node.default = this._parseTSType(); } return this.finishNode(node, 'TSTypeParameter'); } parseMaybeTSTypeParameterDeclaration() { if (this._isStartOfTypeParameters()) { const node = this.startNode(); const params = []; let first = true; this.next(); while (!this.eat(acorn_1.tokTypes.relational)) { if (first) { first = false; } else { this.expect(acorn_1.tokTypes.comma); } if (this._isEndOfTypeParameters()) { break; } params.push(this.parseTSTypeParameter()); } node.params = params; return this.finishNode(node, 'TSTypeParameterDeclaration'); } } parseTSTypeParameterInstantiation() { const node = this.startNode(); const params = []; this.next(); // < let first = true; while ((this.value && !this._isEndOfTypeParameters()) || this.type === acorn_1.tokTypes.comma) { if (first) { first = false; } else { this.expect(acorn_1.tokTypes.comma); } params.push(this._parseTSType()); } if (this._isEndOfTypeParameters()) { if (this.value.length > 1) { this.value = this.value.slice(1); // Fix to allow chaining of type parameters } else { this.next(); // > } } node.params = params; return this.finishNode(node, 'TSTypeParameterInstantiation'); } parseMaybeTSTypeParameterInstantiation() { if (this._isStartOfTypeParameters()) { return this.parseTSTypeParameterInstantiation(); } } _parseObjectLikeType(kind, prop) { const node = this.startNode(); this.expect(acorn_1.tokTypes.braceL); const list = []; while (!this.eat(acorn_1.tokTypes.braceR)) { switch (this.type) { case acorn_1.tokTypes.name: const key = this.parseIdent(); switch (this.type) { case acorn_1.tokTypes.parenL: case acorn_1.tokTypes.relational: list.push(this.parseTSMethodSignature(key)); break; case acorn_1.tokTypes.colon: case acorn_1.tokTypes.semi: case acorn_1.tokTypes.comma: case acorn_1.tokTypes.braceR: case acorn_1.tokTypes.question: list.push(this.parseTSPropertySignature(key)); break; default: if (this._hasPrecedingLineBreak()) { list.push(this.parseTSPropertySignature(key)); continue; } this.unexpected(); } break; case acorn_1.tokTypes.bracketL: const recover = this.tsPreparePreview(); this.nextToken(); if (this.type === acorn_1.tokTypes.name) { this.nextToken(); switch (this.type) { case acorn_1.tokTypes.colon: recover(); list.push(this.parseTSIndexSignature()); break; case acorn_1.tokTypes._in: if (list.length === 0) { recover(); return this.parseTSMappedType(); } else { recover(); list.push(this.parseTSPropertySignature(null, true)); } break; default: recover(); list.push(this.parseTSPropertySignature(null, true)); } } else { recover(); list.push(this.parseTSPropertySignature(null, true)); } break; case acorn_1.tokTypes._new: list.push(this.parseTSConstructSignatureDeclaration()); break; default: this.unexpected(); } } node[prop] = list; return this.finishNode(node, kind); } parseTSMethodSignature(key) { const node = this.startNodeAtNode(key); node.key = key; if (this.eat(acorn_1.tokTypes.question)) { node.optional = true; } node.typeParameters = this.parseMaybeTSTypeParameterDeclaration(); this.expect(acorn_1.tokTypes.parenL); node.parameters = this.parseBindingList(acorn_1.tokTypes.parenR, false, this.options.ecmaVersion >= 8); if (this.type === acorn_1.tokTypes.colon) { node.typeAnnotation = this.parseTSTypeAnnotation(true); } if (!this.eat(acorn_1.tokTypes.comma)) this.eat(acorn_1.tokTypes.semi); return this.finishNode(node, 'TSMethodSignature'); } parseTSPropertySignature(key, computed = false) { let node; if (computed) { node = this.startNode(); this.expect(acorn_1.tokTypes.bracketL); node.key = this.parseExpression(); this.expect(acorn_1.tokTypes.bracketR); } else { node = this.startNodeAtNode(key); node.key = key; } node.computed = computed; if (this.eat(acorn_1.tokTypes.question)) { node.optional = true; } if (this.type === acorn_1.tokTypes.colon) { node.typeAnnotation = this.parseTSTypeAnnotation(true); } if (!this.eat(acorn_1.tokTypes.comma)) this.eat(acorn_1.tokTypes.semi); return this.finishNode(node, 'TSPropertySignature'); } parseTSIndexSignature() { const node = this.startNode(); this.expect(acorn_1.tokTypes.bracketL); const index = this.parseIdent(); index.typeAnnotation = this.parseTSTypeAnnotation(true); index.end = index.typeAnnotation.end; if (this.options.locations) { index.loc.end = index.typeAnnotation.loc.end; } node.index = index; this.expect(acorn_1.tokTypes.bracketR); node.typeAnnotation = this.parseTSTypeAnnotation(true); if (!this.eat(acorn_1.tokTypes.comma)) this.eat(acorn_1.tokTypes.semi); return this.finishNode(node, 'TSIndexSignature'); } parseTSMappedType() { const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); this.expect(acorn_1.tokTypes.bracketL); node.typeParameter = this._parseTSTypeParameterInTSMappedType(); this.expect(acorn_1.tokTypes.bracketR); if (this.eat(acorn_1.tokTypes.question)) { node.optional = true; } if (this.type === acorn_1.tokTypes.colon) { node.typeAnnotation = this.parseTSTypeAnnotation(true); } this.semicolon(); this.expect(acorn_1.tokTypes.braceR); return this.finishNode(node, 'TSMappedType'); } _parseTSTypeParameterInTSMappedType() { const node = this.startNode(); if (this.type === acorn_1.tokTypes.name) { node.name = this.value; this.next(); } else { this.unexpected(); } this.expect(acorn_1.tokTypes._in); node.constraint = this._parseNonConditionalType(); return this.finishNode(node, 'TSTypeParameter'); } _parseMaybeTSExpression(node) { if (this.type === acorn_1.tokTypes.prefix && tsExprMarkup[this.value] === tsExprMarkup['!']) { node = this.parseTSNonNullExpression(node); } if (this.type === acorn_1.tokTypes.name && tsExprMarkup[this.value] === tsExprMarkup.as) { node = this.parseTSAsExpression(node); } return node; } parseTSAsExpression(expression) { let node = expression; while (this.type === acorn_1.tokTypes.name && tsExprMarkup[this.value] === tsExprMarkup.as) { const _node = this.startNodeAtNode(node); this.next(); _node.expression = node; this._parseTSTypeAnnotation(_node); node = this.finishNode(_node, 'TSAsExpression'); } return expression; } parseTSNonNullExpression(expression) { let node = expression; while (this.type === acorn_1.tokTypes.prefix && tsExprMarkup[this.value] === tsExprMarkup['!']) { const _node = this.startNodeAtNode(node); _node.expression = node; this.next(); node = this.finishNode(_node, 'TSNonNullExpression'); } return node; } }; }; // acorn-class-fields plugin is needed, else parsing of some function types will not work // eslint-disable-next-line @typescript-eslint/no-require-imports const TypeParser = acorn_1.Parser.extend(tsPlugin, require('acorn-class-fields')); exports.default = TypeParser; //# sourceMappingURL=typeParser.js.map