@ts-ast-parser/core
Version:
Reflects a simplified version of the TypeScript AST for generating documentation
179 lines • 5.93 kB
JavaScript
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