UNPKG

ts-simple-ast

Version:

TypeScript compiler wrapper for static analysis and code manipulation.

690 lines (689 loc) 33.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var errors = require("./errors"); var fileSystem_1 = require("./fileSystem"); var ProjectContext_1 = require("./ProjectContext"); var typescript_1 = require("./typescript"); var utils_1 = require("./utils"); /** * Project that holds source files. */ var Project = /** @class */ (function () { /** * Initializes a new instance. * @param options - Optional options. */ function Project(options) { if (options === void 0) { options = {}; } // setup file system var fileSystem = options.fileSystem; if (fileSystem != null && options.useVirtualFileSystem) throw new errors.InvalidOperationError("Cannot provide a file system when specifying to use a virtual file system."); else if (options.useVirtualFileSystem) fileSystem = new fileSystem_1.VirtualFileSystemHost(); else if (fileSystem == null) fileSystem = new fileSystem_1.DefaultFileSystemHost(); var fileSystemWrapper = new fileSystem_1.FileSystemWrapper(fileSystem); // get tsconfig info var tsConfigResolver = options.tsConfigFilePath == null ? undefined : new utils_1.TsConfigResolver(fileSystemWrapper, options.tsConfigFilePath, getEncoding()); var compilerOptions = getCompilerOptions(); // setup context this._context = new ProjectContext_1.ProjectContext(fileSystemWrapper, compilerOptions, { createLanguageService: true }); // initialize manipulation settings if (options.manipulationSettings != null) this._context.manipulationSettings.set(options.manipulationSettings); // add any file paths from the tsconfig if necessary if (tsConfigResolver != null && options.addFilesFromTsConfig !== false) { this._addSourceFilesForTsConfigResolver(tsConfigResolver, compilerOptions); if (!options.skipFileDependencyResolution) this.resolveSourceFileDependencies(); } function getCompilerOptions() { return tslib_1.__assign({}, getTsConfigCompilerOptions(), (options.compilerOptions || {})); } function getTsConfigCompilerOptions() { if (tsConfigResolver == null) return {}; return tsConfigResolver.getCompilerOptions(); } function getEncoding() { var defaultEncoding = "utf-8"; if (options.compilerOptions != null) return options.compilerOptions.charset || defaultEncoding; return defaultEncoding; } } Object.defineProperty(Project.prototype, "manipulationSettings", { /** Gets the manipulation settings. */ get: function () { return this._context.manipulationSettings; }, enumerable: true, configurable: true }); Object.defineProperty(Project.prototype, "compilerOptions", { /** Gets the compiler options for modification. */ get: function () { return this._context.compilerOptions; }, enumerable: true, configurable: true }); /** * Adds the source files the project's source files depend on to the project. * @returns The added source files. * @remarks * * This should be done after source files are added to the project, preferably once to * avoid doing more work than necessary. * * This is done by default when creating a Project and providing a tsconfig.json and * not specifying to not add the source files. */ Project.prototype.resolveSourceFileDependencies = function () { var e_1, _a, e_2, _b; var sourceFiles = utils_1.createHashSet(); var onSourceFileAdded = function (sourceFile) { return sourceFiles.add(sourceFile); }; var _c = this._context, compilerFactory = _c.compilerFactory, inProjectCoordinator = _c.inProjectCoordinator; compilerFactory.onSourceFileAdded(onSourceFileAdded); try { this.getProgram().compilerObject; // create the program } finally { compilerFactory.onSourceFileAdded(onSourceFileAdded, false); // unsubscribe } var result = inProjectCoordinator.markSourceFilesAsInProjectForResolution(); try { for (var _d = tslib_1.__values(result.changedSourceFiles), _e = _d.next(); !_e.done; _e = _d.next()) { var sourceFile = _e.value; sourceFiles.add(sourceFile); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_e && !_e.done && (_a = _d.return)) _a.call(_d); } finally { if (e_1) throw e_1.error; } } try { for (var _f = tslib_1.__values(result.unchangedSourceFiles), _g = _f.next(); !_g.done; _g = _f.next()) { var sourceFile = _g.value; sourceFiles.delete(sourceFile); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_g && !_g.done && (_b = _f.return)) _b.call(_f); } finally { if (e_2) throw e_2.error; } } return Array.from(sourceFiles.values()); }; /** * Adds an existing directory from the path or returns undefined if it doesn't exist. * * Will return the directory if it was already added. * @param dirPath - Path to add the directory at. * @param options - Options. * @skipOrThrowCheck */ Project.prototype.addExistingDirectoryIfExists = function (dirPath, options) { if (options === void 0) { options = {}; } dirPath = this._context.fileSystemWrapper.getStandardizedAbsolutePath(dirPath); return this._context.directoryCoordinator.addExistingDirectoryIfExists(dirPath, tslib_1.__assign({}, options, { markInProject: true })); }; /** * Adds an existing directory from the path or throws if it doesn't exist. * * Will return the directory if it was already added. * @param dirPath - Path to add the directory at. * @param options - Options. * @throws DirectoryNotFoundError when the directory does not exist. */ Project.prototype.addExistingDirectory = function (dirPath, options) { if (options === void 0) { options = {}; } dirPath = this._context.fileSystemWrapper.getStandardizedAbsolutePath(dirPath); return this._context.directoryCoordinator.addExistingDirectory(dirPath, tslib_1.__assign({}, options, { markInProject: true })); }; /** * Creates a directory at the specified path. * @param dirPath - Path to create the directory at. */ Project.prototype.createDirectory = function (dirPath) { dirPath = this._context.fileSystemWrapper.getStandardizedAbsolutePath(dirPath); return this._context.directoryCoordinator.createDirectoryOrAddIfExists(dirPath, { markInProject: true }); }; /** * Gets a directory by the specified path or throws if it doesn't exist. * @param dirPath - Path to create the directory at. */ Project.prototype.getDirectoryOrThrow = function (dirPath) { var _this = this; return errors.throwIfNullOrUndefined(this.getDirectory(dirPath), function () { return "Could not find a directory at the specified path: " + _this._context.fileSystemWrapper.getStandardizedAbsolutePath(dirPath); }); }; /** * Gets a directory by the specified path or returns undefined if it doesn't exist. * @param dirPath - Directory path. */ Project.prototype.getDirectory = function (dirPath) { dirPath = this._context.fileSystemWrapper.getStandardizedAbsolutePath(dirPath); var compilerFactory = this._context.compilerFactory; // when a directory path is specified, even return directories not in the project return compilerFactory.getDirectoryFromCache(dirPath); }; /** * Gets all the directories. */ Project.prototype.getDirectories = function () { return utils_1.ArrayUtils.from(this._getProjectDirectoriesByDirectoryDepth()); }; /** * Gets the directories without a parent. */ Project.prototype.getRootDirectories = function () { return this._context.compilerFactory.getOrphanDirectories(); }; /** * Adds source files based on file globs. * @param fileGlobs - File glob or globs to add files based on. * @returns The matched source files. */ Project.prototype.addExistingSourceFiles = function (fileGlobs) { return this._context.directoryCoordinator.addExistingSourceFiles(fileGlobs, { markInProject: true }); }; /** * Adds a source file from a file path if it exists or returns undefined. * * Will return the source file if it was already added. * @param filePath - File path to get the file from. * @skipOrThrowCheck */ Project.prototype.addExistingSourceFileIfExists = function (filePath) { return this._context.directoryCoordinator.addExistingSourceFileIfExists(filePath, { markInProject: true }); }; /** * Adds an existing source file from a file path or throws if it doesn't exist. * * Will return the source file if it was already added. * @param filePath - File path to get the file from. * @throws FileNotFoundError when the file is not found. */ Project.prototype.addExistingSourceFile = function (filePath) { return this._context.directoryCoordinator.addExistingSourceFile(filePath, { markInProject: true }); }; /** * Adds all the source files from the specified tsconfig.json. * * Note that this is done by default when specifying a tsconfig file in the constructor and not explicitly setting the * addFilesFromTsConfig option to false. * @param tsConfigFilePath - File path to the tsconfig.json file. */ Project.prototype.addSourceFilesFromTsConfig = function (tsConfigFilePath) { tsConfigFilePath = this._context.fileSystemWrapper.getStandardizedAbsolutePath(tsConfigFilePath); var resolver = new utils_1.TsConfigResolver(this._context.fileSystemWrapper, tsConfigFilePath, this._context.getEncoding()); return this._addSourceFilesForTsConfigResolver(resolver, resolver.getCompilerOptions()); }; /** @internal */ Project.prototype._addSourceFilesForTsConfigResolver = function (tsConfigResolver, compilerOptions) { var _this = this; var e_3, _a; var paths = tsConfigResolver.getPaths(compilerOptions); var addedSourceFiles = paths.filePaths.map(function (p) { return _this.addExistingSourceFile(p); }); try { for (var _b = tslib_1.__values(paths.directoryPaths), _c = _b.next(); !_c.done; _c = _b.next()) { var dirPath = _c.value; this.addExistingDirectoryIfExists(dirPath); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_3) throw e_3.error; } } return addedSourceFiles; }; /** * Creates a source file at the specified file path with the specified text. * * Note: The file will not be created and saved to the file system until .save() is called on the source file. * @param filePath - File path of the source file. * @param sourceFileText - Text, structure, or writer function for the source file text. * @param options - Options. * @throws - InvalidOperationError if a source file already exists at the provided file path. */ Project.prototype.createSourceFile = function (filePath, sourceFileText, options) { return this._context.compilerFactory.createSourceFile(filePath, sourceFileText || "", tslib_1.__assign({}, (options || {}), { markInProject: true })); }; /** * Removes a source file from the AST. * @param sourceFile - Source file to remove. * @returns True if removed. */ Project.prototype.removeSourceFile = function (sourceFile) { var previouslyForgotten = sourceFile.wasForgotten(); sourceFile.forget(); return !previouslyForgotten; }; Project.prototype.getSourceFileOrThrow = function (fileNameOrSearchFunction) { var sourceFile = this.getSourceFile(fileNameOrSearchFunction); if (sourceFile != null) return sourceFile; // explain to the user why it couldn't find the file if (typeof fileNameOrSearchFunction === "string") { var fileNameOrPath = utils_1.FileUtils.standardizeSlashes(fileNameOrSearchFunction); if (utils_1.FileUtils.pathIsAbsolute(fileNameOrPath) || fileNameOrPath.indexOf("/") >= 0) { var errorFileNameOrPath = this._context.fileSystemWrapper.getStandardizedAbsolutePath(fileNameOrPath); throw new errors.InvalidOperationError("Could not find source file in project at the provided path: " + errorFileNameOrPath); } else throw new errors.InvalidOperationError("Could not find source file in project with the provided file name: " + fileNameOrSearchFunction); } else throw new errors.InvalidOperationError("Could not find source file in project based on the provided condition."); }; Project.prototype.getSourceFile = function (fileNameOrSearchFunction) { var filePathOrSearchFunction = getFilePathOrSearchFunction(this._context.fileSystemWrapper); if (typeof filePathOrSearchFunction === "string") { // when a file path is specified, return even source files not in the project return this._context.compilerFactory.getSourceFileFromCacheFromFilePath(filePathOrSearchFunction); } return utils_1.ArrayUtils.find(this._getProjectSourceFilesByDirectoryDepth(), filePathOrSearchFunction); function getFilePathOrSearchFunction(fileSystemWrapper) { if (fileNameOrSearchFunction instanceof Function) return fileNameOrSearchFunction; var fileNameOrPath = utils_1.FileUtils.standardizeSlashes(fileNameOrSearchFunction); if (utils_1.FileUtils.pathIsAbsolute(fileNameOrPath) || fileNameOrPath.indexOf("/") >= 0) return fileSystemWrapper.getStandardizedAbsolutePath(fileNameOrPath); else return function (def) { return utils_1.FileUtils.pathEndsWith(def.getFilePath(), fileNameOrPath); }; } }; Project.prototype.getSourceFiles = function (globPatterns) { var _a = this._context, compilerFactory = _a.compilerFactory, fileSystemWrapper = _a.fileSystemWrapper; var sourceFiles = this._getProjectSourceFilesByDirectoryDepth(); if (typeof globPatterns === "string" || globPatterns instanceof Array) return utils_1.ArrayUtils.from(getFilteredSourceFiles()); else return utils_1.ArrayUtils.from(sourceFiles); function getFilteredSourceFiles() { function getSourceFilePaths() { var e_5, _a, sourceFiles_1, sourceFiles_1_1, sourceFile, e_5_1; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 5, 6, 7]); sourceFiles_1 = tslib_1.__values(sourceFiles), sourceFiles_1_1 = sourceFiles_1.next(); _b.label = 1; case 1: if (!!sourceFiles_1_1.done) return [3 /*break*/, 4]; sourceFile = sourceFiles_1_1.value; return [4 /*yield*/, sourceFile.getFilePath()]; case 2: _b.sent(); _b.label = 3; case 3: sourceFiles_1_1 = sourceFiles_1.next(); return [3 /*break*/, 1]; case 4: return [3 /*break*/, 7]; case 5: e_5_1 = _b.sent(); e_5 = { error: e_5_1 }; return [3 /*break*/, 7]; case 6: try { if (sourceFiles_1_1 && !sourceFiles_1_1.done && (_a = sourceFiles_1.return)) _a.call(sourceFiles_1); } finally { if (e_5) throw e_5.error; } return [7 /*endfinally*/]; case 7: return [2 /*return*/]; } }); } var e_4, _a, sourceFilePaths, matchedPaths, matchedPaths_1, matchedPaths_1_1, matchedPath, e_4_1; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: sourceFilePaths = Array.from(getSourceFilePaths()); matchedPaths = utils_1.matchGlobs(sourceFilePaths, globPatterns, fileSystemWrapper.getCurrentDirectory()); _b.label = 1; case 1: _b.trys.push([1, 6, 7, 8]); matchedPaths_1 = tslib_1.__values(matchedPaths), matchedPaths_1_1 = matchedPaths_1.next(); _b.label = 2; case 2: if (!!matchedPaths_1_1.done) return [3 /*break*/, 5]; matchedPath = matchedPaths_1_1.value; return [4 /*yield*/, compilerFactory.getSourceFileFromCacheFromFilePath(matchedPath)]; case 3: _b.sent(); _b.label = 4; case 4: matchedPaths_1_1 = matchedPaths_1.next(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 8]; case 6: e_4_1 = _b.sent(); e_4 = { error: e_4_1 }; return [3 /*break*/, 8]; case 7: try { if (matchedPaths_1_1 && !matchedPaths_1_1.done && (_a = matchedPaths_1.return)) _a.call(matchedPaths_1); } finally { if (e_4) throw e_4.error; } return [7 /*endfinally*/]; case 8: return [2 /*return*/]; } }); } }; /** @internal */ Project.prototype._getProjectSourceFilesByDirectoryDepth = function () { var e_6, _a, _b, compilerFactory, inProjectCoordinator, _c, _d, sourceFile, e_6_1; return tslib_1.__generator(this, function (_e) { switch (_e.label) { case 0: _b = this._context, compilerFactory = _b.compilerFactory, inProjectCoordinator = _b.inProjectCoordinator; _e.label = 1; case 1: _e.trys.push([1, 6, 7, 8]); _c = tslib_1.__values(compilerFactory.getSourceFilesByDirectoryDepth()), _d = _c.next(); _e.label = 2; case 2: if (!!_d.done) return [3 /*break*/, 5]; sourceFile = _d.value; if (!inProjectCoordinator.isSourceFileInProject(sourceFile)) return [3 /*break*/, 4]; return [4 /*yield*/, sourceFile]; case 3: _e.sent(); _e.label = 4; case 4: _d = _c.next(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 8]; case 6: e_6_1 = _e.sent(); e_6 = { error: e_6_1 }; return [3 /*break*/, 8]; case 7: try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_6) throw e_6.error; } return [7 /*endfinally*/]; case 8: return [2 /*return*/]; } }); }; /** @internal */ Project.prototype._getProjectDirectoriesByDirectoryDepth = function () { var e_7, _a, _b, compilerFactory, inProjectCoordinator, _c, _d, directory, e_7_1; return tslib_1.__generator(this, function (_e) { switch (_e.label) { case 0: _b = this._context, compilerFactory = _b.compilerFactory, inProjectCoordinator = _b.inProjectCoordinator; _e.label = 1; case 1: _e.trys.push([1, 6, 7, 8]); _c = tslib_1.__values(compilerFactory.getDirectoriesByDepth()), _d = _c.next(); _e.label = 2; case 2: if (!!_d.done) return [3 /*break*/, 5]; directory = _d.value; if (!inProjectCoordinator.isDirectoryInProject(directory)) return [3 /*break*/, 4]; return [4 /*yield*/, directory]; case 3: _e.sent(); _e.label = 4; case 4: _d = _c.next(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 8]; case 6: e_7_1 = _e.sent(); e_7 = { error: e_7_1 }; return [3 /*break*/, 8]; case 7: try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_7) throw e_7.error; } return [7 /*endfinally*/]; case 8: return [2 /*return*/]; } }); }; /** * Gets the specified ambient module symbol or returns undefined if not found. * @param moduleName - The ambient module name with or without quotes. */ Project.prototype.getAmbientModule = function (moduleName) { moduleName = normalizeAmbientModuleName(moduleName); return utils_1.ArrayUtils.find(this.getAmbientModules(), function (s) { return s.getName() === moduleName; }); }; /** * Gets the specified ambient module symbol or throws if not found. * @param moduleName - The ambient module name with or without quotes. */ Project.prototype.getAmbientModuleOrThrow = function (moduleName) { return errors.throwIfNullOrUndefined(this.getAmbientModule(moduleName), function () { return "Could not find ambient module with name: " + normalizeAmbientModuleName(moduleName); }); }; /** * Gets the ambient module symbols (ex. modules in the @types folder or node_modules). */ Project.prototype.getAmbientModules = function () { return this.getTypeChecker().getAmbientModules(); }; /** * Saves all the unsaved source files to the file system and deletes all deleted files. */ Project.prototype.save = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this._context.fileSystemWrapper.flush()]; case 1: _a.sent(); return [4 /*yield*/, Promise.all(this._getUnsavedSourceFiles().map(function (f) { return f.save(); }))]; case 2: _a.sent(); return [2 /*return*/]; } }); }); }; /** * Synchronously saves all the unsaved source files to the file system and deletes all deleted files. * * Remarks: This might be very slow compared to the asynchronous version if there are a lot of files. */ Project.prototype.saveSync = function () { var e_8, _a; this._context.fileSystemWrapper.flushSync(); try { // 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 (var _b = tslib_1.__values(this._getUnsavedSourceFiles()), _c = _b.next(); !_c.done; _c = _b.next()) { var file = _c.value; file.saveSync(); } } catch (e_8_1) { e_8 = { error: e_8_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_8) throw e_8.error; } } }; /** * Enables logging to the console. * @param enabled - Enabled. */ Project.prototype.enableLogging = function (enabled) { if (enabled === void 0) { enabled = true; } this._context.logger.setEnabled(enabled); }; Project.prototype._getUnsavedSourceFiles = function () { return utils_1.ArrayUtils.from(getUnsavedIterator(this._context.compilerFactory.getSourceFilesByDirectoryDepth())); function getUnsavedIterator(sourceFiles) { var e_9, _a, sourceFiles_2, sourceFiles_2_1, sourceFile, e_9_1; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 5, 6, 7]); sourceFiles_2 = tslib_1.__values(sourceFiles), sourceFiles_2_1 = sourceFiles_2.next(); _b.label = 1; case 1: if (!!sourceFiles_2_1.done) return [3 /*break*/, 4]; sourceFile = sourceFiles_2_1.value; if (!!sourceFile.isSaved()) return [3 /*break*/, 3]; return [4 /*yield*/, sourceFile]; case 2: _b.sent(); _b.label = 3; case 3: sourceFiles_2_1 = sourceFiles_2.next(); return [3 /*break*/, 1]; case 4: return [3 /*break*/, 7]; case 5: e_9_1 = _b.sent(); e_9 = { error: e_9_1 }; return [3 /*break*/, 7]; case 6: try { if (sourceFiles_2_1 && !sourceFiles_2_1.done && (_a = sourceFiles_2.return)) _a.call(sourceFiles_2); } finally { if (e_9) throw e_9.error; } return [7 /*endfinally*/]; case 7: return [2 /*return*/]; } }); } }; /** * Gets the pre-emit diagnostics. */ Project.prototype.getPreEmitDiagnostics = function () { return this._context.getPreEmitDiagnostics(); }; /** * Gets the language service. */ Project.prototype.getLanguageService = function () { return this._context.languageService; }; /** * Gets the program. */ Project.prototype.getProgram = function () { return this._context.program; }; /** * Gets the type checker. */ Project.prototype.getTypeChecker = function () { return this._context.typeChecker; }; /** * Gets the file system. */ Project.prototype.getFileSystem = function () { return this._context.fileSystemWrapper.getFileSystem(); }; /** * Emits all the source files. * @param emitOptions - Optional emit options. */ Project.prototype.emit = function (emitOptions) { if (emitOptions === void 0) { emitOptions = {}; } return this._context.program.emit(emitOptions); }; /** * Emits all the source files to memory. * @param emitOptions - Optional emit options. */ Project.prototype.emitToMemory = function (emitOptions) { if (emitOptions === void 0) { emitOptions = {}; } return this._context.program.emitToMemory(emitOptions); }; /** * Gets the compiler options. */ Project.prototype.getCompilerOptions = function () { return this._context.compilerOptions.get(); }; /** * Creates a writer with the current manipulation settings. * @remarks Generally it's best to use a provided writer, but this may be useful in some scenarios. */ Project.prototype.createWriter = function () { return this._context.createWriter(); }; Project.prototype.forgetNodesCreatedInBlock = function (block) { return this._context.compilerFactory.forgetNodesCreatedInBlock(block); }; /** * Formats an array of diagnostics with their color and context into a string. * @param diagnostics - Diagnostics to get a string of. * @param options - Collection of options. For exmaple, the new line character to use (defaults to the OS' new line character). */ Project.prototype.formatDiagnosticsWithColorAndContext = function (diagnostics, opts) { var _this = this; if (opts === void 0) { opts = {}; } return typescript_1.ts.formatDiagnosticsWithColorAndContext(diagnostics.map(function (d) { return d.compilerObject; }), { getCurrentDirectory: function () { return _this._context.fileSystemWrapper.getCurrentDirectory(); }, getCanonicalFileName: function (fileName) { return fileName; }, getNewLine: function () { return opts.newLineChar || require("os").EOL; } }); }; /** * Applies the given file text changes to this project. This modifies and possibly creates new SourceFiles. * * WARNING: This will forget any previously navigated descendant nodes of changed files. It's best to do * this when you're all done. * @param fileTextChanges - Collections of file changes to apply to this project. * @param options - Options for applying the text changes. */ Project.prototype.applyFileTextChanges = function (fileTextChanges, options) { if (options === void 0) { options = {}; } var e_10, _a; try { for (var fileTextChanges_1 = tslib_1.__values(fileTextChanges), fileTextChanges_1_1 = fileTextChanges_1.next(); !fileTextChanges_1_1.done; fileTextChanges_1_1 = fileTextChanges_1.next()) { var fileTextChange = fileTextChanges_1_1.value; var file = this.getSourceFile(fileTextChange.getFilePath()); if (fileTextChange.isNewFile() && file != null && !options.overwrite) { throw new errors.InvalidOperationError("Cannot apply file text change for creating a new file when the " + ("file exists at path " + fileTextChange.getFilePath() + ". Did you mean to provide the overwrite option?")); } if (fileTextChange.isNewFile()) file = this.createSourceFile(fileTextChange.getFilePath(), "", { overwrite: options.overwrite }); else if (file == null) { throw new errors.InvalidOperationError("Cannot apply file text change to modify existing file " + ("that doesn't exist at path: " + fileTextChange.getFilePath())); } file.applyTextChanges(fileTextChange.getTextChanges()); } } catch (e_10_1) { e_10 = { error: e_10_1 }; } finally { try { if (fileTextChanges_1_1 && !fileTextChanges_1_1.done && (_a = fileTextChanges_1.return)) _a.call(fileTextChanges_1); } finally { if (e_10) throw e_10.error; } } }; return Project; }()); exports.Project = Project; function normalizeAmbientModuleName(moduleName) { if (isQuote(moduleName[0]) && isQuote(moduleName[moduleName.length - 1])) moduleName = moduleName.substring(1, moduleName.length - 1); return "\"" + moduleName + "\""; function isQuote(char) { return char === "\"" || char === "'"; } }