Use a plain Set intead of custom FilePathSet

This commit is contained in:
Robert
2023-06-16 11:29:38 +01:00
parent f7a72c6d45
commit fce27d02dc
3 changed files with 21 additions and 108 deletions

View File

@@ -1,42 +0,0 @@
import { containsPath } from "../pure/files";
/**
* A set of file paths.
*
* All paths in the set will not overlap. If a path is added to the set
* that is a parent or child of an existing path in the set, only the
* parent path will be kept.
*/
export class FilePathSet {
private paths: string[] = [];
/** Is the set currently empty */
public isEmpty(): boolean {
return this.paths.length === 0;
}
/**
* Adds the path to the set.
*
* The set will not contain overlapping paths. This means that if the
* new path is a child of an existing path in the set then it will not
* be added. And if the new path is a parent of any existing paths, then
* those existing paths will be removed. This can cause the "size" of
* the set of decrease, but it won't go from non-zero to zero.
*/
public addPath(path: string): void {
if (this.paths.some((p) => containsPath(p, path))) {
// The new path is a child of an existing path, so don't add it.
return;
} else {
// Remove any existing paths that are children of the new path.
this.paths = this.paths.filter((p) => !containsPath(path, p));
this.paths.push(path);
}
}
/** Removes and returns a path from the set, if the set is non-empty. */
public popPath(): string | undefined {
return this.paths.shift();
}
}

View File

@@ -9,7 +9,6 @@ import {
import { MultiFileSystemWatcher } from "./multi-file-system-watcher";
import { AppEventEmitter } from "../events";
import { extLogger } from "..";
import { FilePathSet } from "../file-path-set";
import { exists, lstat } from "fs-extra";
import { containsPath } from "../../pure/files";
import { getOnDiskWorkspaceFoldersObjects } from "./workspace-folders";
@@ -30,9 +29,23 @@ interface PathData {
export abstract class FilePathDiscovery<T extends PathData> extends Discovery {
/** The set of known paths we are tracking */
protected paths: T[] = [];
/** Event that fires whenever the set of known paths changes */
protected readonly onDidChangePathsEmitter: AppEventEmitter<void>;
private readonly changedFilePaths = new FilePathSet();
/**
* The set of file paths that may have changed on disk since the last time
* refresh was run. Whenever a watcher reports some change to a file we add
* it to this set, and then during the next refresh we will process all
* file paths from this set and update our internal state to match whatever
* we find on disk (i.e. the file exists, doesn't exist, computed data has
* changed).
*/
private readonly changedFilePaths = new Set<string>();
/**
* Watches for changes to files and directories in all workspace folders.
*/
private readonly watcher: MultiFileSystemWatcher = this.push(
new MultiFileSystemWatcher(),
);
@@ -76,7 +89,7 @@ export abstract class FilePathDiscovery<T extends PathData> extends Discovery {
*/
public async initialRefresh() {
getOnDiskWorkspaceFoldersObjects().forEach((workspaceFolder) => {
this.changedFilePaths.addPath(workspaceFolder.uri.fsPath);
this.changedFilePaths.add(workspaceFolder.uri.fsPath);
});
this.updateWatchers();
@@ -85,10 +98,10 @@ export abstract class FilePathDiscovery<T extends PathData> extends Discovery {
private workspaceFoldersChanged(event: WorkspaceFoldersChangeEvent) {
event.added.forEach((workspaceFolder) => {
this.changedFilePaths.addPath(workspaceFolder.uri.fsPath);
this.changedFilePaths.add(workspaceFolder.uri.fsPath);
});
event.removed.forEach((workspaceFolder) => {
this.changedFilePaths.addPath(workspaceFolder.uri.fsPath);
this.changedFilePaths.add(workspaceFolder.uri.fsPath);
});
this.updateWatchers();
@@ -108,14 +121,14 @@ export abstract class FilePathDiscovery<T extends PathData> extends Discovery {
}
private fileChanged(uri: Uri) {
this.changedFilePaths.addPath(uri.fsPath);
this.changedFilePaths.add(uri.fsPath);
void this.refresh();
}
protected async discover() {
let pathsUpdated = false;
let path: string | undefined;
while ((path = this.changedFilePaths.popPath()) !== undefined) {
for (const path of this.changedFilePaths) {
this.changedFilePaths.delete(path);
if (await this.handledChangedPath(path)) {
pathsUpdated = true;
}

View File

@@ -1,58 +0,0 @@
import { FilePathSet } from "../../../src/common/file-path-set";
describe("FilePathSet", () => {
describe("isEmpty", () => {
it("should return true only when set is empty", () => {
const v = new FilePathSet();
expect(v.isEmpty()).toBe(true);
v.addPath("/foo");
expect(v.isEmpty()).toBe(false);
v.popPath();
expect(v.isEmpty()).toBe(true);
});
});
describe("addPath / popPath", () => {
it("should keep all paths when they don't overlap", () => {
const v = new FilePathSet();
v.addPath("/foo");
v.addPath("/bar");
v.addPath("/baz");
expect(v.popPath()).toBe("/foo");
expect(v.popPath()).toBe("/bar");
expect(v.popPath()).toBe("/baz");
expect(v.popPath()).toBe(undefined);
});
it("should only keep one copy of repeated paths", () => {
const v = new FilePathSet();
v.addPath("/foo");
v.addPath("/foo");
v.addPath("/foo");
expect(v.popPath()).toBe("/foo");
expect(v.popPath()).toBe(undefined);
});
it("should adding adding paths that are children of existing paths", () => {
const v = new FilePathSet();
v.addPath("/foo");
v.addPath("/foo/bar");
v.addPath("/foo/baz");
expect(v.popPath()).toBe("/foo");
expect(v.popPath()).toBe(undefined);
});
it("should remove existing paths that are children of new paths", () => {
const v = new FilePathSet();
v.addPath("/foo");
v.addPath("/bar/baz");
v.addPath("/bar/qux");
v.addPath("/bar");
expect(v.popPath()).toBe("/foo");
expect(v.popPath()).toBe("/bar");
expect(v.popPath()).toBe(undefined);
});
});
});