Fixes to compile commands file watchers fallback logic (#12948)

* close file watchers before clearing the array
* keep track of fallback time per file
This commit is contained in:
Yiftah Waisman 2024-11-13 02:02:42 +02:00 коммит произвёл GitHub
Родитель c9cae0b8c0
Коммит 911c39d054
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
1 изменённых файлов: 32 добавлений и 5 удалений

Просмотреть файл

@ -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<string, Date> = new Map<string, Date>(); // 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<string> = 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<string> = new Set<string>();
@ -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.
}
}
});
}