UNPKG

ts-simple-ast

Version:

TypeScript compiler wrapper for AST navigation and code generation.

180 lines (178 loc) 6.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ts = require("typescript"); const minimatch_1 = require("minimatch"); const errors = require("./errors"); const utils_1 = require("./utils"); const DefaultFileSystemHost_1 = require("./DefaultFileSystemHost"); const GlobalContainer_1 = require("./GlobalContainer"); /** * Compiler wrapper. */ class TsSimpleAst { /** * Initializes a new instance. * @param options - Optional options. * @param fileSystem - Optional file system host. Useful for mocking access to the file system. */ constructor(options = {}, fileSystem = new DefaultFileSystemHost_1.DefaultFileSystemHost()) { this.fileSystem = fileSystem; this.global = new GlobalContainer_1.GlobalContainer(fileSystem, getCompilerOptionsFromOptions(options, fileSystem), true); if (options.manipulationSettings != null) this.global.manipulationSettings.set(options.manipulationSettings); } /** Gets the manipulation settings. */ get manipulationSettings() { return this.global.manipulationSettings; } /** * Add source files based on file globs. * @param fileGlobs - File globs to add files based on. */ addSourceFiles(...fileGlobs) { const filePaths = this.fileSystem.glob(fileGlobs); for (const filePath of filePaths) { // ignore any FileNotFoundErrors try { this.getOrAddSourceFile(filePath); } catch (ex) { /* istanbul ignore if */ if (!(ex instanceof errors.FileNotFoundError)) throw ex; } } } /** * Gets or adds a source file from a file path. * @param filePath - File path to create the file from. */ getOrAddSourceFile(filePath) { const absoluteFilePath = utils_1.FileUtils.getStandardizedAbsolutePath(filePath); if (!this.fileSystem.fileExistsSync(absoluteFilePath)) throw new errors.FileNotFoundError(absoluteFilePath); return this.global.compilerFactory.getSourceFileFromFilePath(absoluteFilePath); } /** * Adds a source file from text. * @param filePath - File path for the source file. * @param sourceFileText - Source file text. * @throws - InvalidOperationError if a source file already exists at the provided file path. */ addSourceFileFromText(filePath, sourceFileText) { return this.global.compilerFactory.addSourceFileFromText(filePath, sourceFileText); } /** * Adds a source file from a structure. * @param filePath - File path for the source file. * @param structure - Structure that represents the source file. * @throws - InvalidOperationError if a source file already exists at the provided file path. */ addSourceFileFromStructure(filePath, structure) { const sourceFile = this.global.compilerFactory.addSourceFileFromText(filePath, ""); sourceFile.fill(structure); return sourceFile; } /** * Removes a source file from the AST. * @param sourceFile - Source file to remove. * @returns True if removed. */ removeSourceFile(sourceFile) { return this.global.languageService.removeSourceFile(sourceFile); } getSourceFileOrThrow(fileNameOrSearchFunction) { const sourceFile = this.getSourceFile(fileNameOrSearchFunction); if (sourceFile == null) { if (typeof fileNameOrSearchFunction === "string") throw new errors.InvalidOperationError(`Could not find source file based on the provided name or path: ${fileNameOrSearchFunction}.`); else throw new errors.InvalidOperationError(`Could not find source file based on the provided condition.`); } return sourceFile; } getSourceFile(fileNameOrSearchFunction) { let searchFunction = fileNameOrSearchFunction; if (typeof fileNameOrSearchFunction === "string") searchFunction = def => utils_1.FileUtils.filePathMatches(def.getFilePath(), fileNameOrSearchFunction); return this.getSourceFiles().find(searchFunction); } /** * Gets all the source files contained in the compiler wrapper. * @param globPattern - Glob pattern for filtering out the source files. */ getSourceFiles(globPattern) { let sourceFiles = this.global.languageService.getSourceFiles(); if (typeof globPattern === "string") { const mm = new minimatch_1.Minimatch(globPattern, { matchBase: true }); sourceFiles = sourceFiles.filter(s => mm.match(s.getFilePath())); } return sourceFiles; } /** * Saves all the unsaved source files. */ saveUnsavedSourceFiles() { return Promise.all(this.getUnsavedSourceFiles().map(f => f.save())); } /** * Saves all the unsaved source files synchronously. * * Remarks: This might be very slow compared to the asynchronous version if there are a lot of files. */ saveUnsavedSourceFilesSync() { // sidenote: I wish I could do something like in c# where I do this all asynchronously then // wait synchronously on the task. It would not be as bad as this is performance wise. Maybe there // is a way, but people just shouldn't be using this method unless they're really lazy. for (const file of this.getUnsavedSourceFiles()) file.saveSync(); } getUnsavedSourceFiles() { return this.getSourceFiles().filter(f => !f.isSaved()); } /** * Gets the compiler diagnostics. */ getDiagnostics() { // todo: implement cancellation token const compilerDiagnostics = ts.getPreEmitDiagnostics(this.global.program.compilerObject); return compilerDiagnostics.map(d => this.global.compilerFactory.getDiagnostic(d)); } /** * Gets the language service. */ getLanguageService() { return this.global.languageService; } /** * Gets the program. */ getProgram() { return this.global.program; } /** * Gets the type checker. */ getTypeChecker() { return this.global.typeChecker; } /** * Emits all the source files. * @param emitOptions - Optional emit options. */ emit(emitOptions = {}) { return this.global.program.emit(emitOptions); } /** * Gets the compiler options. */ getCompilerOptions() { // return a copy return Object.assign({}, this.global.compilerOptions); } } exports.TsSimpleAst = TsSimpleAst; function getCompilerOptionsFromOptions(options, fileSystem) { return Object.assign({}, (options.tsConfigFilePath == null ? {} : utils_1.getCompilerOptionsFromTsConfig(options.tsConfigFilePath, fileSystem)), (options.compilerOptions || {})); } //# sourceMappingURL=TsSimpleAst.js.map