mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-27 12:04:04 +01:00
FIx #47262
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostContext, MainThreadTreeViewsShape, ExtHostTreeViewsShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
|
||||
@@ -29,7 +28,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
}
|
||||
|
||||
$registerTreeViewDataProvider(treeViewId: string): void {
|
||||
const dataProvider = this._register(new TreeViewDataProvider(treeViewId, this._proxy, this.notificationService));
|
||||
const dataProvider = new TreeViewDataProvider(treeViewId, this._proxy, this.notificationService);
|
||||
this._dataProviders.set(treeViewId, dataProvider);
|
||||
const treeViewer = this.viewsService.getTreeViewer(treeViewId);
|
||||
if (treeViewer) {
|
||||
@@ -48,11 +47,14 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
});
|
||||
}
|
||||
|
||||
$refresh(treeViewId: string, itemsToRefresh: { [treeItemHandle: string]: ITreeItem }): void {
|
||||
$refresh(treeViewId: string, itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): TPromise<void> {
|
||||
const viewer = this.viewsService.getTreeViewer(treeViewId);
|
||||
const dataProvider = this._dataProviders.get(treeViewId);
|
||||
if (dataProvider) {
|
||||
dataProvider.refresh(itemsToRefresh);
|
||||
if (viewer && dataProvider) {
|
||||
const itemsToRefresh = dataProvider.getItemsToRefresh(itemsToRefreshByHandle);
|
||||
return viewer.refresh(itemsToRefresh.length ? itemsToRefresh : void 0);
|
||||
}
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
private registerListeners(treeViewId: string, treeViewer: ITreeViewer): void {
|
||||
@@ -62,6 +64,12 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._dataProviders.forEach((dataProvider, treeViewId) => {
|
||||
const treeViewer = this.viewsService.getTreeViewer(treeViewId);
|
||||
if (treeViewer) {
|
||||
treeViewer.dataProvider = null;
|
||||
}
|
||||
});
|
||||
this._dataProviders.clear();
|
||||
super.dispose();
|
||||
}
|
||||
@@ -71,12 +79,6 @@ type TreeItemHandle = string;
|
||||
|
||||
class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
|
||||
private readonly _onDidChange: Emitter<ITreeItem[] | undefined | null> = new Emitter<ITreeItem[] | undefined | null>();
|
||||
readonly onDidChange: Event<ITreeItem[] | undefined | null> = this._onDidChange.event;
|
||||
|
||||
private readonly _onDispose: Emitter<void> = new Emitter<void>();
|
||||
readonly onDispose: Event<void> = this._onDispose.event;
|
||||
|
||||
private itemsMap: Map<TreeItemHandle, ITreeItem> = new Map<TreeItemHandle, ITreeItem>();
|
||||
|
||||
constructor(private treeViewId: string,
|
||||
@@ -98,7 +100,7 @@ class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
});
|
||||
}
|
||||
|
||||
refresh(itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }) {
|
||||
getItemsToRefresh(itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): ITreeItem[] {
|
||||
const itemsToRefresh: ITreeItem[] = [];
|
||||
if (itemsToRefreshByHandle) {
|
||||
for (const treeItemHandle of Object.keys(itemsToRefreshByHandle)) {
|
||||
@@ -121,11 +123,7 @@ class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itemsToRefresh.length) {
|
||||
this._onDidChange.fire(itemsToRefresh);
|
||||
} else {
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
return itemsToRefresh;
|
||||
}
|
||||
|
||||
private postGetChildren(elements: ITreeItem[]): ITreeItem[] {
|
||||
@@ -148,8 +146,4 @@ class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._onDispose.fire();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
|
||||
export interface MainThreadTreeViewsShape extends IDisposable {
|
||||
$registerTreeViewDataProvider(treeViewId: string): void;
|
||||
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): void;
|
||||
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): TPromise<void>;
|
||||
$reveal(treeViewId: string, treeItem: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void>;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,11 +119,25 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
private _onDidCollapseElement: Emitter<T> = this._register(new Emitter<T>());
|
||||
readonly onDidCollapseElement: Event<T> = this._onDidCollapseElement.event;
|
||||
|
||||
private refreshPromise: TPromise<void> = TPromise.as(null);
|
||||
|
||||
constructor(private viewId: string, private dataProvider: vscode.TreeDataProvider<T>, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter) {
|
||||
super();
|
||||
this.proxy.$registerTreeViewDataProvider(viewId);
|
||||
if (this.dataProvider.onDidChangeTreeData) {
|
||||
this._register(debounceEvent<T, T[]>(this.dataProvider.onDidChangeTreeData, (last, current) => last ? [...last, current] : [current], 200)(elements => this.refresh(elements)));
|
||||
let refreshingPromise, promiseCallback;
|
||||
this._register(debounceEvent<T, T[]>(this.dataProvider.onDidChangeTreeData, (last, current) => {
|
||||
if (!refreshingPromise) {
|
||||
// New refresh has started
|
||||
refreshingPromise = new TPromise((c, e) => promiseCallback = c);
|
||||
this.refreshPromise = this.refreshPromise.then(() => refreshingPromise);
|
||||
}
|
||||
return last ? [...last, current] : [current];
|
||||
}, 200, true)(elements => {
|
||||
const _promiseCallback = promiseCallback;
|
||||
refreshingPromise = null;
|
||||
this.refresh(elements).then(() => _promiseCallback());
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,9 +159,10 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
|
||||
reveal(element: T, options?: { select?: boolean }): TPromise<void> {
|
||||
if (typeof this.dataProvider.getParent !== 'function') {
|
||||
return TPromise.wrapError(new Error(`Required registered TreeDataProvider to implement 'getParent' method to access 'reveal' mehtod`));
|
||||
return TPromise.wrapError(new Error(`Required registered TreeDataProvider to implement 'getParent' method to access 'reveal' method`));
|
||||
}
|
||||
return this.resolveUnknownParentChain(element)
|
||||
return this.refreshPromise
|
||||
.then(() => this.resolveUnknownParentChain(element))
|
||||
.then(parentChain => this.resolveTreeNode(element, parentChain[parentChain.length - 1])
|
||||
.then(treeNode => this.proxy.$reveal(this.viewId, treeNode.item, parentChain.map(p => p.item), options)));
|
||||
}
|
||||
@@ -234,17 +249,18 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
.then(nodes => nodes.filter(n => !!n));
|
||||
}
|
||||
|
||||
private refresh(elements: T[]): void {
|
||||
private refresh(elements: T[]): TPromise<void> {
|
||||
const hasRoot = elements.some(element => !element);
|
||||
if (hasRoot) {
|
||||
this.clearAll(); // clear cache
|
||||
this.proxy.$refresh(this.viewId);
|
||||
return this.proxy.$refresh(this.viewId);
|
||||
} else {
|
||||
const handlesToRefresh = this.getHandlesToRefresh(elements);
|
||||
if (handlesToRefresh.length) {
|
||||
this.refreshHandles(handlesToRefresh);
|
||||
return this.refreshHandles(handlesToRefresh);
|
||||
}
|
||||
}
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
private getHandlesToRefresh(elements: T[]): TreeItemHandle[] {
|
||||
|
||||
Reference in New Issue
Block a user