UNPKG

ts-simple-ast

Version:

TypeScript compiler wrapper for static analysis and code manipulation.

960 lines (959 loc) 45.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var errors = require("../errors"); var utils_1 = require("../utils"); var Directory = /** @class */ (function () { function Directory(path) { this.path = path; this.operations = []; this.inboundOperations = []; this.isDeleted = false; this.wasEverDeleted = false; this.childDirs = new utils_1.SortedKeyValueArray(function (item) { return item.path; }, utils_1.LocaleStringComparer.instance); } Directory.prototype.getExternalOperations = function () { var _this = this; return tslib_1.__spread(utils_1.ArrayUtils.flatten(this.getAncestors().map(function (a) { return getMoveCopyOrDeleteOperations(a); })).filter(function (o) { return isAncestorAffectedOperation(_this, o); }), utils_1.ArrayUtils.flatten(tslib_1.__spread([this], this.getDescendants()).map(function (d) { return getMoveOrCopyOperations(d); })).filter(function (o) { return !isInternalOperation(_this, o); })); function isInternalOperation(thisDir, operation) { return operation.oldDir.isDescendantOrEqual(thisDir) && operation.newDir.isDescendantOrEqual(thisDir); } function isAncestorAffectedOperation(thisDir, operation) { switch (operation.kind) { case "move": case "copy": return thisDir.isDescendantOrEqual(operation.oldDir) || thisDir.isDescendantOrEqual(operation.newDir); case "deleteDir": return thisDir.isDescendantOrEqual(operation.dir); default: throw errors.getNotImplementedForNeverValueError(operation); } } function getMoveOrCopyOperations(dir) { return dir.operations.filter(function (o) { return o.kind === "move" || o.kind === "copy"; }); } function getMoveCopyOrDeleteOperations(dir) { return dir.operations.filter(function (o) { return o.kind === "move" || o.kind === "deleteDir" || o.kind === "copy"; }); } }; Directory.prototype.isDescendantOrEqual = function (directory) { return this.isDescendant(directory) || this === directory; }; Directory.prototype.isDescendant = function (directory) { return utils_1.FileUtils.pathStartsWith(this.path, directory.path); }; Directory.prototype.getIsDeleted = function () { return this.isDeleted; }; Directory.prototype.getWasEverDeleted = function () { var e_1, _a; if (this.wasEverDeleted) return true; try { for (var _b = tslib_1.__values(this.getAncestorsIterator()), _c = _b.next(); !_c.done; _c = _b.next()) { var ancestor = _c.value; if (ancestor.wasEverDeleted) return true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } return false; }; Directory.prototype.setIsDeleted = function (isDeleted) { var e_2, _a; if (this.isDeleted === isDeleted) return; if (isDeleted) { this.wasEverDeleted = true; try { for (var _b = tslib_1.__values(this.childDirs.entries()), _c = _b.next(); !_c.done; _c = _b.next()) { var child = _c.value; child.setIsDeleted(true); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } } else { if (this.parent != null) this.parent.setIsDeleted(false); } this.isDeleted = isDeleted; }; Directory.prototype.getParent = function () { return this.parent; }; Directory.prototype.setParent = function (parent) { if (this.parent != null) throw new errors.InvalidOperationError("For some reason, a parent was being set when the directory already had a parent. Please open an issue."); this.parent = parent; parent.childDirs.set(this); if (parent.isDeleted && !this.isDeleted) parent.setIsDeleted(false); }; Directory.prototype.removeParent = function () { var parent = this.parent; if (parent == null) return; parent.childDirs.removeByValue(this); this.parent = undefined; }; Directory.prototype.getAncestors = function () { return utils_1.ArrayUtils.from(this.getAncestorsIterator()); }; Directory.prototype.getAncestorsIterator = function () { var parent; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: parent = this.parent; _a.label = 1; case 1: if (!(parent != null)) return [3 /*break*/, 3]; return [4 /*yield*/, parent]; case 2: _a.sent(); parent = parent.parent; return [3 /*break*/, 1]; case 3: return [2 /*return*/]; } }); }; Directory.prototype.getDescendants = function () { var e_3, _a; var descendants = []; try { for (var _b = tslib_1.__values(this.childDirs.entries()), _c = _b.next(); !_c.done; _c = _b.next()) { var child = _c.value; descendants.push(child); descendants.push.apply(descendants, tslib_1.__spread(child.getDescendants())); } } 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 descendants; }; Directory.prototype.isFileQueuedForDelete = function (filePath) { return this.hasOperation(function (operation) { return operation.kind === "deleteFile" && operation.filePath === filePath; }); }; Directory.prototype.hasOperation = function (operationMatches) { var e_4, _a; try { for (var _b = tslib_1.__values(this.operations), _c = _b.next(); !_c.done; _c = _b.next()) { var operation = _c.value; if (operationMatches(operation)) return true; } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_4) throw e_4.error; } } return false; }; Directory.prototype.dequeueFileDelete = function (filePath) { this.removeMatchingOperations(function (operation) { return operation.kind === "deleteFile" && operation.filePath === filePath; }); }; Directory.prototype.dequeueDirDelete = function (dirPath) { this.removeMatchingOperations(function (operation) { return operation.kind === "deleteDir" && operation.dir.path === dirPath; }); }; Directory.prototype.isRootDir = function () { return utils_1.FileUtils.isRootDirPath(this.path); }; Directory.prototype.removeMatchingOperations = function (operationMatches) { utils_1.ArrayUtils.removeAll(this.operations, operationMatches); }; return Directory; }()); /** * File system host wrapper that allows queuing deletions to the file system. */ var FileSystemWrapper = /** @class */ (function () { function FileSystemWrapper(fileSystem) { this.fileSystem = fileSystem; this.directories = new utils_1.KeyValueCache(); this.operationIndex = 0; } FileSystemWrapper.prototype.queueFileDelete = function (filePath) { filePath = this.getStandardizedAbsolutePath(filePath); var parentDir = this.getParentDirectory(filePath); parentDir.operations.push({ kind: "deleteFile", index: this.getNextOperationIndex(), filePath: filePath }); }; FileSystemWrapper.prototype.removeFileDelete = function (filePath) { filePath = this.getStandardizedAbsolutePath(filePath); this.getParentDirectory(filePath).dequeueFileDelete(filePath); }; FileSystemWrapper.prototype.queueMkdir = function (dirPath) { dirPath = this.getStandardizedAbsolutePath(dirPath); var dir = this.getDirectory(dirPath); dir.setIsDeleted(false); var parentDir = this.getParentDirectory(dirPath); parentDir.operations.push({ kind: "mkdir", index: this.getNextOperationIndex(), dir: dir }); }; FileSystemWrapper.prototype.queueDirectoryDelete = function (dirPath) { dirPath = this.getStandardizedAbsolutePath(dirPath); var dir = this.getDirectory(dirPath); dir.setIsDeleted(true); var parentDir = this.getParentDirectory(dirPath); parentDir.operations.push({ kind: "deleteDir", index: this.getNextOperationIndex(), dir: dir }); }; FileSystemWrapper.prototype.queueMoveDirectory = function (srcPath, destPath) { // todo: tests for the root directory srcPath = this.getStandardizedAbsolutePath(srcPath); destPath = this.getStandardizedAbsolutePath(destPath); var parentDir = this.getParentDirectory(srcPath); var moveDir = this.getDirectory(srcPath); var destinationDir = this.getDirectory(destPath); var moveOperation = { kind: "move", index: this.getNextOperationIndex(), oldDir: moveDir, newDir: destinationDir }; parentDir.operations.push(moveOperation); (destinationDir.getParent() || destinationDir).inboundOperations.push(moveOperation); moveDir.setIsDeleted(true); }; FileSystemWrapper.prototype.queueCopyDirectory = function (srcPath, destPath) { srcPath = this.getStandardizedAbsolutePath(srcPath); destPath = this.getStandardizedAbsolutePath(destPath); var parentDir = this.getParentDirectory(srcPath); var copyDir = this.getDirectory(srcPath); var destinationDir = this.getDirectory(destPath); var copyOperation = { kind: "copy", index: this.getNextOperationIndex(), oldDir: copyDir, newDir: destinationDir }; parentDir.operations.push(copyOperation); (destinationDir.getParent() || destinationDir).inboundOperations.push(copyOperation); }; FileSystemWrapper.prototype.flush = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var e_5, _a, operations, operations_1, operations_1_1, operation, e_5_1; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: operations = this.getAndClearOperations(); _b.label = 1; case 1: _b.trys.push([1, 6, 7, 8]); operations_1 = tslib_1.__values(operations), operations_1_1 = operations_1.next(); _b.label = 2; case 2: if (!!operations_1_1.done) return [3 /*break*/, 5]; operation = operations_1_1.value; return [4 /*yield*/, this.executeOperation(operation)]; case 3: _b.sent(); _b.label = 4; case 4: operations_1_1 = operations_1.next(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 8]; case 6: e_5_1 = _b.sent(); e_5 = { error: e_5_1 }; return [3 /*break*/, 8]; case 7: try { if (operations_1_1 && !operations_1_1.done && (_a = operations_1.return)) _a.call(operations_1); } finally { if (e_5) throw e_5.error; } return [7 /*endfinally*/]; case 8: return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.flushSync = function () { var e_6, _a; try { for (var _b = tslib_1.__values(this.getAndClearOperations()), _c = _b.next(); !_c.done; _c = _b.next()) { var operation = _c.value; this.executeOperationSync(operation); } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_6) throw e_6.error; } } }; FileSystemWrapper.prototype.saveForDirectory = function (dirPath) { return tslib_1.__awaiter(this, void 0, void 0, function () { var e_7, _a, dir, operations, operations_2, operations_2_1, operation, e_7_1; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: dirPath = this.getStandardizedAbsolutePath(dirPath); dir = this.getDirectory(dirPath); this.throwIfHasExternalOperations(dir, "save directory"); operations = this.getAndClearOperationsForDir(dir); // await after the state is set return [4 /*yield*/, this.ensureDirectoryExists(dirPath)]; case 1: // await after the state is set _b.sent(); _b.label = 2; case 2: _b.trys.push([2, 7, 8, 9]); operations_2 = tslib_1.__values(operations), operations_2_1 = operations_2.next(); _b.label = 3; case 3: if (!!operations_2_1.done) return [3 /*break*/, 6]; operation = operations_2_1.value; return [4 /*yield*/, this.executeOperation(operation)]; case 4: _b.sent(); _b.label = 5; case 5: operations_2_1 = operations_2.next(); return [3 /*break*/, 3]; case 6: return [3 /*break*/, 9]; case 7: e_7_1 = _b.sent(); e_7 = { error: e_7_1 }; return [3 /*break*/, 9]; case 8: try { if (operations_2_1 && !operations_2_1.done && (_a = operations_2.return)) _a.call(operations_2); } finally { if (e_7) throw e_7.error; } return [7 /*endfinally*/]; case 9: return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.saveForDirectorySync = function (dirPath) { var e_8, _a; dirPath = this.getStandardizedAbsolutePath(dirPath); var dir = this.getDirectory(dirPath); this.throwIfHasExternalOperations(dir, "save directory"); this.ensureDirectoryExistsSync(dirPath); try { for (var _b = tslib_1.__values(this.getAndClearOperationsForDir(dir)), _c = _b.next(); !_c.done; _c = _b.next()) { var operation = _c.value; this.executeOperationSync(operation); } } 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; } } }; FileSystemWrapper.prototype.getAndClearOperationsForDir = function (dir) { var e_9, _a; var operations = getAndClearParentMkDirOperations(dir.getParent(), dir); try { for (var _b = tslib_1.__values(tslib_1.__spread([dir], dir.getDescendants())), _c = _b.next(); !_c.done; _c = _b.next()) { var currentDir = _c.value; operations.push.apply(operations, tslib_1.__spread(currentDir.operations)); } } catch (e_9_1) { e_9 = { error: e_9_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_9) throw e_9.error; } } utils_1.ArrayUtils.sortByProperty(operations, function (item) { return item.index; }); this.removeDirAndSubDirs(dir); return operations; function getAndClearParentMkDirOperations(parentDir, childDir) { if (parentDir == null) return []; var parentOperations = utils_1.ArrayUtils.removeAll(parentDir.operations, function (operation) { return operation.kind === "mkdir" && operation.dir === childDir; }); return tslib_1.__spread(parentOperations, getAndClearParentMkDirOperations(parentDir.getParent(), parentDir)); } }; FileSystemWrapper.prototype.executeOperation = function (operation) { return tslib_1.__awaiter(this, void 0, void 0, function () { var _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: _a = operation.kind; switch (_a) { case "deleteDir": return [3 /*break*/, 1]; case "deleteFile": return [3 /*break*/, 3]; case "move": return [3 /*break*/, 5]; case "copy": return [3 /*break*/, 7]; case "mkdir": return [3 /*break*/, 9]; } return [3 /*break*/, 11]; case 1: return [4 /*yield*/, this.deleteSuppressNotFound(operation.dir.path)]; case 2: _b.sent(); return [3 /*break*/, 12]; case 3: return [4 /*yield*/, this.deleteSuppressNotFound(operation.filePath)]; case 4: _b.sent(); return [3 /*break*/, 12]; case 5: return [4 /*yield*/, this.fileSystem.move(operation.oldDir.path, operation.newDir.path)]; case 6: _b.sent(); return [3 /*break*/, 12]; case 7: return [4 /*yield*/, this.fileSystem.copy(operation.oldDir.path, operation.newDir.path)]; case 8: _b.sent(); return [3 /*break*/, 12]; case 9: return [4 /*yield*/, this.fileSystem.mkdir(operation.dir.path)]; case 10: _b.sent(); return [3 /*break*/, 12]; case 11: throw errors.getNotImplementedForNeverValueError(operation); case 12: return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.executeOperationSync = function (operation) { switch (operation.kind) { case "deleteDir": this.deleteSuppressNotFoundSync(operation.dir.path); break; case "deleteFile": this.deleteSuppressNotFoundSync(operation.filePath); break; case "move": this.fileSystem.moveSync(operation.oldDir.path, operation.newDir.path); break; case "copy": this.fileSystem.copySync(operation.oldDir.path, operation.newDir.path); break; case "mkdir": this.fileSystem.mkdirSync(operation.dir.path); break; default: throw errors.getNotImplementedForNeverValueError(operation); } }; FileSystemWrapper.prototype.getAndClearOperations = function () { var e_10, _a; var operations = []; try { for (var _b = tslib_1.__values(this.directories.getValues()), _c = _b.next(); !_c.done; _c = _b.next()) { var dir = _c.value; operations.push.apply(operations, tslib_1.__spread(dir.operations)); } } catch (e_10_1) { e_10 = { error: e_10_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_10) throw e_10.error; } } utils_1.ArrayUtils.sortByProperty(operations, function (item) { return item.index; }); this.directories.clear(); return operations; }; FileSystemWrapper.prototype.moveFileImmediately = function (oldFilePath, newFilePath, fileText) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: oldFilePath = this.getStandardizedAbsolutePath(oldFilePath); newFilePath = this.getStandardizedAbsolutePath(newFilePath); this.throwIfHasExternalOperations(this.getParentDirectory(oldFilePath), "move file"); this.throwIfHasExternalOperations(this.getParentDirectory(newFilePath), "move file"); return [4 /*yield*/, this.deleteFileImmediately(oldFilePath)]; case 1: _a.sent(); return [4 /*yield*/, this.writeFile(newFilePath, fileText)]; case 2: _a.sent(); return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.moveFileImmediatelySync = function (oldFilePath, newFilePath, fileText) { oldFilePath = this.getStandardizedAbsolutePath(oldFilePath); newFilePath = this.getStandardizedAbsolutePath(newFilePath); this.throwIfHasExternalOperations(this.getParentDirectory(oldFilePath), "move file"); this.throwIfHasExternalOperations(this.getParentDirectory(newFilePath), "move file"); this.deleteFileImmediatelySync(oldFilePath); this.writeFileSync(newFilePath, fileText); }; FileSystemWrapper.prototype.deleteFileImmediately = function (filePath) { return tslib_1.__awaiter(this, void 0, void 0, function () { var dir, err_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: filePath = this.getStandardizedAbsolutePath(filePath); dir = this.getParentDirectory(filePath); this.throwIfHasExternalOperations(dir, "delete file"); dir.dequeueFileDelete(filePath); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.deleteSuppressNotFound(filePath)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_1 = _a.sent(); this.queueFileDelete(filePath); throw err_1; case 4: return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.deleteFileImmediatelySync = function (filePath) { filePath = this.getStandardizedAbsolutePath(filePath); var dir = this.getParentDirectory(filePath); this.throwIfHasExternalOperations(dir, "delete file"); dir.dequeueFileDelete(filePath); try { this.deleteSuppressNotFoundSync(filePath); } catch (err) { this.queueFileDelete(filePath); throw err; } }; FileSystemWrapper.prototype.copyDirectoryImmediately = function (srcDirPath, destDirPath) { return tslib_1.__awaiter(this, void 0, void 0, function () { var srcDir, destDir, saveTask; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: srcDirPath = this.getStandardizedAbsolutePath(srcDirPath); destDirPath = this.getStandardizedAbsolutePath(destDirPath); srcDir = this.getDirectory(srcDirPath); destDir = this.getDirectory(destDirPath); this.throwIfHasExternalOperations(srcDir, "copy directory"); this.throwIfHasExternalOperations(destDir, "copy directory"); saveTask = Promise.all([this.saveForDirectory(srcDirPath), this.saveForDirectory(destDirPath)]); this.removeDirAndSubDirs(srcDir); // await after the state is set return [4 /*yield*/, saveTask]; case 1: // await after the state is set _a.sent(); return [4 /*yield*/, this.fileSystem.copy(srcDirPath, destDirPath)]; case 2: _a.sent(); return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.copyDirectoryImmediatelySync = function (srcDirPath, destDirPath) { srcDirPath = this.getStandardizedAbsolutePath(srcDirPath); destDirPath = this.getStandardizedAbsolutePath(destDirPath); var srcDir = this.getDirectory(srcDirPath); var destDir = this.getDirectory(destDirPath); this.throwIfHasExternalOperations(srcDir, "copy directory"); this.throwIfHasExternalOperations(destDir, "copy directory"); this.saveForDirectorySync(srcDirPath); this.saveForDirectorySync(destDirPath); this.removeDirAndSubDirs(srcDir); this.fileSystem.copySync(srcDirPath, destDirPath); }; FileSystemWrapper.prototype.moveDirectoryImmediately = function (srcDirPath, destDirPath) { return tslib_1.__awaiter(this, void 0, void 0, function () { var srcDir, destDir, saveTask; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: srcDirPath = this.getStandardizedAbsolutePath(srcDirPath); destDirPath = this.getStandardizedAbsolutePath(destDirPath); srcDir = this.getDirectory(srcDirPath); destDir = this.getDirectory(destDirPath); this.throwIfHasExternalOperations(srcDir, "move directory"); this.throwIfHasExternalOperations(destDir, "move directory"); saveTask = Promise.all([this.saveForDirectory(srcDirPath), this.saveForDirectory(destDirPath)]); this.removeDirAndSubDirs(srcDir); // await after the state is set return [4 /*yield*/, saveTask]; case 1: // await after the state is set _a.sent(); return [4 /*yield*/, this.fileSystem.move(srcDirPath, destDirPath)]; case 2: _a.sent(); return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.moveDirectoryImmediatelySync = function (srcDirPath, destDirPath) { srcDirPath = this.getStandardizedAbsolutePath(srcDirPath); destDirPath = this.getStandardizedAbsolutePath(destDirPath); var srcDir = this.getDirectory(srcDirPath); var destDir = this.getDirectory(destDirPath); this.throwIfHasExternalOperations(srcDir, "move directory"); this.throwIfHasExternalOperations(destDir, "move directory"); this.saveForDirectorySync(srcDirPath); this.saveForDirectorySync(destDirPath); this.removeDirAndSubDirs(srcDir); this.fileSystem.moveSync(srcDirPath, destDirPath); }; FileSystemWrapper.prototype.deleteDirectoryImmediately = function (dirPath) { return tslib_1.__awaiter(this, void 0, void 0, function () { var dir, err_2; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: dirPath = this.getStandardizedAbsolutePath(dirPath); dir = this.getDirectory(dirPath); this.throwIfHasExternalOperations(dir, "delete"); this.removeDirAndSubDirs(dir); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.deleteSuppressNotFound(dirPath)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_2 = _a.sent(); this.addBackDirAndSubDirs(dir); this.queueDirectoryDelete(dirPath); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.deleteDirectoryImmediatelySync = function (dirPath) { dirPath = this.getStandardizedAbsolutePath(dirPath); var dir = this.getDirectory(dirPath); this.throwIfHasExternalOperations(dir, "delete"); this.removeDirAndSubDirs(dir); try { this.deleteSuppressNotFoundSync(dirPath); } catch (err) { this.addBackDirAndSubDirs(dir); this.queueDirectoryDelete(dirPath); } }; FileSystemWrapper.prototype.deleteSuppressNotFound = function (path) { return tslib_1.__awaiter(this, void 0, void 0, function () { var err_3; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); return [4 /*yield*/, this.fileSystem.delete(path)]; case 1: _a.sent(); return [3 /*break*/, 3]; case 2: err_3 = _a.sent(); if (!utils_1.FileUtils.isNotExistsError(err_3)) throw err_3; return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.deleteSuppressNotFoundSync = function (path) { try { this.fileSystem.deleteSync(path); } catch (err) { if (!utils_1.FileUtils.isNotExistsError(err)) throw err; } }; FileSystemWrapper.prototype.fileExistsSync = function (filePath) { filePath = this.getStandardizedAbsolutePath(filePath); if (this.isPathQueuedForDeletion(filePath)) return false; if (this.getParentDirectory(filePath).getWasEverDeleted()) return false; return this.fileSystem.fileExistsSync(filePath); }; FileSystemWrapper.prototype.directoryExistsSync = function (dirPath) { dirPath = this.getStandardizedAbsolutePath(dirPath); if (this.isPathQueuedForDeletion(dirPath)) return false; if (this.isPathDirectoryInQueueThatExists(dirPath)) return true; if (this.getDirectory(dirPath).getWasEverDeleted()) return false; return this.fileSystem.directoryExistsSync(dirPath); }; FileSystemWrapper.prototype.readFileSync = function (filePath, encoding) { filePath = this.getStandardizedAbsolutePath(filePath); if (this.isPathQueuedForDeletion(filePath)) throw new errors.InvalidOperationError("Cannot read file at " + filePath + " when it is queued for deletion."); if (this.getParentDirectory(filePath).getWasEverDeleted()) throw new errors.InvalidOperationError("Cannot read file at " + filePath + " because one of its ancestor directories was once deleted or moved."); return this.fileSystem.readFileSync(filePath, encoding); }; FileSystemWrapper.prototype.readDirSync = function (dirPath) { var _this = this; dirPath = this.getStandardizedAbsolutePath(dirPath); var dir = this.getDirectory(dirPath); if (dir.getIsDeleted()) throw new errors.InvalidOperationError("Cannot read directory at " + dirPath + " when it is queued for deletion."); if (dir.getWasEverDeleted()) throw new errors.InvalidOperationError("Cannot read directory at " + dirPath + " because one of its ancestor directories was once deleted or moved."); return this.fileSystem.readDirSync(dirPath).filter(function (path) { return !_this.isPathQueuedForDeletion(path) && !_this.isPathQueuedForDeletion(path); }); }; FileSystemWrapper.prototype.glob = function (patterns) { var _this = this; return this.fileSystem.glob(patterns).filter(function (path) { return !_this.isPathQueuedForDeletion(path); }); }; FileSystemWrapper.prototype.getFileSystem = function () { return this.fileSystem; }; FileSystemWrapper.prototype.getCurrentDirectory = function () { return this.fileSystem.getCurrentDirectory(); }; FileSystemWrapper.prototype.getStandardizedAbsolutePath = function (fileOrDirPath, relativeBase) { return utils_1.FileUtils.getStandardizedAbsolutePath(this.fileSystem, fileOrDirPath, relativeBase); }; FileSystemWrapper.prototype.readFileOrNotExists = function (filePath, encoding) { filePath = this.getStandardizedAbsolutePath(filePath); if (this.isPathQueuedForDeletion(filePath)) return false; return utils_1.FileUtils.readFileOrNotExists(this.fileSystem, filePath, encoding); }; FileSystemWrapper.prototype.readFileOrNotExistsSync = function (filePath, encoding) { filePath = this.getStandardizedAbsolutePath(filePath); if (this.isPathQueuedForDeletion(filePath)) return false; return utils_1.FileUtils.readFileOrNotExistsSync(this.fileSystem, filePath, encoding); }; FileSystemWrapper.prototype.writeFile = function (filePath, fileText) { return tslib_1.__awaiter(this, void 0, void 0, function () { var parentDir; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: filePath = this.getStandardizedAbsolutePath(filePath); parentDir = this.getParentDirectory(filePath); this.throwIfHasExternalOperations(parentDir, "write file"); parentDir.dequeueFileDelete(filePath); return [4 /*yield*/, this.ensureDirectoryExists(parentDir.path)]; case 1: _a.sent(); return [4 /*yield*/, this.fileSystem.writeFile(filePath, fileText)]; case 2: _a.sent(); return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.writeFileSync = function (filePath, fileText) { filePath = this.getStandardizedAbsolutePath(filePath); var parentDir = this.getParentDirectory(filePath); this.throwIfHasExternalOperations(parentDir, "write file"); parentDir.dequeueFileDelete(filePath); this.ensureDirectoryExistsSync(parentDir.path); this.fileSystem.writeFileSync(filePath, fileText); }; FileSystemWrapper.prototype.isPathDirectoryInQueueThatExists = function (path) { var pathDir = this.getDirectoryIfExists(path); return pathDir == null ? false : !pathDir.getIsDeleted(); }; FileSystemWrapper.prototype.isPathQueuedForDeletion = function (path) { // check if the provided path is a dir and if it's deleted var pathDir = this.getDirectoryIfExists(path); if (pathDir != null) return pathDir.getIsDeleted(); // check if the provided path is a file or if it or its parent is deleted var parentDir = this.getParentDirectory(path); return parentDir.isFileQueuedForDelete(path) || parentDir.getIsDeleted(); }; FileSystemWrapper.prototype.removeDirAndSubDirs = function (dir) { var e_11, _a; var originalParent = dir.getParent(); dir.removeParent(); try { for (var _b = tslib_1.__values(tslib_1.__spread([dir], dir.getDescendants())), _c = _b.next(); !_c.done; _c = _b.next()) { var dirToRemove = _c.value; this.directories.removeByKey(dirToRemove.path); } } catch (e_11_1) { e_11 = { error: e_11_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_11) throw e_11.error; } } if (originalParent != null) originalParent.dequeueDirDelete(dir.path); }; FileSystemWrapper.prototype.addBackDirAndSubDirs = function (dir) { var e_12, _a; try { for (var _b = tslib_1.__values(tslib_1.__spread([dir], dir.getDescendants())), _c = _b.next(); !_c.done; _c = _b.next()) { var dirToAdd = _c.value; this.directories.set(dirToAdd.path, dirToAdd); } } catch (e_12_1) { e_12 = { error: e_12_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_12) throw e_12.error; } } if (!dir.isRootDir()) dir.setParent(this.getParentDirectory(dir.path)); }; FileSystemWrapper.prototype.getNextOperationIndex = function () { return this.operationIndex++; }; FileSystemWrapper.prototype.getParentDirectory = function (filePath) { return this.getDirectory(utils_1.FileUtils.getDirPath(filePath)); }; FileSystemWrapper.prototype.getDirectoryIfExists = function (dirPath) { return this.directories.get(dirPath); }; FileSystemWrapper.prototype.getDirectory = function (dirPath) { var _this = this; var dir = this.directories.get(dirPath); if (dir != null) return dir; var getOrCreateDir = function (creatingDirPath) { return _this.directories.getOrCreate(creatingDirPath, function () { return new Directory(creatingDirPath); }); }; dir = getOrCreateDir(dirPath); var currentDirPath = dirPath; var currentDir = dir; while (!utils_1.FileUtils.isRootDirPath(currentDirPath)) { var nextDirPath = utils_1.FileUtils.getDirPath(currentDirPath); var hadNextDir = this.directories.has(nextDirPath); var nextDir = getOrCreateDir(nextDirPath); currentDir.setParent(nextDir); if (hadNextDir) return dir; currentDir = nextDir; currentDirPath = nextDirPath; } return dir; }; FileSystemWrapper.prototype.throwIfHasExternalOperations = function (dir, commandName) { var operations = dir.getExternalOperations(); if (operations.length === 0) return; throw new errors.InvalidOperationError(getErrorText()); function getErrorText() { var e_13, _a; var hasCopy = false; var errorText = "Cannot execute immediate operation '" + commandName + "' because of the following external operations:\n"; try { for (var operations_3 = tslib_1.__values(operations), operations_3_1 = operations_3.next(); !operations_3_1.done; operations_3_1 = operations_3.next()) { var operation = operations_3_1.value; if (operation.kind === "move") errorText += "\n* Move: " + operation.oldDir.path + " --> " + operation.newDir.path; else if (operation.kind === "copy") { errorText += "\n* Copy: " + operation.oldDir.path + " --> " + operation.newDir.path; hasCopy = true; } else if (operation.kind === "deleteDir") errorText += "\n* Delete: " + operation.dir.path; else { var expectNever = operation; errorText += "\n* Unknown operation: Please report this as a bug."; } } } catch (e_13_1) { e_13 = { error: e_13_1 }; } finally { try { if (operations_3_1 && !operations_3_1.done && (_a = operations_3.return)) _a.call(operations_3); } finally { if (e_13) throw e_13.error; } } if (hasCopy) errorText += "\n\nNote: Copy operations can be removed from external operations by setting `includeUntrackedFiles` to `false` when copying."; return errorText; } }; FileSystemWrapper.prototype.ensureDirectoryExists = function (dirPath) { return tslib_1.__awaiter(this, void 0, void 0, function () { var parentDirPath; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.fileSystem.directoryExists(dirPath)]; case 1: if (_a.sent()) return [2 /*return*/]; parentDirPath = utils_1.FileUtils.getDirPath(dirPath); if (!(parentDirPath !== dirPath && !utils_1.FileUtils.isRootDirPath(parentDirPath))) return [3 /*break*/, 3]; return [4 /*yield*/, this.ensureDirectoryExists(parentDirPath)]; case 2: _a.sent(); _a.label = 3; case 3: // make this directory this.removeMkDirOperationsForDir(dirPath); return [4 /*yield*/, this.fileSystem.mkdir(dirPath)]; case 4: _a.sent(); return [2 /*return*/]; } }); }); }; FileSystemWrapper.prototype.ensureDirectoryExistsSync = function (dirPath) { if (this.fileSystem.directoryExistsSync(dirPath)) return; // ensure the parent exists and is not the root var parentDirPath = utils_1.FileUtils.getDirPath(dirPath); if (parentDirPath !== dirPath && !utils_1.FileUtils.isRootDirPath(parentDirPath)) this.ensureDirectoryExistsSync(parentDirPath); // make this directory this.removeMkDirOperationsForDir(dirPath); this.fileSystem.mkdirSync(dirPath); }; FileSystemWrapper.prototype.removeMkDirOperationsForDir = function (dirPath) { var dir = this.getDirectory(dirPath); var parentDir = this.getParentDirectory(dirPath); utils_1.ArrayUtils.removeAll(parentDir.operations, function (operation) { return operation.kind === "mkdir" && operation.dir === dir; }); }; return FileSystemWrapper; }()); exports.FileSystemWrapper = FileSystemWrapper;