UNPKG

ts-simple-ast

Version:

TypeScript compiler wrapper for static analysis and code manipulation.

184 lines (183 loc) 8.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var utils_1 = require("../utils"); /** * Holds information about whether source files or directories are in the project. * * todo: Move this to a different folder. */ var InProjectCoordinator = /** @class */ (function () { function InProjectCoordinator(compilerFactory) { var _this = this; this.compilerFactory = compilerFactory; this.notInProjectFiles = utils_1.createHashSet(); compilerFactory.onSourceFileRemoved(function (sourceFile) { _this.notInProjectFiles.delete(sourceFile); }); } /** Sets the source file as not being in the project. */ InProjectCoordinator.prototype.setSourceFileNotInProject = function (sourceFile) { this.notInProjectFiles.add(sourceFile); sourceFile._inProject = false; }; /** Marks the specified source file being included in the project. */ InProjectCoordinator.prototype.markSourceFileAsInProject = function (sourceFile) { if (this.isSourceFileInProject(sourceFile)) return; this._internalMarkSourceFileAsInProject(sourceFile); this.notInProjectFiles.delete(sourceFile); }; /** * Marks source files not in a not in project node_modules folder as being in the project. * @returns Source files that were marked as being in the project. */ InProjectCoordinator.prototype.markSourceFilesAsInProjectForResolution = function () { var e_1, _a; var nodeModulesSearchName = "/node_modules/"; var compilerFactory = this.compilerFactory; var changedSourceFiles = []; var unchangedSourceFiles = []; try { for (var _b = tslib_1.__values(tslib_1.__spread(this.notInProjectFiles.values())), _c = _b.next(); !_c.done; _c = _b.next()) { var sourceFile = _c.value; if (shouldMarkInProject(sourceFile)) { this._internalMarkSourceFileAsInProject(sourceFile); this.notInProjectFiles.delete(sourceFile); changedSourceFiles.push(sourceFile); } else { unchangedSourceFiles.push(sourceFile); } } } 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 { changedSourceFiles: changedSourceFiles, unchangedSourceFiles: unchangedSourceFiles }; function shouldMarkInProject(sourceFile) { // check if there's a node_modules directory (use the closest one) var filePath = sourceFile.getFilePath(); var index = filePath.toLowerCase().lastIndexOf(nodeModulesSearchName); if (index === -1) return true; // see if the node_modules directory is in the project var nodeModulesPath = filePath.substring(0, index + nodeModulesSearchName.length - 1); // remove last slash var nodeModulesDir = compilerFactory.getDirectoryFromCacheOnlyIfInCache(nodeModulesPath); if (nodeModulesDir != null && nodeModulesDir._isInProject()) return true; // see if there's a directory between this and the node_modules directory that's in the project var directory = sourceFile.getDirectory(); while (directory != null && directory.getPath() !== nodeModulesPath) { if (directory._isInProject()) return true; directory = compilerFactory.getDirectoryFromCacheOnlyIfInCache(utils_1.FileUtils.getDirPath(directory.getPath())); } // otherwise, don't mark it as in the project return false; } }; InProjectCoordinator.prototype._internalMarkSourceFileAsInProject = function (sourceFile) { sourceFile._inProject = true; this.markDirectoryAsInProject(sourceFile.getDirectory()); }; /** Checks if the specified source file is in the project. */ InProjectCoordinator.prototype.isSourceFileInProject = function (sourceFile) { return sourceFile._inProject === true; }; /** Sets the directory and files as not being in the project for testing. */ InProjectCoordinator.prototype.setDirectoryAndFilesAsNotInProjectForTesting = function (directory) { var e_2, _a, e_3, _b; try { for (var _c = tslib_1.__values(directory.getDirectories()), _d = _c.next(); !_d.done; _d = _c.next()) { var subDir = _d.value; this.setDirectoryAndFilesAsNotInProjectForTesting(subDir); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_2) throw e_2.error; } } try { for (var _e = tslib_1.__values(directory.getSourceFiles()), _f = _e.next(); !_f.done; _f = _e.next()) { var file = _f.value; delete file._inProject; this.notInProjectFiles.add(file); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_f && !_f.done && (_b = _e.return)) _b.call(_e); } finally { if (e_3) throw e_3.error; } } delete directory._inProject; }; /** Marks the specified directory as being in the project. */ InProjectCoordinator.prototype.markDirectoryAsInProject = function (directory) { if (this.isDirectoryInProject(directory)) return; var inProjectCoordinator = this; var compilerFactory = this.compilerFactory; directory._inProject = true; markAncestorDirs(directory); function markAncestorDirs(dir) { var e_4, _a; var ancestorDirs = utils_1.ArrayUtils.from(getAncestorsUpToOneInProject(dir)); // only mark the ancestor directories as being in the project if the top one is in the project var topAncestor = ancestorDirs[ancestorDirs.length - 1]; if (topAncestor == null || !inProjectCoordinator.isDirectoryInProject(topAncestor)) return; try { for (var ancestorDirs_1 = tslib_1.__values(ancestorDirs), ancestorDirs_1_1 = ancestorDirs_1.next(); !ancestorDirs_1_1.done; ancestorDirs_1_1 = ancestorDirs_1.next()) { var ancestorDir = ancestorDirs_1_1.value; ancestorDir._inProject = true; } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (ancestorDirs_1_1 && !ancestorDirs_1_1.done && (_a = ancestorDirs_1.return)) _a.call(ancestorDirs_1); } finally { if (e_4) throw e_4.error; } } } function getAncestorsUpToOneInProject(dir) { var parentDirPath, parentDir; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (utils_1.FileUtils.isRootDirPath(dir.getPath())) return [2 /*return*/]; parentDirPath = utils_1.FileUtils.getDirPath(dir.getPath()); parentDir = compilerFactory.getDirectoryFromCacheOnlyIfInCache(parentDirPath); if (parentDir == null) return [2 /*return*/]; return [4 /*yield*/, parentDir]; case 1: _a.sent(); if (!!inProjectCoordinator.isDirectoryInProject(parentDir)) return [3 /*break*/, 3]; return [5 /*yield**/, tslib_1.__values(getAncestorsUpToOneInProject(parentDir))]; case 2: _a.sent(); _a.label = 3; case 3: return [2 /*return*/]; } }); } }; /** Checks if the specified directory is in the project. */ InProjectCoordinator.prototype.isDirectoryInProject = function (directory) { return directory._inProject === true; }; return InProjectCoordinator; }()); exports.InProjectCoordinator = InProjectCoordinator;