mirror of
https://github.com/Microsoft/vscode
synced 2024-09-13 13:46:13 +00:00
Add fast path for synchronously resolved children (nested children)
ref #140883
This commit is contained in:
parent
93a2a2fa12
commit
079a688663
|
@ -87,14 +87,19 @@ export class ExplorerDataSource implements IAsyncDataSource<ExplorerItem | Explo
|
|||
return Array.isArray(element) || element.hasChildren;
|
||||
}
|
||||
|
||||
getChildren(element: ExplorerItem | ExplorerItem[]): Promise<ExplorerItem[]> {
|
||||
getChildren(element: ExplorerItem | ExplorerItem[]): ExplorerItem[] | Promise<ExplorerItem[]> {
|
||||
if (Array.isArray(element)) {
|
||||
return Promise.resolve(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
const wasError = element.isError;
|
||||
const sortOrder = this.explorerService.sortOrderConfiguration.sortOrder;
|
||||
const promise = element.fetchChildren(sortOrder).then(
|
||||
const children = element.fetchChildren(sortOrder);
|
||||
if (Array.isArray(children)) {
|
||||
// fast path when children are known sync (i.e. nested children)
|
||||
return children;
|
||||
}
|
||||
const promise = children.then(
|
||||
children => {
|
||||
// Clear previous error decoration on root folder
|
||||
if (element instanceof ExplorerItem && element.isRoot && !element.isError && wasError && this.contextService.getWorkbenchState() !== WorkbenchState.FOLDER) {
|
||||
|
|
|
@ -296,63 +296,66 @@ export class ExplorerItem {
|
|||
return this.children.get(this.getPlatformAwareName(name));
|
||||
}
|
||||
|
||||
async fetchChildren(sortOrder: SortOrder): Promise<ExplorerItem[]> {
|
||||
fetchChildren(sortOrder: SortOrder): ExplorerItem[] | Promise<ExplorerItem[]> {
|
||||
const nestingConfig = this.configService.getValue<IFilesConfiguration>().explorer.experimental.fileNesting;
|
||||
|
||||
// fast path when the children can be resolved sync
|
||||
if (nestingConfig.enabled && this.nestedChildren) { return this.nestedChildren; }
|
||||
|
||||
if (!this._isDirectoryResolved) {
|
||||
// Resolve metadata only when the mtime is needed since this can be expensive
|
||||
// Mtime is only used when the sort order is 'modified'
|
||||
const resolveMetadata = sortOrder === SortOrder.Modified;
|
||||
this.isError = false;
|
||||
try {
|
||||
const stat = await this.fileService.resolve(this.resource, { resolveSingleChildDescendants: true, resolveMetadata });
|
||||
const resolved = ExplorerItem.create(this.fileService, this.configService, stat, this);
|
||||
ExplorerItem.mergeLocalWithDisk(resolved, this);
|
||||
} catch (e) {
|
||||
this.isError = true;
|
||||
throw e;
|
||||
}
|
||||
this._isDirectoryResolved = true;
|
||||
}
|
||||
|
||||
const items: ExplorerItem[] = [];
|
||||
if (nestingConfig.enabled) {
|
||||
const fileChildren: [string, ExplorerItem][] = [];
|
||||
const dirChildren: [string, ExplorerItem][] = [];
|
||||
for (const child of this.children.entries()) {
|
||||
if (child[1].isDirectory) {
|
||||
dirChildren.push(child);
|
||||
} else {
|
||||
fileChildren.push(child);
|
||||
return (async () => {
|
||||
if (!this._isDirectoryResolved) {
|
||||
// Resolve metadata only when the mtime is needed since this can be expensive
|
||||
// Mtime is only used when the sort order is 'modified'
|
||||
const resolveMetadata = sortOrder === SortOrder.Modified;
|
||||
this.isError = false;
|
||||
try {
|
||||
const stat = await this.fileService.resolve(this.resource, { resolveSingleChildDescendants: true, resolveMetadata });
|
||||
const resolved = ExplorerItem.create(this.fileService, this.configService, stat, this);
|
||||
ExplorerItem.mergeLocalWithDisk(resolved, this);
|
||||
} catch (e) {
|
||||
this.isError = true;
|
||||
throw e;
|
||||
}
|
||||
this._isDirectoryResolved = true;
|
||||
}
|
||||
|
||||
const nested = this.buildFileNester().nest(fileChildren.map(([name]) => name));
|
||||
|
||||
for (const [fileEntryName, fileEntryItem] of fileChildren) {
|
||||
const nestedItems = nested.get(fileEntryName);
|
||||
if (nestedItems !== undefined) {
|
||||
fileEntryItem.nestedChildren = [];
|
||||
for (const name of nestedItems.keys()) {
|
||||
fileEntryItem.nestedChildren.push(assertIsDefined(this.children.get(name)));
|
||||
const items: ExplorerItem[] = [];
|
||||
if (nestingConfig.enabled) {
|
||||
const fileChildren: [string, ExplorerItem][] = [];
|
||||
const dirChildren: [string, ExplorerItem][] = [];
|
||||
for (const child of this.children.entries()) {
|
||||
if (child[1].isDirectory) {
|
||||
dirChildren.push(child);
|
||||
} else {
|
||||
fileChildren.push(child);
|
||||
}
|
||||
items.push(fileEntryItem);
|
||||
} else {
|
||||
fileEntryItem.nestedChildren = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [_, dirEntryItem] of dirChildren.values()) {
|
||||
items.push(dirEntryItem);
|
||||
}
|
||||
} else {
|
||||
this.children.forEach(child => {
|
||||
items.push(child);
|
||||
});
|
||||
}
|
||||
const nested = this.buildFileNester().nest(fileChildren.map(([name]) => name));
|
||||
|
||||
return items;
|
||||
for (const [fileEntryName, fileEntryItem] of fileChildren) {
|
||||
const nestedItems = nested.get(fileEntryName);
|
||||
if (nestedItems !== undefined) {
|
||||
fileEntryItem.nestedChildren = [];
|
||||
for (const name of nestedItems.keys()) {
|
||||
fileEntryItem.nestedChildren.push(assertIsDefined(this.children.get(name)));
|
||||
}
|
||||
items.push(fileEntryItem);
|
||||
} else {
|
||||
fileEntryItem.nestedChildren = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [_, dirEntryItem] of dirChildren.values()) {
|
||||
items.push(dirEntryItem);
|
||||
}
|
||||
} else {
|
||||
this.children.forEach(child => {
|
||||
items.push(child);
|
||||
});
|
||||
}
|
||||
return items;
|
||||
})();
|
||||
}
|
||||
|
||||
// TODO:@jkearl, share one nester across all explorer items and only build on config change
|
||||
|
|
Loading…
Reference in a new issue