ts-simple-ast
Version:
TypeScript compiler wrapper for static analysis and code manipulation.
690 lines (689 loc) • 33.3 kB
JavaScript
"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 === "'";
}
}