UNPKG

@ts-ast-parser/core

Version:

Reflects a simplified version of the TypeScript AST for generating documentation

179 lines 5.93 kB
import ts from 'typescript'; /** * A class that shares common utilities between all reflected nodes */ export class ProjectContext { constructor(system, getProgram, getCommandLine, diagnostics, options) { Object.defineProperty(this, "_getProgram", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_getCommandLine", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_options", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_diagnostics", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_system", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_reflectedNodesBySymbol", { enumerable: true, configurable: true, writable: true, value: new Map() }); this._system = system; this._getProgram = getProgram; this._getCommandLine = getCommandLine; this._diagnostics = diagnostics; this._options = options; } /** * A Program is an immutable collection of source files and the compiler options. Together * represent a compilation unit. * * @returns The TypeScript program created with the TypeScript compiler API */ getProgram() { return this._getProgram(); } /** * The TypeScript compiler options parsed (if you have a TSConfig file, the parsed * options will be the ones defined there) * * @returns The parsed compiler options */ getCommandLine() { return this._getCommandLine(); } /** * The TypeScript type checker. * * Useful to resolve the types and location of the reflected nodes. * * @returns The TypeScript type checker */ getTypeChecker() { return this._getProgram().getTypeChecker(); } /** * An abstraction layer around how we interact with the environment (browser or Node.js) * * @returns The system environment used */ getSystem() { return this._system; } /** * Here we save all the errors we find while analysing the source files * * @returns An instance of the `AnalyserDiagnostic` where all errors are enqueue */ getDiagnostics() { return this._diagnostics; } /** * The user provided analyzer options. * * @returns The options that were provided when calling the parser function */ getOptions() { return this._options; } /** * Creates a new reflected node only if it doesn't exist already in the internal cache. * * @param node - The `ts.Node` associated with the reflected node * @param reflectedNodeFactory - The function to use to build the new reflection if it doesn't exist * @returns The reflected node instance */ registerReflectedNode(node, reflectedNodeFactory) { const symbol = this.getSymbol(node); if (!symbol) { return reflectedNodeFactory(); } let reflection = this._reflectedNodesBySymbol.get(symbol); if (!reflection) { reflection = reflectedNodeFactory(); this._reflectedNodesBySymbol.set(symbol, reflection); } return reflection; } /** * Returns the associated `ts.Symbol` for the given node * * @param node - The `ts.Node` to search its symbol * @returns The symbol if it has one */ getSymbol(node) { const checker = this.getTypeChecker(); let symbol = checker.getSymbolAtLocation(node); if (!symbol && this._isNamedNode(node)) { symbol = checker.getSymbolAtLocation(node.name); } // We have to check first, because the TS TypeChecker will throw an // error if there is no alias while (symbol && (symbol.flags & ts.SymbolFlags.Alias) !== 0) { symbol = checker.getAliasedSymbol(symbol); } if (!symbol) { symbol = node.symbol; } return symbol ?? null; } /** * Given a node or a type it returns it's associated symbol, line position and the file path where * it was defined. * * @param nodeOrType - The node or type to search for * @returns The symbol, line position and path where the node/type is located */ getLocation(nodeOrType) { let symbol; if ('kind' in nodeOrType) { symbol = this.getSymbol(nodeOrType); } else { symbol = nodeOrType.aliasSymbol ?? nodeOrType.getSymbol(); } const decl = symbol?.getDeclarations()?.[0]; const sourceFile = decl?.getSourceFile(); const path = sourceFile?.fileName ? this._system.normalizePath(this._system.realpath(sourceFile.fileName)) : ''; const line = decl ? this.getLinePosition(decl) : null; return { symbol, path, line }; } /** * Returns the start line number where the node is located * * @param node - The node to locate * @returns The line number where the node is located */ getLinePosition(node) { return node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()).line + 1; } _isNamedNode(node) { const name = node.name; return !!name && (ts.isMemberName(name) || ts.isComputedPropertyName(name)); } } //# sourceMappingURL=project-context.js.map