UNPKG

16.9 kBSource Map (JSON)View Raw
1{"version":3,"file":"TypeScriptHelpers.js","sourceRoot":"","sources":["../../src/analyzer/TypeScriptHelpers.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;AAE3D,+BAA+B;AAE/B,+CAAiC;AACjC,+EAA4E;AAC5E,+DAA4D;AAC5D,oEAA6D;AAE7D,MAAa,iBAAiB;IAS5B;;;;;;;;;;OAUG;IACI,MAAM,CAAC,aAAa,CAAC,MAAiB,EAAE,WAA2B;QACxE,IAAI,OAAO,GAAc,MAAM,CAAC;QAChC,SAAS;YACP,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE;gBAC3C,MAAM;aACP;YACD,MAAM,YAAY,GAAc,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACtE,IAAI,CAAC,YAAY,IAAI,YAAY,KAAK,OAAO,EAAE;gBAC7C,MAAM;aACP;YACD,OAAO,GAAG,YAAY,CAAC;SACxB;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,iBAAiB,CAAC,MAAiB,EAAE,WAA2B;QAC5E,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE;YAC1C,OAAO,KAAK,CAAC;SACd;QAED,MAAM,KAAK,GAAc,WAAW,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,MAAM,EAAE;YAC9B,OAAO,KAAK,CAAC;SACd;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,kBAAkB,CAAC,MAAiB;QAChD,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;YACzD,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;SAC/B;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE,WAA2B;QACpE,MAAM,cAAc,GAAc,iBAAiB,CAAC,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEvF,IAAI,cAAc,CAAC,YAAY,IAAI,cAAc,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;YACzE,MAAM,gBAAgB,GAAmB,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAExE,mEAAmE;YACnE,MAAM,wBAAwB,GAAqC,iBAAiB,CAAC,iBAAiB,CACpG,gBAAgB,EAChB,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAChC,CAAC;YACF,IAAI,wBAAwB,EAAE;gBAC5B,IAAI,wBAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,QAAQ,EAAE;oBAC/D,OAAO,IAAI,CAAC;iBACb;aACF;YAED,sFAAsF;YACtF,uFAAuF;YACvF,iCAAiC;YACjC,MAAM,UAAU,GAAkB,gBAAgB,CAAC,aAAa,EAAE,CAAC;YAEnE,IAAI,WAAW,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE;gBAC/C,OAAO,KAAK,CAAC;aACd;SACF;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,uBAAuB,CAAC,WAA2B,EAAE,OAAuB;QACxF,MAAM,MAAM,GAA0B,yCAAmB,CAAC,0BAA0B,CAClF,WAAW,EACX,OAAO,CACR,CAAC;QACF,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,iCAAa,CACrB,6DAA6D;gBAC3D,yDAA2B,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAC7D,CAAC;SACH;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,0GAA0G;IACnG,MAAM,CAAC,kBAAkB,CAC9B,uBAAwF;QAExF,IAAI,uBAAuB,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE;YAC7D,mFAAmF;YACnF,IACE,uBAAuB,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,WAAW;gBAClE,uBAAuB,CAAC,QAA+B,CAAC,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,aAAa,EACrG;gBACA,MAAM,IAAI,iCAAa,CACrB,2BAA2B,uBAAuB,CAAC,OAAO,EAAE,IAAI;oBAC9D,yDAA2B,CAAC,iBAAiB,CAAC,uBAAuB,CAAC,CACzE,CAAC;aACH;YACD,MAAM,eAAe,GAAuB,uBAAuB,CAAC,QAA8B,CAAC;YACnG,MAAM,aAAa,GAAqB,eAAe,CAAC,OAA2B,CAAC;YACpF,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAClC;QAED,wBAAwB;QACxB,IACE,uBAAuB,CAAC,eAAe;YACvC,EAAE,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,eAAe,CAAC,EAC/D;YACA,OAAO,yCAAmB,CAAC,4BAA4B,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC;SAClG;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,MAAM,CAAC,aAAa,CACzB,IAAa,EACb,YAA6B;QAE7B,6BAA6B;QAC7B,MAAM,mBAAmB,GAAoB,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAE7E,IAAI,OAAO,GAAwB,SAAS,CAAC;QAE7C,KAAK,MAAM,UAAU,IAAI,mBAAmB,EAAE;YAC5C,IAAI,CAAC,OAAO,EAAE;gBACZ,0CAA0C;gBAC1C,OAAO,GAAG,IAAI,CAAC;aAChB;iBAAM;gBACL,wBAAwB;gBACxB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;aAC1B;YAED,kEAAkE;YAClE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE;gBAC3C,OAAO,SAAS,CAAC;aAClB;SACF;QAED,wFAAwF;QACxF,OAAO,OAAY,CAAC;IACtB,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,kBAAkB,CAC9B,IAAa,EACb,WAA0B;QAE1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;YACtC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE;gBAC9B,OAAO,KAAU,CAAC;aACnB;YAED,MAAM,cAAc,GAAkB,iBAAiB,CAAC,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;YAC/F,IAAI,cAAc,EAAE;gBAClB,OAAO,cAAc,CAAC;aACvB;SACF;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,eAAe,CAAoB,IAAa,EAAE,WAA0B;QACxF,IAAI,OAAO,GAAwB,IAAI,CAAC,MAAM,CAAC;QAE/C,OAAO,OAAO,EAAE;YACd,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE;gBAChC,OAAO,OAAY,CAAC;aACrB;YACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;SAC1B;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,iBAAiB,CAC7B,IAAa,EACb,WAA0B;QAE1B,IAAI,OAAO,GAAwB,IAAI,CAAC;QACxC,IAAI,OAAO,GAAkB,SAAS,CAAC;QAEvC,SAAS;YACP,OAAO,GAAG,iBAAiB,CAAC,eAAe,CAAI,OAAO,EAAE,WAAW,CAAC,CAAC;YACrE,IAAI,CAAC,OAAO,EAAE;gBACZ,MAAM;aACP;YACD,OAAO,GAAG,OAAY,CAAC;SACxB;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,4BAA4B,CAAC,IAAiB;QAC1D,MAAM,KAAK,GAA2B,iBAAiB,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;QACxG,IAAI,KAAK,EAAE;YACT,MAAM,UAAU,GAAW,KAAK,CAAC,CAAC,CAAC,CAAC;YACpC,OAAO,WAAW,UAAU,GAAG,CAAC;SACjC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,kBAAkB,CAAC,IAAiB;QAChD,OAAO,iBAAiB,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;IACxE,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,mBAAmB,CAAC,eAAwC;QACxE,yFAAyF;QACzF,+BAA+B;QAC/B,MAAM,OAAO,GAAe,EAAE,CAAC,aAAa,CAC1C,EAAE,cAAc,EAAE,IAAI,EAAE,EACxB;YACE,UAAU,CACR,IAAiB,EACjB,IAAa,EACb,YAAwD;gBAExD,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa,GAAG,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;gBACvF,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC3B,CAAC;SACF,CACF,CAAC;QACF,MAAM,UAAU,GAAkB,eAAe,CAAC,aAAa,EAAE,CAAC;QAClE,MAAM,IAAI,GAAW,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;QAC7F,8DAA8D;QAC9D,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;;AAzSH,8CA0SC;AAzSC,4EAA4E;AAC5E,qCAAqC;AACb,4CAA0B,GAAW,YAAY,CAAC;AAE1E,sGAAsG;AACtG,qFAAqF;AAC7D,yCAAuB,GAAW,aAAa,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/* eslint-disable no-bitwise */\n\nimport * as ts from 'typescript';\nimport { SourceFileLocationFormatter } from './SourceFileLocationFormatter';\nimport { TypeScriptInternals } from './TypeScriptInternals';\nimport { InternalError } from '@rushstack/node-core-library';\n\nexport class TypeScriptHelpers {\n // Matches TypeScript's encoded names for well-known ECMAScript symbols like\n // \"__@iterator\" or \"__@toStringTag\".\n private static readonly _wellKnownSymbolNameRegExp: RegExp = /^__@(\\w+)$/;\n\n // Matches TypeScript's encoded names for late-bound symbols derived from `unique symbol` declarations\n // which have the form of \"__@<variableName>@<symbolId>\", i.e. \"__@someSymbol@12345\".\n private static readonly _uniqueSymbolNameRegExp: RegExp = /^__@.*@\\d+$/;\n\n /**\n * This traverses any symbol aliases to find the original place where an item was defined.\n * For example, suppose a class is defined as \"export default class MyClass { }\"\n * but exported from the package's index.ts like this:\n *\n * export { default as _MyClass } from './MyClass';\n *\n * In this example, calling followAliases() on the _MyClass symbol will return the\n * original definition of MyClass, traversing any intermediary places where the\n * symbol was imported and re-exported.\n */\n public static followAliases(symbol: ts.Symbol, typeChecker: ts.TypeChecker): ts.Symbol {\n let current: ts.Symbol = symbol;\n for (;;) {\n if (!(current.flags & ts.SymbolFlags.Alias)) {\n break;\n }\n const currentAlias: ts.Symbol = typeChecker.getAliasedSymbol(current);\n if (!currentAlias || currentAlias === current) {\n break;\n }\n current = currentAlias;\n }\n\n return current;\n }\n\n /**\n * Returns true if TypeScriptHelpers.followAliases() would return something different\n * from the input `symbol`.\n */\n public static isFollowableAlias(symbol: ts.Symbol, typeChecker: ts.TypeChecker): boolean {\n if (!(symbol.flags & ts.SymbolFlags.Alias)) {\n return false;\n }\n\n const alias: ts.Symbol = typeChecker.getAliasedSymbol(symbol);\n if (!alias || alias === symbol) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Certain virtual symbols do not have any declarations. For example, `ts.TypeChecker.getExportsOfModule()` can\n * sometimes return a \"prototype\" symbol for an object, even though there is no corresponding declaration in the\n * source code. API Extractor generally ignores such symbols.\n */\n public static tryGetADeclaration(symbol: ts.Symbol): ts.Declaration | undefined {\n if (symbol.declarations && symbol.declarations.length > 0) {\n return symbol.declarations[0];\n }\n return undefined;\n }\n\n /**\n * Returns true if the specified symbol is an ambient declaration.\n */\n public static isAmbient(symbol: ts.Symbol, typeChecker: ts.TypeChecker): boolean {\n const followedSymbol: ts.Symbol = TypeScriptHelpers.followAliases(symbol, typeChecker);\n\n if (followedSymbol.declarations && followedSymbol.declarations.length > 0) {\n const firstDeclaration: ts.Declaration = followedSymbol.declarations[0];\n\n // Test 1: Are we inside the sinister \"declare global {\" construct?\n const highestModuleDeclaration: ts.ModuleDeclaration | undefined = TypeScriptHelpers.findHighestParent(\n firstDeclaration,\n ts.SyntaxKind.ModuleDeclaration\n );\n if (highestModuleDeclaration) {\n if (highestModuleDeclaration.name.getText().trim() === 'global') {\n return true;\n }\n }\n\n // Test 2: Otherwise, the main heuristic for ambient declarations is by looking at the\n // ts.SyntaxKind.SourceFile node to see whether it has a symbol or not (i.e. whether it\n // is acting as a module or not).\n const sourceFile: ts.SourceFile = firstDeclaration.getSourceFile();\n\n if (typeChecker.getSymbolAtLocation(sourceFile)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Same semantics as tryGetSymbolForDeclaration(), but throws an exception if the symbol\n * cannot be found.\n */\n public static getSymbolForDeclaration(declaration: ts.Declaration, checker: ts.TypeChecker): ts.Symbol {\n const symbol: ts.Symbol | undefined = TypeScriptInternals.tryGetSymbolForDeclaration(\n declaration,\n checker\n );\n if (!symbol) {\n throw new InternalError(\n 'Unable to determine semantic information for declaration:\\n' +\n SourceFileLocationFormatter.formatDeclaration(declaration)\n );\n }\n return symbol;\n }\n\n // Return name of the module, which could be like \"./SomeLocalFile' or like 'external-package/entry/point'\n public static getModuleSpecifier(\n nodeWithModuleSpecifier: ts.ImportDeclaration | ts.ExportDeclaration | ts.ImportTypeNode\n ): string | undefined {\n if (nodeWithModuleSpecifier.kind === ts.SyntaxKind.ImportType) {\n // As specified internally in typescript:/src/compiler/types.ts#ValidImportTypeNode\n if (\n nodeWithModuleSpecifier.argument.kind !== ts.SyntaxKind.LiteralType ||\n (nodeWithModuleSpecifier.argument as ts.LiteralTypeNode).literal.kind !== ts.SyntaxKind.StringLiteral\n ) {\n throw new InternalError(\n `Invalid ImportTypeNode: ${nodeWithModuleSpecifier.getText()}\\n` +\n SourceFileLocationFormatter.formatDeclaration(nodeWithModuleSpecifier)\n );\n }\n const literalTypeNode: ts.LiteralTypeNode = nodeWithModuleSpecifier.argument as ts.LiteralTypeNode;\n const stringLiteral: ts.StringLiteral = literalTypeNode.literal as ts.StringLiteral;\n return stringLiteral.text.trim();\n }\n\n // Node is a declaration\n if (\n nodeWithModuleSpecifier.moduleSpecifier &&\n ts.isStringLiteralLike(nodeWithModuleSpecifier.moduleSpecifier)\n ) {\n return TypeScriptInternals.getTextOfIdentifierOrLiteral(nodeWithModuleSpecifier.moduleSpecifier);\n }\n\n return undefined;\n }\n\n /**\n * Returns an ancestor of \"node\", such that the ancestor, any intermediary nodes,\n * and the starting node match a list of expected kinds. Undefined is returned\n * if there aren't enough ancestors, or if the kinds are incorrect.\n *\n * For example, suppose child \"C\" has parents A --> B --> C.\n *\n * Calling _matchAncestor(C, [ExportSpecifier, NamedExports, ExportDeclaration])\n * would return A only if A is of kind ExportSpecifier, B is of kind NamedExports,\n * and C is of kind ExportDeclaration.\n *\n * Calling _matchAncestor(C, [ExportDeclaration]) would return C.\n */\n public static matchAncestor<T extends ts.Node>(\n node: ts.Node,\n kindsToMatch: ts.SyntaxKind[]\n ): T | undefined {\n // (slice(0) clones an array)\n const reversedParentKinds: ts.SyntaxKind[] = kindsToMatch.slice(0).reverse();\n\n let current: ts.Node | undefined = undefined;\n\n for (const parentKind of reversedParentKinds) {\n if (!current) {\n // The first time through, start with node\n current = node;\n } else {\n // Then walk the parents\n current = current.parent;\n }\n\n // If we ran out of items, or if the kind doesn't match, then fail\n if (!current || current.kind !== parentKind) {\n return undefined;\n }\n }\n\n // If we matched everything, then return the node that matched the last parentKinds item\n return current as T;\n }\n\n /**\n * Does a depth-first search of the children of the specified node. Returns the first child\n * with the specified kind, or undefined if there is no match.\n */\n public static findFirstChildNode<T extends ts.Node>(\n node: ts.Node,\n kindToMatch: ts.SyntaxKind\n ): T | undefined {\n for (const child of node.getChildren()) {\n if (child.kind === kindToMatch) {\n return child as T;\n }\n\n const recursiveMatch: T | undefined = TypeScriptHelpers.findFirstChildNode(child, kindToMatch);\n if (recursiveMatch) {\n return recursiveMatch;\n }\n }\n\n return undefined;\n }\n\n /**\n * Returns the first parent node with the specified SyntaxKind, or undefined if there is no match.\n */\n public static findFirstParent<T extends ts.Node>(node: ts.Node, kindToMatch: ts.SyntaxKind): T | undefined {\n let current: ts.Node | undefined = node.parent;\n\n while (current) {\n if (current.kind === kindToMatch) {\n return current as T;\n }\n current = current.parent;\n }\n\n return undefined;\n }\n\n /**\n * Returns the highest parent node with the specified SyntaxKind, or undefined if there is no match.\n * @remarks\n * Whereas findFirstParent() returns the first match, findHighestParent() returns the last match.\n */\n public static findHighestParent<T extends ts.Node>(\n node: ts.Node,\n kindToMatch: ts.SyntaxKind\n ): T | undefined {\n let current: ts.Node | undefined = node;\n let highest: T | undefined = undefined;\n\n for (;;) {\n current = TypeScriptHelpers.findFirstParent<T>(current, kindToMatch);\n if (!current) {\n break;\n }\n highest = current as T;\n }\n\n return highest;\n }\n\n /**\n * Decodes the names that the compiler generates for a built-in ECMAScript symbol.\n *\n * @remarks\n * TypeScript binds well-known ECMAScript symbols like `[Symbol.iterator]` as `__@iterator`.\n * If `name` is of this form, then `tryGetWellKnownSymbolName()` converts it back into e.g. `[Symbol.iterator]`.\n * If the string does not start with `__@` then `undefined` is returned.\n */\n public static tryDecodeWellKnownSymbolName(name: ts.__String): string | undefined {\n const match: RegExpExecArray | null = TypeScriptHelpers._wellKnownSymbolNameRegExp.exec(name as string);\n if (match) {\n const identifier: string = match[1];\n return `[Symbol.${identifier}]`;\n }\n return undefined;\n }\n\n /**\n * Returns whether the provided name was generated for a TypeScript `unique symbol`.\n */\n public static isUniqueSymbolName(name: ts.__String): boolean {\n return TypeScriptHelpers._uniqueSymbolNameRegExp.test(name as string);\n }\n\n /**\n * Derives the string representation of a TypeScript late-bound symbol.\n */\n public static tryGetLateBoundName(declarationName: ts.ComputedPropertyName): string | undefined {\n // Create a node printer that ignores comments and indentation that we can use to convert\n // declarationName to a string.\n const printer: ts.Printer = ts.createPrinter(\n { removeComments: true },\n {\n onEmitNode(\n hint: ts.EmitHint,\n node: ts.Node,\n emitCallback: (hint: ts.EmitHint, node: ts.Node) => void\n ): void {\n ts.setEmitFlags(declarationName, ts.EmitFlags.NoIndentation | ts.EmitFlags.SingleLine);\n emitCallback(hint, node);\n }\n }\n );\n const sourceFile: ts.SourceFile = declarationName.getSourceFile();\n const text: string = printer.printNode(ts.EmitHint.Unspecified, declarationName, sourceFile);\n // clean up any emit flags we've set on any nodes in the tree.\n ts.disposeEmitNodes(sourceFile);\n return text;\n }\n}\n"]}
\No newline at end of file