More work based on feedback

This commit is contained in:
Sheetal Nandi
2017-08-14 14:59:51 -07:00
parent 989508245b
commit f1b1b12604
7 changed files with 147 additions and 102 deletions

View File

@@ -2631,12 +2631,16 @@ namespace ts {
useCaseSensitiveFileNames: boolean;
}
export interface CachedHost extends PartialSystem {
addOrDeleteFileOrFolder(fileOrFolder: string): void;
export interface CachedHost {
addOrDeleteFileOrFolder(fileOrFolder: string, fileOrFolderPath: Path): void;
addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind): void;
clearCache(): void;
}
export function createCachedHost(host: HostForCaching): CachedHost {
export interface CachedPartialSystem extends PartialSystem, CachedHost {
}
export function createCachedPartialSystem(host: HostForCaching): CachedPartialSystem {
const cachedReadDirectoryResult = createMap<FileSystemEntries>();
const getCurrentDirectory = memoize(() => host.getCurrentDirectory());
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
@@ -2649,6 +2653,7 @@ namespace ts {
getDirectories,
readDirectory,
addOrDeleteFileOrFolder,
addOrDeleteFile,
clearCache
};
@@ -2656,33 +2661,46 @@ namespace ts {
return ts.toPath(fileName, getCurrentDirectory(), getCanonicalFileName);
}
function getFileSystemEntries(rootDir: string) {
const path = toPath(rootDir);
const cachedResult = cachedReadDirectoryResult.get(path);
if (cachedResult) {
return cachedResult;
}
function getCachedFileSystemEntries(rootDirPath: Path): FileSystemEntries | undefined {
return cachedReadDirectoryResult.get(rootDirPath);
}
function getCachedFileSystemEntriesForBaseDir(path: Path): FileSystemEntries | undefined {
return getCachedFileSystemEntries(getDirectoryPath(path));
}
function getBaseNameOfFileName(fileName: string) {
return getBaseFileName(normalizePath(fileName));
}
function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) {
const resultFromHost: FileSystemEntries = {
files: host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]) || [],
directories: host.getDirectories(rootDir) || []
};
cachedReadDirectoryResult.set(path, resultFromHost);
cachedReadDirectoryResult.set(rootDirPath, resultFromHost);
return resultFromHost;
}
function canWorkWithCacheForDir(rootDir: string) {
// Some of the hosts might not be able to handle read directory or getDirectories
const path = toPath(rootDir);
if (cachedReadDirectoryResult.get(path)) {
return true;
/**
* If the readDirectory result was already cached, it returns that
* Otherwise gets result from host and caches it.
* The host request is done under try catch block to avoid caching incorrect result
*/
function tryReadDirectory(rootDir: string, rootDirPath: Path): FileSystemEntries | undefined {
const cachedResult = getCachedFileSystemEntries(rootDirPath);
if (cachedResult) {
return cachedResult;
}
try {
return getFileSystemEntries(rootDir);
return createCachedFileSystemEntries(rootDir, rootDirPath);
}
catch (_e) {
return false;
// If there is exception to read directories, dont cache the result and direct the calls to host
Debug.assert(!cachedReadDirectoryResult.has(rootDirPath));
return undefined;
}
}
@@ -2708,19 +2726,18 @@ namespace ts {
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
const path = toPath(fileName);
const result = cachedReadDirectoryResult.get(getDirectoryPath(path));
const baseFileName = getBaseFileName(normalizePath(fileName));
const result = getCachedFileSystemEntriesForBaseDir(path);
if (result) {
result.files = updateFileSystemEntry(result.files, baseFileName, /*isValid*/ true);
updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true);
}
return host.writeFile(fileName, data, writeByteOrderMark);
}
function fileExists(fileName: string): boolean {
const path = toPath(fileName);
const result = cachedReadDirectoryResult.get(getDirectoryPath(path));
const baseName = getBaseFileName(normalizePath(fileName));
return (result && hasEntry(result.files, baseName)) || host.fileExists(fileName);
const result = getCachedFileSystemEntriesForBaseDir(path);
return (result && hasEntry(result.files, getBaseNameOfFileName(fileName))) ||
host.fileExists(fileName);
}
function directoryExists(dirPath: string): boolean {
@@ -2730,8 +2747,8 @@ namespace ts {
function createDirectory(dirPath: string) {
const path = toPath(dirPath);
const result = cachedReadDirectoryResult.get(getDirectoryPath(path));
const baseFileName = getBaseFileName(path);
const result = getCachedFileSystemEntriesForBaseDir(path);
const baseFileName = getBaseNameOfFileName(dirPath);
if (result) {
result.directories = updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true);
}
@@ -2739,41 +2756,68 @@ namespace ts {
}
function getDirectories(rootDir: string): string[] {
if (canWorkWithCacheForDir(rootDir)) {
return getFileSystemEntries(rootDir).directories.slice();
const rootDirPath = toPath(rootDir);
const result = tryReadDirectory(rootDir, rootDirPath);
if (result) {
return result.directories.slice();
}
return host.getDirectories(rootDir);
}
function readDirectory(rootDir: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
if (canWorkWithCacheForDir(rootDir)) {
return matchFiles(rootDir, extensions, excludes, includes, host.useCaseSensitiveFileNames, getCurrentDirectory(), depth, path => getFileSystemEntries(path));
const rootDirPath = toPath(rootDir);
const result = tryReadDirectory(rootDir, rootDirPath);
if (result) {
return matchFiles(rootDir, extensions, excludes, includes, host.useCaseSensitiveFileNames, getCurrentDirectory(), depth, getFileSystemEntries);
}
return host.readDirectory(rootDir, extensions, excludes, includes, depth);
function getFileSystemEntries(dir: string) {
const path = toPath(dir);
if (path === rootDirPath) {
return result;
}
return getCachedFileSystemEntries(path) || createCachedFileSystemEntries(dir, path);
}
}
function addOrDeleteFileOrFolder(fileOrFolder: string) {
const path = toPath(fileOrFolder);
const existingResult = cachedReadDirectoryResult.get(path);
function addOrDeleteFileOrFolder(fileOrFolder: string, fileOrFolderPath: Path) {
const existingResult = getCachedFileSystemEntries(fileOrFolderPath);
if (existingResult) {
// This was a folder already present, remove it if this doesnt exist any more
if (!host.directoryExists(fileOrFolder)) {
cachedReadDirectoryResult.delete(path);
cachedReadDirectoryResult.delete(fileOrFolderPath);
}
}
else {
// This was earlier a file (hence not in cached directory contents)
// or we never cached the directory containing it
const parentResult = cachedReadDirectoryResult.get(getDirectoryPath(path));
const parentResult = getCachedFileSystemEntriesForBaseDir(fileOrFolderPath);
if (parentResult) {
const baseName = getBaseFileName(fileOrFolder);
const baseName = getBaseNameOfFileName(fileOrFolder);
if (parentResult) {
parentResult.files = updateFileSystemEntry(parentResult.files, baseName, host.fileExists(path));
parentResult.directories = updateFileSystemEntry(parentResult.directories, baseName, host.directoryExists(path));
updateFilesOfFileSystemEntry(parentResult, baseName, host.fileExists(fileOrFolderPath));
parentResult.directories = updateFileSystemEntry(parentResult.directories, baseName, host.directoryExists(fileOrFolderPath));
}
}
}
}
function addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind) {
if (eventKind === FileWatcherEventKind.Changed) {
return;
}
const parentResult = getCachedFileSystemEntriesForBaseDir(filePath);
if (parentResult) {
updateFilesOfFileSystemEntry(parentResult, getBaseNameOfFileName(fileName), eventKind === FileWatcherEventKind.Created);
}
}
function updateFilesOfFileSystemEntry(parentResult: FileSystemEntries, baseName: string, fileExists: boolean) {
parentResult.files = updateFileSystemEntry(parentResult.files, baseName, fileExists);
}
function clearCache() {
cachedReadDirectoryResult.clear();
}

View File

@@ -40,7 +40,7 @@ namespace ts {
export function createResolutionCache(
toPath: (fileName: string) => Path,
getCompilerOptions: () => CompilerOptions,
watchForFailedLookupLocation: (failedLookupLocation: string, containingFile: string, name: string) => FileWatcher,
watchForFailedLookupLocation: (failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) => FileWatcher,
log: (s: string) => void,
resolveWithGlobalCache?: ResolverWithGlobalCache): ResolutionCache {
@@ -201,7 +201,7 @@ namespace ts {
}
else {
log(`Watcher: FailedLookupLocations: Status: new watch: Location: ${failedLookupLocation}, containingFile: ${containingFile}, name: ${name}`);
const fileWatcher = watchForFailedLookupLocation(failedLookupLocation, containingFile, name);
const fileWatcher = watchForFailedLookupLocation(failedLookupLocation, failedLookupLocationPath, containingFile, name);
failedLookupLocationsWatches.set(failedLookupLocationPath, { fileWatcher, refCount: 1 });
}
}

View File

@@ -520,7 +520,7 @@ namespace ts {
function onSourceFileChange(fileName: string, path: Path, eventKind: FileWatcherEventKind) {
writeLog(`Source file path : ${path} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${fileName}`);
updateCachedSystem(fileName, path);
updateCachedSystemWithFile(fileName, path, eventKind);
const hostSourceFile = sourceFilesCache.get(path);
if (hostSourceFile) {
// Update the cache
@@ -547,21 +547,19 @@ namespace ts {
scheduleProgramUpdate();
}
function updateCachedSystem(fileName: string, path: Path) {
function updateCachedSystemWithFile(fileName: string, path: Path, eventKind: FileWatcherEventKind) {
if (configFileName) {
const absoluteNormalizedPath = getNormalizedAbsolutePath(fileName, getDirectoryPath(path));
(host as CachedSystem).addOrDeleteFileOrFolder(normalizePath(absoluteNormalizedPath));
(host as CachedSystem).addOrDeleteFile(fileName, path, eventKind);
}
}
function watchFailedLookupLocation(failedLookupLocation: string, containingFile: string, name: string) {
return host.watchFile(failedLookupLocation, (fileName, eventKind) => onFailedLookupLocationChange(fileName, eventKind, failedLookupLocation, containingFile, name));
function watchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) {
return host.watchFile(failedLookupLocation, (fileName, eventKind) => onFailedLookupLocationChange(fileName, eventKind, failedLookupLocation, failedLookupLocationPath, containingFile, name));
}
function onFailedLookupLocationChange(fileName: string, eventKind: FileWatcherEventKind, failedLookupLocation: string, containingFile: string, name: string) {
function onFailedLookupLocationChange(fileName: string, eventKind: FileWatcherEventKind, failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) {
writeLog(`Failed lookup location : ${failedLookupLocation} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${fileName} containingFile: ${containingFile}, name: ${name}`);
const path = toPath(failedLookupLocation);
updateCachedSystem(failedLookupLocation, path);
updateCachedSystemWithFile(fileName, failedLookupLocationPath, eventKind);
resolutionCache.invalidateResolutionOfChangedFailedLookupLocation(failedLookupLocation);
scheduleProgramUpdate();
}
@@ -574,14 +572,14 @@ namespace ts {
fileWatcher.close();
}
function onMissingFileChange(filename: string, missingFilePath: Path, eventKind: FileWatcherEventKind) {
writeLog(`Missing file path : ${missingFilePath} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${filename}`);
function onMissingFileChange(fileName: string, missingFilePath: Path, eventKind: FileWatcherEventKind) {
writeLog(`Missing file path : ${missingFilePath} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${fileName}`);
updateCachedSystemWithFile(fileName, missingFilePath, eventKind);
if (eventKind === FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) {
closeMissingFilePathWatcher(missingFilePath, missingFilesMap.get(missingFilePath));
missingFilesMap.delete(missingFilePath);
updateCachedSystem(filename, missingFilePath);
// Delete the entry in the source files cache so that new source file is created
removeSourceFile(missingFilePath);
@@ -600,8 +598,8 @@ namespace ts {
}
function watchWildCardDirectory(directory: string, flags: WatchDirectoryFlags) {
return host.watchDirectory(directory, fileName =>
onFileAddOrRemoveInWatchedDirectory(getNormalizedAbsolutePath(fileName, directory)),
return host.watchDirectory(directory, fileOrFolder =>
onFileAddOrRemoveInWatchedDirectory(getNormalizedAbsolutePath(fileOrFolder, directory)),
(flags & WatchDirectoryFlags.Recursive) !== 0);
}
@@ -609,24 +607,24 @@ namespace ts {
watcher.close();
}
function onFileAddOrRemoveInWatchedDirectory(fileName: string) {
function onFileAddOrRemoveInWatchedDirectory(fileOrFolder: string) {
Debug.assert(!!configFileName);
const path = toPath(fileName);
const fileOrFolderPath = toPath(fileOrFolder);
// Since the file existance changed, update the sourceFiles cache
updateCachedSystem(fileName, path);
removeSourceFile(path);
(host as CachedSystem).addOrDeleteFileOrFolder(fileOrFolder, fileOrFolderPath);
removeSourceFile(fileOrFolderPath);
// If a change was made inside "folder/file", node will trigger the callback twice:
// one with the fileName being "folder/file", and the other one with "folder".
// We don't respond to the second one.
if (fileName && !isSupportedSourceFileName(fileName, compilerOptions)) {
writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileName}`);
if (fileOrFolder && !isSupportedSourceFileName(fileOrFolder, compilerOptions)) {
writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrFolder}`);
return;
}
writeLog(`Project: ${configFileName} Detected file add/remove of supported extension: ${fileName}`);
writeLog(`Project: ${configFileName} Detected file add/remove of supported extension: ${fileOrFolder}`);
// Reload is pending, do the reload
if (!needsReload) {
@@ -658,9 +656,7 @@ namespace ts {
}
}
interface CachedSystem extends System {
addOrDeleteFileOrFolder(fileOrFolder: string): void;
clearCache(): void;
interface CachedSystem extends System, CachedHost {
}
function createCachedSystem(host: System): CachedSystem {
@@ -675,7 +671,7 @@ namespace ts {
const setTimeout = host.setTimeout ? (callback: (...args: any[]) => void, ms: number, ...args: any[]) => host.setTimeout(callback, ms, ...args) : undefined;
const clearTimeout = host.clearTimeout ? (timeoutId: any) => host.clearTimeout(timeoutId) : undefined;
const cachedHost = createCachedHost(host);
const cachedPartialSystem = createCachedPartialSystem(host);
return {
args: host.args,
newLine: host.newLine,
@@ -683,17 +679,17 @@ namespace ts {
write: s => host.write(s),
readFile: (path, encoding?) => host.readFile(path, encoding),
getFileSize,
writeFile: (fileName, data, writeByteOrderMark?) => cachedHost.writeFile(fileName, data, writeByteOrderMark),
writeFile: (fileName, data, writeByteOrderMark?) => cachedPartialSystem.writeFile(fileName, data, writeByteOrderMark),
watchFile,
watchDirectory,
resolvePath: path => host.resolvePath(path),
fileExists: fileName => cachedHost.fileExists(fileName),
directoryExists: dir => cachedHost.directoryExists(dir),
createDirectory: dir => cachedHost.createDirectory(dir),
fileExists: fileName => cachedPartialSystem.fileExists(fileName),
directoryExists: dir => cachedPartialSystem.directoryExists(dir),
createDirectory: dir => cachedPartialSystem.createDirectory(dir),
getExecutingFilePath: () => host.getExecutingFilePath(),
getCurrentDirectory: () => cachedHost.getCurrentDirectory(),
getDirectories: dir => cachedHost.getDirectories(dir),
readDirectory: (path, extensions, excludes, includes, depth) => cachedHost.readDirectory(path, extensions, excludes, includes, depth),
getCurrentDirectory: () => cachedPartialSystem.getCurrentDirectory(),
getDirectories: dir => cachedPartialSystem.getDirectories(dir),
readDirectory: (path, extensions, excludes, includes, depth) => cachedPartialSystem.readDirectory(path, extensions, excludes, includes, depth),
getModifiedTime,
createHash,
getMemoryUsage,
@@ -704,8 +700,9 @@ namespace ts {
debugMode: host.debugMode,
setTimeout,
clearTimeout,
addOrDeleteFileOrFolder: fileOrFolder => cachedHost.addOrDeleteFileOrFolder(fileOrFolder),
clearCache: () => cachedHost.clearCache()
addOrDeleteFileOrFolder: (fileOrFolder, fileOrFolderPath) => cachedPartialSystem.addOrDeleteFileOrFolder(fileOrFolder, fileOrFolderPath),
addOrDeleteFile: (file, filePath, eventKind) => cachedPartialSystem.addOrDeleteFile(file, filePath, eventKind),
clearCache: () => cachedPartialSystem.clearCache()
};
}
}

View File

@@ -695,8 +695,8 @@ namespace ts.server {
}
/* @internal */
onTypeRootFileChanged(project: ConfiguredProject, fileName: NormalizedPath) {
project.getCachedServerHost().addOrDeleteFileOrFolder(fileName);
onTypeRootFileChanged(project: ConfiguredProject, fileOrFolder: NormalizedPath) {
project.getCachedServerHost().addOrDeleteFileOrFolder(fileOrFolder, this.toPath(fileOrFolder));
project.updateTypes();
this.delayUpdateProjectGraphAndInferredProjectsRefresh(project);
}
@@ -707,15 +707,15 @@ namespace ts.server {
* @param fileName the absolute file name that changed in watched directory
*/
/* @internal */
onFileAddOrRemoveInWatchedDirectoryOfProject(project: ConfiguredProject, fileName: NormalizedPath) {
project.getCachedServerHost().addOrDeleteFileOrFolder(fileName);
onFileAddOrRemoveInWatchedDirectoryOfProject(project: ConfiguredProject, fileOrFolder: NormalizedPath) {
project.getCachedServerHost().addOrDeleteFileOrFolder(fileOrFolder, this.toPath(fileOrFolder));
const configFilename = project.getConfigFilePath();
// If a change was made inside "folder/file", node will trigger the callback twice:
// one with the fileName being "folder/file", and the other one with "folder".
// We don't respond to the second one.
if (fileName && !isSupportedSourceFileName(fileName, project.getCompilerOptions(), this.hostConfiguration.extraFileExtensions)) {
this.logger.info(`Project: ${configFilename} Detected file add/remove of non supported extension: ${fileName}`);
if (fileOrFolder && !isSupportedSourceFileName(fileOrFolder, project.getCompilerOptions(), this.hostConfiguration.extraFileExtensions)) {
this.logger.info(`Project: ${configFilename} Detected file add/remove of non supported extension: ${fileOrFolder}`);
return;
}

View File

@@ -4,12 +4,13 @@
/// <reference path="..\compiler\resolutionCache.ts" />
namespace ts.server {
/*@internal*/
export class CachedServerHost implements ServerHost {
args: string[];
newLine: string;
useCaseSensitiveFileNames: boolean;
private readonly cachedHost: CachedHost;
private readonly cachedPartialSystem: CachedPartialSystem;
readonly trace: (s: string) => void;
readonly realpath?: (path: string) => string;
@@ -24,7 +25,7 @@ namespace ts.server {
if (this.host.realpath) {
this.realpath = path => this.host.realpath(path);
}
this.cachedHost = createCachedHost(host);
this.cachedPartialSystem = createCachedPartialSystem(host);
}
write(s: string) {
@@ -32,7 +33,7 @@ namespace ts.server {
}
writeFile(fileName: string, data: string, writeByteOrderMark?: boolean) {
this.cachedHost.writeFile(fileName, data, writeByteOrderMark);
this.cachedPartialSystem.writeFile(fileName, data, writeByteOrderMark);
}
resolvePath(path: string) {
@@ -48,7 +49,7 @@ namespace ts.server {
}
getCurrentDirectory() {
return this.cachedHost.getCurrentDirectory();
return this.cachedPartialSystem.getCurrentDirectory();
}
exit(exitCode?: number) {
@@ -61,32 +62,35 @@ namespace ts.server {
}
getDirectories(rootDir: string) {
return this.cachedHost.getDirectories(rootDir);
return this.cachedPartialSystem.getDirectories(rootDir);
}
readDirectory(rootDir: string, extensions: string[], excludes: string[], includes: string[], depth: number): string[] {
return this.cachedHost.readDirectory(rootDir, extensions, excludes, includes, depth);
return this.cachedPartialSystem.readDirectory(rootDir, extensions, excludes, includes, depth);
}
fileExists(fileName: string): boolean {
return this.cachedHost.fileExists(fileName);
return this.cachedPartialSystem.fileExists(fileName);
}
directoryExists(dirPath: string) {
return this.cachedHost.directoryExists(dirPath);
return this.cachedPartialSystem.directoryExists(dirPath);
}
readFile(path: string, encoding?: string): string {
return this.host.readFile(path, encoding);
}
addOrDeleteFileOrFolder(fileOrFolder: NormalizedPath, fileOrFolderPath: Path) {
return this.cachedPartialSystem.addOrDeleteFileOrFolder(fileOrFolder, fileOrFolderPath);
}
addOrDeleteFileOrFolder(fileOrFolder: NormalizedPath) {
return this.cachedHost.addOrDeleteFileOrFolder(fileOrFolder);
addOrDeleteFile(file: string, path: Path, eventKind: FileWatcherEventKind) {
return this.cachedPartialSystem.addOrDeleteFile(file, path, eventKind);
}
clearCache() {
return this.cachedHost.clearCache();
return this.cachedPartialSystem.clearCache();
}
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]) {

View File

@@ -218,7 +218,7 @@ namespace ts.server {
this.resolutionCache = createResolutionCache(
fileName => this.projectService.toPath(fileName),
() => this.compilerOptions,
(failedLookupLocation, containingFile, name) => this.watchFailedLookupLocation(failedLookupLocation, containingFile, name),
(failedLookupLocation, failedLookupLocationPath, containingFile, name) => this.watchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath, containingFile, name),
s => this.projectService.logger.info(s),
(primaryResult, moduleName, compilerOptions, host) => resolveWithGlobalCache(primaryResult, moduleName, compilerOptions, host,
this.getTypeAcquisition().enable ? this.projectService.typingsInstaller.globalTypingsCacheLocation : undefined, this.getProjectName())
@@ -235,12 +235,12 @@ namespace ts.server {
this.markAsDirty();
}
private watchFailedLookupLocation(failedLookupLocation: string, containingFile: string, name: string) {
private watchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) {
// There is some kind of change in the failed lookup location, update the program
return this.projectService.addFileWatcher(WatchType.FailedLookupLocation, this, failedLookupLocation, (__fileName, eventKind) => {
return this.projectService.addFileWatcher(WatchType.FailedLookupLocation, this, failedLookupLocation, (fileName, eventKind) => {
this.projectService.logger.info(`Watcher: FailedLookupLocations: Status: ${FileWatcherEventKind[eventKind]}: Location: ${failedLookupLocation}, containingFile: ${containingFile}, name: ${name}`);
if (this.projectKind === ProjectKind.Configured) {
(this.lsHost.host as CachedServerHost).addOrDeleteFileOrFolder(toNormalizedPath(failedLookupLocation));
(this.lsHost.host as CachedServerHost).addOrDeleteFile(fileName, failedLookupLocationPath, eventKind);
}
this.resolutionCache.invalidateResolutionOfChangedFailedLookupLocation(failedLookupLocation);
this.markAsDirty();
@@ -719,16 +719,15 @@ namespace ts.server {
private addMissingFileWatcher(missingFilePath: Path) {
const fileWatcher = this.projectService.addFileWatcher(
WatchType.MissingFilePath, this, missingFilePath,
(filename, eventKind) => {
(fileName, eventKind) => {
if (this.projectKind === ProjectKind.Configured) {
(this.lsHost.host as CachedServerHost).addOrDeleteFile(fileName, missingFilePath, eventKind);
}
if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap.has(missingFilePath)) {
this.missingFilesMap.delete(missingFilePath);
this.closeMissingFileWatcher(missingFilePath, fileWatcher, WatcherCloseReason.FileCreated);
if (this.projectKind === ProjectKind.Configured) {
const absoluteNormalizedPath = getNormalizedAbsolutePath(filename, getDirectoryPath(missingFilePath));
(this.lsHost.host as CachedServerHost).addOrDeleteFileOrFolder(toNormalizedPath(absoluteNormalizedPath));
}
// When a missing file is created, we should update the graph.
this.markAsDirty();
this.projectService.delayUpdateProjectGraphAndInferredProjectsRefresh(this);
@@ -1076,6 +1075,7 @@ namespace ts.server {
return super.updateGraph();
}
/*@internal*/
getCachedServerHost() {
return this.lsHost.host as CachedServerHost;
}

View File

@@ -237,7 +237,7 @@ namespace ts.server {
detachAllProjects() {
for (const p of this.containingProjects) {
if (p.projectKind === ProjectKind.Configured) {
(p.lsHost.host as CachedServerHost).addOrDeleteFileOrFolder(this.fileName);
(p.lsHost.host as CachedServerHost).addOrDeleteFile(this.fileName, this.path, FileWatcherEventKind.Deleted);
}
const isInfoRoot = p.isRoot(this);
// detach is unnecessary since we'll clean the list of containing projects anyways