From dcbd7b10f19037dc907774a8fc0877e316a6cd3c Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Sat, 15 Jul 2017 22:26:10 -0700 Subject: [PATCH] Combine the logic to find config file as well as the watch. This should speed up the file open scenarios where the file belongs to same configured project as we would use cache to answer those fileExists answers --- .../unittests/tsserverProjectSystem.ts | 16 +- src/harness/unittests/typingsInstaller.ts | 2 +- src/server/editorServices.ts | 216 ++++++++---------- src/server/project.ts | 4 - 4 files changed, 109 insertions(+), 129 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index e26df82731..e662e7b792 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -809,7 +809,9 @@ namespace ts.projectSystem { const project = projectService.inferredProjects[0]; checkFileNames("inferred project", project.getFileNames(), [appFile.path, libFile.path, moduleFile.path]); - checkWatchedFiles(host, ["/a/b/c/tsconfig.json", "/a/b/tsconfig.json", "/a/tsconfig.json", libFile.path, moduleFile.path]); + const configFileLocations = ["/a/b/c/", "/a/b/", "/a/", "/"]; + const configFiles = flatMap(configFileLocations, location => [location + "tsconfig.json", location + "jsconfig.json"]); + checkWatchedFiles(host, configFiles.concat(libFile.path, moduleFile.path)); }); it("can handle tsconfig file name with difference casing", () => { @@ -879,7 +881,8 @@ namespace ts.projectSystem { checkProjectActualFiles(project, [file1.path, libFile.path, file2.path, configFile.path]); checkProjectRootFiles(project, [file1.path, file2.path]); // watching all files except one that was open - checkWatchedFiles(host, [configFile.path, file2.path, libFile.path]); + // And also tsconfig files for the open files + checkWatchedFiles(host, [configFile.path, file2.path, libFile.path, "/a/b/c/tsconfig.json", "/a/b/c/jsconfig.json"]); checkWatchedDirectories(host, [getDirectoryPath(configFile.path)], /*recursive*/ true); }); @@ -899,15 +902,16 @@ namespace ts.projectSystem { projectService.openClientFile(commonFile2.path); checkNumberOfInferredProjects(projectService, 2); - checkWatchedFiles(host, [configFile.path, "/a/tsconfig.json", libFile.path]); + const configFileLocations = ["/", "/a/", "/a/b/"]; + const watchedFiles = flatMap(configFileLocations, location => [location + "tsconfig.json", location + "jsconfig.json"]).concat(libFile.path); + checkWatchedFiles(host, watchedFiles); // Add a tsconfig file host.reloadFS(filesWithConfig); host.checkTimeoutQueueLengthAndRun(1); checkNumberOfInferredProjects(projectService, 1); checkNumberOfConfiguredProjects(projectService, 1); - // watching all files except one that was open - checkWatchedFiles(host, [libFile.path, configFile.path, "/a/tsconfig.json"]); + checkWatchedFiles(host, watchedFiles); // remove the tsconfig file host.reloadFS(filesWithoutConfig); @@ -917,7 +921,7 @@ namespace ts.projectSystem { checkNumberOfInferredProjects(projectService, 2); checkNumberOfConfiguredProjects(projectService, 0); - checkWatchedFiles(host, ["/a/b/tsconfig.json", "/a/tsconfig.json", libFile.path]); + checkWatchedFiles(host, watchedFiles); }); it("add new files to a configured project without file list", () => { diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index c9617625cc..7fab4ffdcc 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -755,7 +755,7 @@ namespace ts.projectSystem { checkNumberOfProjects(projectService, { configuredProjects: 1 }); const p = configuredProjectAt(projectService, 0); checkProjectActualFiles(p, [app.path, jsconfig.path]); - checkWatchedFiles(host, [jsconfig.path, "/bower_components", "/node_modules", libFile.path]); + checkWatchedFiles(host, ["/tsconfig.json", jsconfig.path, "/bower_components", "/node_modules", libFile.path]); installer.installAll(/*expectedCount*/ 1); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index c2a7991392..c2b712c06a 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -252,7 +252,7 @@ namespace ts.server { WildCardDirectories = "Wild card directory", TypeRoot = "Type root of the project", ClosedScriptInfo = "Closed Script info", - ConfigFileForInferredRoot = "Config file for the root script info of the inferred project" + ConfigFileForOpenFile = "Config file changes for the open script info" } /* @internal */ @@ -266,12 +266,12 @@ namespace ts.server { OrphanScriptInfo = "Removing Orphan script info as part of cleanup", FileDeleted = "File was deleted", FileOpened = "File opened", - ConfigProjectCreated = "Config file project created" + ConfigProjectCreated = "Config file project created", + FileClosed = "File is closed" } const enum ConfigFileWatcherStatus { ReloadingFiles = "Reloading configured projects files", - NoAction = "No action on files", UpdatedCallback = "Updated the callback", TrackingFileAdded = "Tracking file added", TrackingFileRemoved = "Tracking file removed" @@ -282,7 +282,7 @@ namespace ts.server { type ConfigFileExistence = { exists: boolean; - trackingOpenFiles?: ScriptInfo[]; + trackingOpenFileSet?: Map; configFileWatcher?: FileWatcher; }; @@ -672,48 +672,31 @@ namespace ts.server { // Update the cached status // No action needed on tracking open files since the existing config file anyways didnt affect the tracking file configFilePresenceInfo.exists = false; - this.logTrackingFiles(project.getConfigFilePath(), configFilePresenceInfo, ConfigFileWatcherStatus.NoAction); this.removeProject(project); - // Reload the configured projects for these open files in the project as - // they could be held up by another config file somewhere in the parent directory - const orphanFiles = filter(this.openFiles, file => file.containingProjects.length === 0); - this.delayReloadConfiguredProjectForFiles(orphanFiles); + // Reload the configured projects for the open files in the map as they are affectected by this config file + this.logConfigFileWatch(project.getConfigFilePath(), configFilePresenceInfo, ConfigFileWatcherStatus.ReloadingFiles); + this.delayReloadConfiguredProjectForFiles(configFilePresenceInfo.trackingOpenFileSet); } else { + this.logConfigFileWatch(project.getConfigFilePath(), configFilePresenceInfo, ConfigFileWatcherStatus.ReloadingFiles); project.pendingReload = true; - this.logTrackingFiles(project.getConfigFilePath(), configFilePresenceInfo, ConfigFileWatcherStatus.ReloadingFiles); - if (configFilePresenceInfo.trackingOpenFiles) { - this.delayUpdateProjectGraph(project); - this.delayReloadConfiguredProjectForFiles(configFilePresenceInfo.trackingOpenFiles); - } - else { - this.delayUpdateProjectGraphAndInferredProjectsRefresh(project); - } + this.delayUpdateProjectGraph(project); + this.delayReloadConfiguredProjectForFiles(configFilePresenceInfo.trackingOpenFileSet); } } /** - * This is the callback function for the config file add/remove/change for the root in the inferred project + * This is the callback function for the config file add/remove/change at any location that matters to open + * script info but doesnt have configured project open for the config file */ - private onConfigFileAddedForInferredProject(configFileName: NormalizedPath, eventKind: FileWatcherEventKind) { + private onConfigFileChangeForOpenScriptInfo(configFileName: NormalizedPath, eventKind: FileWatcherEventKind) { // This callback is called only if we dont have config file project for this config file const cononicalConfigPath = normalizedPathToPath(configFileName, this.currentDirectory, this.toCanonicalFileName); const configFilePresenceInfo = this.mapOfConfigFilePresence.get(cononicalConfigPath); - - if (eventKind === FileWatcherEventKind.Deleted) { - // No action needed if the event was for deletion of the file - // - because the existing config file didnt affect the inferred project roots anyways - configFilePresenceInfo.exists = false; - this.logTrackingFiles(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.NoAction); - } - else { - // Either the config file was created or changed - // Reload the projects - configFilePresenceInfo.exists = true; - this.logTrackingFiles(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.ReloadingFiles); - this.delayReloadConfiguredProjectForFiles(configFilePresenceInfo.trackingOpenFiles); - } + configFilePresenceInfo.exists = (eventKind !== FileWatcherEventKind.Deleted); + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.ReloadingFiles); + this.delayReloadConfiguredProjectForFiles(configFilePresenceInfo.trackingOpenFileSet); } private removeProject(project: Project) { @@ -729,7 +712,7 @@ namespace ts.server { this.projectToSizeMap.delete((project as ExternalProject).externalProjectName); break; case ProjectKind.Configured: - // Update the map of mapOfKnownTsConfigFiles + this.setConfigFilePresenceByClosedConfigFile(project); this.configuredProjects.delete((project).canonicalConfigFilePath); this.projectToSizeMap.delete((project as ConfiguredProject).canonicalConfigFilePath); break; @@ -791,6 +774,7 @@ namespace ts.server { // because the user may chose to discard the buffer content before saving // to the disk, and the server's version of the file can be out of sync. info.close(); + this.stopWatchingConfigFileForScriptInfo(info); removeItemFromSet(this.openFiles, info); @@ -863,28 +847,24 @@ namespace ts.server { }); } - private configFileExists(configFileName: NormalizedPath) { + private configFileExists(configFileName: NormalizedPath, info: ScriptInfo) { const canonicalConfigFilePath = normalizedPathToPath(configFileName, this.currentDirectory, this.toCanonicalFileName); - const configFilePresenceInfo = this.mapOfConfigFilePresence.get(canonicalConfigFilePath); - if (configFilePresenceInfo) { - return configFilePresenceInfo.exists; - } - return this.host.fileExists(configFileName); + return this.watchConfigFileForScriptInfo(configFileName, canonicalConfigFilePath, info).exists; } private setConfigFilePresenceByNewConfiguredProject(project: ConfiguredProject) { const configFilePresenceInfo = this.mapOfConfigFilePresence.get(project.canonicalConfigFilePath); if (configFilePresenceInfo) { - configFilePresenceInfo.exists = true; + Debug.assert(configFilePresenceInfo.exists); // close existing watcher if (configFilePresenceInfo.configFileWatcher) { const configFileName = project.getConfigFilePath(); this.closeFileWatcher( - WatchType.ConfigFileForInferredRoot, /*project*/ undefined, configFileName, + WatchType.ConfigFileForOpenFile, /*project*/ undefined, configFileName, configFilePresenceInfo.configFileWatcher, WatcherCloseReason.ConfigProjectCreated ); configFilePresenceInfo.configFileWatcher = undefined; - this.logTrackingFiles(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.UpdatedCallback); + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.UpdatedCallback); } } else { @@ -893,17 +873,16 @@ namespace ts.server { } } - /* @internal */ - setConfigFilePresenceByClosedConfigFile(closedProject: ConfiguredProject) { + private setConfigFilePresenceByClosedConfigFile(closedProject: ConfiguredProject) { const configFilePresenceInfo = this.mapOfConfigFilePresence.get(closedProject.canonicalConfigFilePath); Debug.assert(!!configFilePresenceInfo); - if (configFilePresenceInfo.trackingOpenFiles) { + if (configFilePresenceInfo.trackingOpenFileSet) { const configFileName = closedProject.getConfigFilePath(); configFilePresenceInfo.configFileWatcher = this.addFileWatcher( - WatchType.ConfigFileForInferredRoot, /*project*/ undefined, configFileName, - (_filename, eventKind) => this.onConfigFileAddedForInferredProject(configFileName, eventKind) + WatchType.ConfigFileForOpenFile, /*project*/ undefined, configFileName, + (_filename, eventKind) => this.onConfigFileChangeForOpenScriptInfo(configFileName, eventKind) ); - this.logTrackingFiles(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.UpdatedCallback); + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.UpdatedCallback); } else { // There is no one tracking anymore. Remove the status @@ -911,85 +890,83 @@ namespace ts.server { } } - private logTrackingFiles(configFileName: NormalizedPath, configFilePresenceInfo: ConfigFileExistence, status: ConfigFileWatcherStatus) { - const watchType = configFilePresenceInfo.configFileWatcher ? WatchType.ConfigFileForInferredRoot : WatchType.ConfigFilePath; - const files = map(configFilePresenceInfo.trackingOpenFiles, info => info.fileName); + private logConfigFileWatch(configFileName: NormalizedPath, configFilePresenceInfo: ConfigFileExistence, status: ConfigFileWatcherStatus) { + const watchType = configFilePresenceInfo.configFileWatcher ? WatchType.ConfigFileForOpenFile : WatchType.ConfigFilePath; + const files = configFilePresenceInfo.trackingOpenFileSet ? + arrayFrom(configFilePresenceInfo.trackingOpenFileSet.keys(), key => + this.getScriptInfoForPath(key as Path).fileName) : + []; this.logger.info(`FileWatcher:: ${watchType}: File: ${configFileName} Currently Tracking for files: ${files} Status: ${status}`); } - private watchConfigFileForInferredRoot(configFileName: NormalizedPath, canonicalConfigFilePath: string, root: ScriptInfo) { + private watchConfigFileForScriptInfo(configFileName: NormalizedPath, canonicalConfigFilePath: string, info: ScriptInfo) { let configFilePresenceInfo = this.mapOfConfigFilePresence.get(canonicalConfigFilePath); if (configFilePresenceInfo) { // Existing information - just add to tracking files - (configFilePresenceInfo.trackingOpenFiles || (configFilePresenceInfo.trackingOpenFiles = [])).push(root); - } - else { - // Add new callback - configFilePresenceInfo = { - exists: this.host.fileExists(configFileName), - trackingOpenFiles: [root], - configFileWatcher: this.addFileWatcher( - WatchType.ConfigFileForInferredRoot, /*project*/ undefined, configFileName, - (_fileName, eventKind) => this.onConfigFileAddedForInferredProject(configFileName, eventKind) - ) - }; - this.mapOfConfigFilePresence.set(canonicalConfigFilePath, configFilePresenceInfo); - } - this.logTrackingFiles(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileAdded); - } - - private closeWatchConfigFileForInferredRoot(configFileName: NormalizedPath, canonicalConfigFilePath: string, root: ScriptInfo, reason: WatcherCloseReason) { - const configFilePresenceInfo = this.mapOfConfigFilePresence.get(canonicalConfigFilePath); - Debug.assert(!!configFilePresenceInfo); - if (configFilePresenceInfo.trackingOpenFiles.length === 1) { - configFilePresenceInfo.trackingOpenFiles = undefined; - this.logTrackingFiles(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileRemoved); - if (configFilePresenceInfo.configFileWatcher) { - this.closeFileWatcher( - WatchType.ConfigFileForInferredRoot, /*project*/ undefined, - configFileName, configFilePresenceInfo.configFileWatcher, reason - ); - this.mapOfConfigFilePresence.delete(canonicalConfigFilePath); + if (!configFilePresenceInfo.trackingOpenFileSet) { + configFilePresenceInfo.trackingOpenFileSet = createMap(); + configFilePresenceInfo.trackingOpenFileSet.set(info.path, true); + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileAdded); + } + else if (!configFilePresenceInfo.trackingOpenFileSet.has(info.path)) { + configFilePresenceInfo.trackingOpenFileSet.set(info.path, true); + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileAdded); } } else { - removeItemFromSet(configFilePresenceInfo.trackingOpenFiles, root); - this.logTrackingFiles(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileRemoved); + // Add new callback + const trackingOpenFileSet = createMap(); + trackingOpenFileSet.set(info.path, true); + const exists = this.host.fileExists(configFileName); + configFilePresenceInfo = { + exists, + trackingOpenFileSet, + configFileWatcher: this.addFileWatcher( + WatchType.ConfigFileForOpenFile, /*project*/ undefined, configFileName, + (_fileName, eventKind) => this.onConfigFileChangeForOpenScriptInfo(configFileName, eventKind) + ) + }; + this.mapOfConfigFilePresence.set(canonicalConfigFilePath, configFilePresenceInfo); + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileAdded); + } + return configFilePresenceInfo; + } + + private closeConfigFileWatchForScriptInfo(configFileName: NormalizedPath, canonicalConfigFilePath: string, info: ScriptInfo) { + const configFilePresenceInfo = this.mapOfConfigFilePresence.get(canonicalConfigFilePath); + if (configFilePresenceInfo) { + if (configFilePresenceInfo.trackingOpenFileSet.size === 1) { + configFilePresenceInfo.trackingOpenFileSet = undefined; + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileRemoved); + if (configFilePresenceInfo.configFileWatcher) { + this.closeFileWatcher( + WatchType.ConfigFileForOpenFile, /*project*/ undefined, configFileName, + configFilePresenceInfo.configFileWatcher, WatcherCloseReason.FileClosed + ); + this.mapOfConfigFilePresence.delete(canonicalConfigFilePath); + } + } + else { + configFilePresenceInfo.trackingOpenFileSet.delete(info.path); + this.logConfigFileWatch(configFileName, configFilePresenceInfo, ConfigFileWatcherStatus.TrackingFileRemoved); + } } } - private enumerateWatchingRootOfInferredProject(root: ScriptInfo, - action: (configFileName: NormalizedPath, canonicalConfigFilePath: string, root: ScriptInfo) => void) { - let current = root.fileName; - let currentPath = getDirectoryPath(root.path); + private stopWatchingConfigFileForScriptInfo(info: ScriptInfo) { + Debug.assert(!info.isScriptOpen()); + let current = info.fileName; + let currentPath = getDirectoryPath(info.path); let parentPath = getDirectoryPath(currentPath); while (currentPath !== parentPath) { current = asNormalizedPath(getDirectoryPath(current)); - action(asNormalizedPath(combinePaths(current, "tsconfig.json")), combinePaths(currentPath, "tsconfig.json"), root); - //if (root.isJavaScript()) { - // this.watchConfigFileForInferredRoot(asNormalizedPath(combinePaths(current, "jsconfig.json")), combinePaths(currentPath, "jsconfig.json"), root); - //} + this.closeConfigFileWatchForScriptInfo(asNormalizedPath(combinePaths(current, "tsconfig.json")), combinePaths(currentPath, "tsconfig.json"), info); + this.closeConfigFileWatchForScriptInfo(asNormalizedPath(combinePaths(current, "jsconfig.json")), combinePaths(currentPath, "jsconfig.json"), info); currentPath = parentPath; parentPath = getDirectoryPath(parentPath); } } - /*@internal*/ - startWatchingRootOfInferredProject(root: ScriptInfo) { - this.enumerateWatchingRootOfInferredProject(root, - (configFileName, canonicalConfigFilePath, root) => - this.watchConfigFileForInferredRoot(configFileName, canonicalConfigFilePath, root) - ); - } - - /*@internal*/ - stopWatchingRootOfInferredProject(root: ScriptInfo, reason: WatcherCloseReason) { - this.enumerateWatchingRootOfInferredProject(root, - (configFileName, canonicalConfigFilePath, root) => - this.closeWatchConfigFileForInferredRoot(configFileName, canonicalConfigFilePath, root, reason) - ); - } - /** * This function tries to search for a tsconfig.json for the given file. * This is different from the method the compiler uses because @@ -998,20 +975,21 @@ namespace ts.server { * The server must start searching from the directory containing * the newly opened file. */ - private getConfigFileNameForFile(fileName: NormalizedPath, projectRootPath?: NormalizedPath) { - let searchPath = getDirectoryPath(fileName); + private getConfigFileNameForFile(info: ScriptInfo, projectRootPath?: NormalizedPath) { + Debug.assert(info.isScriptOpen()); + let searchPath = getDirectoryPath(info.fileName); this.logger.info(`Search path: ${searchPath}`); // check if this file is already included in one of external projects while (!projectRootPath || searchPath.indexOf(projectRootPath) >= 0) { const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); - if (this.configFileExists(tsconfigFileName)) { + if (this.configFileExists(tsconfigFileName, info)) { this.logger.info(`Config file name: ${tsconfigFileName}`); return tsconfigFileName; } const jsconfigFileName = asNormalizedPath(combinePaths(searchPath, "jsconfig.json")); - if (this.configFileExists(jsconfigFileName)) { + if (this.configFileExists(jsconfigFileName, info)) { this.logger.info(`Config file name: ${jsconfigFileName}`); return jsconfigFileName; } @@ -1359,7 +1337,6 @@ namespace ts.server { : new InferredProject(this, this.documentRegistry, this.compilerOptionsForInferredProjects); project.addRoot(root); - this.startWatchingRootOfInferredProject(root); project.updateGraph(); if (!useExistingProject) { @@ -1513,8 +1490,11 @@ namespace ts.server { this.refreshInferredProjects(); } - delayReloadConfiguredProjectForFiles(openFiles: ScriptInfo[]) { - this.reloadConfiguredProjectForFiles(openFiles, /*delayReload*/ true); + delayReloadConfiguredProjectForFiles(openFileSet: Map) { + if (openFileSet) { + const openFiles = arrayFrom(openFileSet.keys(), path => this.getScriptInfoForPath(path as Path)); + this.reloadConfiguredProjectForFiles(openFiles, /*delayReload*/ true); + } this.delayInferredProjectsRefresh(); } @@ -1532,7 +1512,7 @@ namespace ts.server { // we first detect if there is already a configured project created for it: if so, // we re- read the tsconfig file content and update the project only if we havent already done so // otherwise we create a new one. - const configFileName = this.getConfigFileNameForFile(info.fileName); + const configFileName = this.getConfigFileNameForFile(info); if (configFileName) { let project = this.findConfiguredProjectByProjectName(configFileName); if (!project) { @@ -1614,9 +1594,10 @@ namespace ts.server { let configFileName: NormalizedPath; let configFileErrors: Diagnostic[]; + const info = this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent); let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName); if (!project) { - configFileName = this.getConfigFileNameForFile(fileName, projectRootPath); + configFileName = this.getConfigFileNameForFile(info, projectRootPath); if (configFileName) { project = this.findConfiguredProjectByProjectName(configFileName); if (!project) { @@ -1640,7 +1621,6 @@ namespace ts.server { } // at this point if file is the part of some configured/external project then this project should be created - const info = this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent); this.assignScriptInfoToInferredProjectIfNecessary(info, /*addToListOfOpenFiles*/ true); // Delete the orphan files here because there might be orphan script infos (which are not part of project) // when some file/s were closed which resulted in project removal. diff --git a/src/server/project.ts b/src/server/project.ts index 2e14c75efc..774865b335 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -924,7 +924,6 @@ namespace ts.server { } addRoot(info: ScriptInfo) { - this.projectService.startWatchingRootOfInferredProject(info); if (!this._isJsInferredProject && info.isJavaScript()) { this.toggleJsInferredProject(/*isJsInferredProject*/ true); } @@ -932,7 +931,6 @@ namespace ts.server { } removeRoot(info: ScriptInfo) { - this.projectService.stopWatchingRootOfInferredProject(info, WatcherCloseReason.NotNeeded); super.removeRoot(info); if (this._isJsInferredProject && info.isJavaScript()) { if (!some(this.getRootScriptInfos(), info => info.isJavaScript())) { @@ -957,7 +955,6 @@ namespace ts.server { } close() { - forEach(this.getRootScriptInfos(), root => this.projectService.stopWatchingRootOfInferredProject(root, WatcherCloseReason.ProjectClose)); super.close(); } @@ -1208,7 +1205,6 @@ namespace ts.server { if (this.configFileWatcher) { this.projectService.closeFileWatcher(WatchType.ConfigFilePath, this, this.getConfigFilePath(), this.configFileWatcher, WatcherCloseReason.ProjectClose); this.configFileWatcher = undefined; - this.projectService.setConfigFilePresenceByClosedConfigFile(this); } this.stopWatchingTypeRoots(WatcherCloseReason.ProjectClose);