Skip to content

Commit

Permalink
Change explorer model to a Map to fix #47120 (#47184)
Browse files Browse the repository at this point in the history
  • Loading branch information
bpasero authored Apr 4, 2018
1 parent fe6f32b commit 5a34fba
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 22 deletions.
52 changes: 34 additions & 18 deletions src/vs/workbench/parts/files/common/explorerModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class ExplorerItem {
public etag: string;
private _isDirectory: boolean;
private _isSymbolicLink: boolean;
private children: { [name: string]: ExplorerItem };
private children: Map<string, ExplorerItem>;
public parent: ExplorerItem;

public isDirectoryResolved: boolean;
Expand Down Expand Up @@ -109,7 +109,7 @@ export class ExplorerItem {
if (value !== this._isDirectory) {
this._isDirectory = value;
if (this._isDirectory) {
this.children = Object.create(null);
this.children = new Map<string, ExplorerItem>();
} else {
this.children = undefined;
}
Expand Down Expand Up @@ -185,18 +185,16 @@ export class ExplorerItem {
// Map resource => stat
const oldLocalChildren = new ResourceMap<ExplorerItem>();
if (local.children) {
for (let name in local.children) {
const child = local.children[name];
local.children.forEach(child => {
oldLocalChildren.set(child.resource, child);
}
});
}

// Clear current children
local.children = Object.create(null);
local.children = new Map<string, ExplorerItem>();

// Merge received children
for (let name in disk.children) {
const diskChild = disk.children[name];
disk.children.forEach(diskChild => {
const formerLocalChild = oldLocalChildren.get(diskChild.resource);
// Existing child: merge
if (formerLocalChild) {
Expand All @@ -210,7 +208,7 @@ export class ExplorerItem {
diskChild.parent = local;
local.addChild(diskChild);
}
}
});
}
}

Expand All @@ -223,15 +221,15 @@ export class ExplorerItem {
child.parent = this;
child.updateResource(false);

this.children[this.getPlatformAwareName(child.name)] = child;
this.children.set(this.getPlatformAwareName(child.name), child);
}

public getChild(name: string): ExplorerItem {
if (!this.children) {
return undefined;
}

return this.children[this.getPlatformAwareName(name)];
return this.children.get(this.getPlatformAwareName(name));
}

/**
Expand All @@ -242,22 +240,40 @@ export class ExplorerItem {
return undefined;
}

return Object.keys(this.children).map(name => this.children[name]);
const items: ExplorerItem[] = [];
this.children.forEach(child => {
items.push(child);
});

return items;
}

public getChildrenCount(): number {
if (!this.children) {
return 0;
}

return this.children.size;
}

public getChildrenNames(): string[] {
if (!this.children) {
return [];
}

return Object.keys(this.children);
const names: string[] = [];
this.children.forEach(child => {
names.push(child.name);
});

return names;
}

/**
* Removes a child element from this folder.
*/
public removeChild(child: ExplorerItem): void {
delete this.children[this.getPlatformAwareName(child.name)];
this.children.delete(this.getPlatformAwareName(child.name));
}

private getPlatformAwareName(name: string): string {
Expand Down Expand Up @@ -289,9 +305,9 @@ export class ExplorerItem {

if (recursive) {
if (this.isDirectory && this.children) {
for (let name in this.children) {
this.children[name].updateResource(true);
}
this.children.forEach(child => {
child.updateResource(true);
});
}
}
}
Expand Down Expand Up @@ -347,7 +363,7 @@ export class ExplorerItem {
// The name to search is between two separators
const name = path.substring(index, indexOfNextSep);

const child = this.children[this.getPlatformAwareName(name)];
const child = this.children.get(this.getPlatformAwareName(name));

if (child) {
// We found a child with the given name, search inside it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,13 +694,15 @@ export class FileFilter implements IFilter {
}

// Workaround for O(N^2) complexity (https://github.com/Microsoft/vscode/issues/9962)
let siblingNames = stat.parent && stat.parent.getChildrenNames();
if (siblingNames && siblingNames.length > FileFilter.MAX_SIBLINGS_FILTER_THRESHOLD) {
siblingNames = void 0;
let siblingsFn: () => string[];
let siblingCount = stat.parent && stat.parent.getChildrenCount();
if (siblingCount && siblingCount > FileFilter.MAX_SIBLINGS_FILTER_THRESHOLD) {
siblingsFn = () => void 0;
} else {
siblingsFn = () => stat.parent ? stat.parent.getChildrenNames() : void 0;
}

// Hide those that match Hidden Patterns
const siblingsFn = () => siblingNames;
const expression = this.hiddenExpressionPerRoot.get(stat.root.resource.toString()) || Object.create(null);
if (glob.match(expression, paths.normalize(relative(stat.root.resource.fsPath, stat.resource.fsPath), true), siblingsFn)) {
return false; // hidden through pattern
Expand Down

0 comments on commit 5a34fba

Please sign in to comment.