Use a plain Set intead of custom FilePathSet
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user