diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 3339514cc2..6f23eb3479 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -138,7 +138,7 @@ export class CppProperties { private configFileWatcherFallbackTime: Date = new Date(); // Used when file watching fails. private compileCommandsFile: vscode.Uri | undefined | null = undefined; private compileCommandsFileWatchers: fs.FSWatcher[] = []; - private compileCommandsFileWatcherFallbackTime: Date = new Date(); // Used when file watching fails. + private compileCommandsFileWatcherFallbackTime: Map = new Map(); // Used when file watching fails. private defaultCompilerPath: string | null = null; private knownCompilers?: KnownCompiler[]; private defaultCStandard: string | null = null; @@ -1093,6 +1093,10 @@ export class CppProperties { if (configuration.compileCommands) { configuration.compileCommands = this.resolvePath(configuration.compileCommands); + if (!this.compileCommandsFileWatcherFallbackTime.has(configuration.compileCommands)) { + // Start tracking the fallback time for a new path. + this.compileCommandsFileWatcherFallbackTime.set(configuration.compileCommands, new Date()); + } } if (configuration.forcedInclude) { @@ -1104,12 +1108,31 @@ export class CppProperties { } } + this.clearStaleCompileCommandsFileWatcherFallbackTimes(); this.updateCompileCommandsFileWatchers(); if (!this.configurationIncomplete) { this.onConfigurationsChanged(); } } + private clearStaleCompileCommandsFileWatcherFallbackTimes(): void { + // We need to keep track of relevant timestamps, so we cannot simply clear all entries. + // Instead, we clear entries that are no longer relevant. + const trackedCompileCommandsPaths: Set = new Set(); + this.configurationJson?.configurations.forEach((config: Configuration) => { + const path = this.resolvePath(config.compileCommands); + if (path.length > 0) { + trackedCompileCommandsPaths.add(path); + } + }); + + for (const path of this.compileCommandsFileWatcherFallbackTime.keys()) { + if (!trackedCompileCommandsPaths.has(path)) { + this.compileCommandsFileWatcherFallbackTime.delete(path); + } + } + } + private compileCommandsFileWatcherTimer?: NodeJS.Timeout; private compileCommandsFileWatcherFiles: Set = new Set(); @@ -2310,14 +2333,18 @@ export class CppProperties { fs.stat(compileCommandsFile, (err, stats) => { if (err) { if (err.code === "ENOENT" && this.compileCommandsFile) { + this.compileCommandsFileWatchers.forEach((watcher: fs.FSWatcher) => watcher.close()); this.compileCommandsFileWatchers = []; // reset file watchers this.onCompileCommandsChanged(compileCommandsFile); this.compileCommandsFile = null; // File deleted } - } else if (stats.mtime > this.compileCommandsFileWatcherFallbackTime) { - this.compileCommandsFileWatcherFallbackTime = new Date(); - this.onCompileCommandsChanged(compileCommandsFile); - this.compileCommandsFile = vscode.Uri.file(compileCommandsFile); // File created. + } else { + const compileCommandsLastChanged: Date | undefined = this.compileCommandsFileWatcherFallbackTime.get(compileCommandsFile); + if (compileCommandsLastChanged !== undefined && stats.mtime > compileCommandsLastChanged) { + this.compileCommandsFileWatcherFallbackTime.set(compileCommandsFile, new Date()); + this.onCompileCommandsChanged(compileCommandsFile); + this.compileCommandsFile = vscode.Uri.file(compileCommandsFile); // File created. + } } }); }