Vscode merge (#4582)

* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd

* fix issues with merges

* bump node version in azpipe

* replace license headers

* remove duplicate launch task

* fix build errors

* fix build errors

* fix tslint issues

* working through package and linux build issues

* more work

* wip

* fix packaged builds

* working through linux build errors

* wip

* wip

* wip

* fix mac and linux file limits

* iterate linux pipeline

* disable editor typing

* revert series to parallel

* remove optimize vscode from linux

* fix linting issues

* revert testing change

* add work round for new node

* readd packaging for extensions

* fix issue with angular not resolving decorator dependencies
This commit is contained in:
Anthony Dresser
2019-03-19 17:44:35 -07:00
committed by GitHub
parent 833d197412
commit 87765e8673
1879 changed files with 54505 additions and 38058 deletions

View File

@@ -9,7 +9,7 @@ import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOve
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { timeout, always, CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
import { timeout, CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
import { Iterator } from 'vs/base/common/iterator';
import { IDragAndDropData } from 'vs/base/browser/dnd';
@@ -17,24 +17,35 @@ import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
import { toggleClass } from 'vs/base/browser/dom';
const enum AsyncDataTreeNodeState {
Uninitialized = 'uninitialized',
Loaded = 'loaded',
Loading = 'loading'
}
interface IAsyncDataTreeNode<TInput, T> {
element: TInput | T;
readonly parent: IAsyncDataTreeNode<TInput, T> | null;
readonly children: IAsyncDataTreeNode<TInput, T>[];
readonly id?: string | null;
state: AsyncDataTreeNodeState;
loading: boolean;
hasChildren: boolean;
needsRefresh: boolean;
stale: boolean;
slow: boolean;
disposed: boolean;
}
interface IAsyncDataTreeNodeRequiredProps<TInput, T> extends Partial<IAsyncDataTreeNode<TInput, T>> {
readonly element: TInput | T;
readonly parent: IAsyncDataTreeNode<TInput, T> | null;
readonly hasChildren: boolean;
}
function createAsyncDataTreeNode<TInput, T>(props: IAsyncDataTreeNodeRequiredProps<TInput, T>): IAsyncDataTreeNode<TInput, T> {
return {
...props,
children: [],
loading: false,
stale: true,
disposed: false,
slow: false
};
}
function isAncestor<TInput, T>(ancestor: IAsyncDataTreeNode<TInput, T>, descendant: IAsyncDataTreeNode<TInput, T>): boolean {
if (!descendant.parent) {
return false;
@@ -87,8 +98,8 @@ class DataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements ITreeRe
return { templateData };
}
renderElement(node: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>): void {
this.renderer.renderElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData);
renderElement(node: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>, dynamicHeightProbing?: boolean): void {
this.renderer.renderElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData, dynamicHeightProbing);
}
renderTwistie(element: IAsyncDataTreeNode<TInput, T>, twistieElement: HTMLElement): boolean {
@@ -96,9 +107,9 @@ class DataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements ITreeRe
return false;
}
disposeElement(node: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>): void {
disposeElement(node: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>, dynamicHeightProbing?: boolean): void {
if (this.renderer.disposeElement) {
this.renderer.disposeElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData);
this.renderer.disposeElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData, dynamicHeightProbing);
}
}
@@ -217,20 +228,26 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e.element as T);
}
},
sorter: undefined
sorter: undefined,
expandOnlyOnTwistieClick: typeof options.expandOnlyOnTwistieClick === 'undefined' ? undefined : (
typeof options.expandOnlyOnTwistieClick !== 'function' ? options.expandOnlyOnTwistieClick : (
e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)
)
),
ariaSetProvider: undefined
};
}
function asTreeElement<TInput, T>(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): ITreeElement<IAsyncDataTreeNode<TInput, T>> {
let collapsed: boolean | undefined;
if (viewStateContext && node.id) {
if (viewStateContext && viewStateContext.viewState.expanded && node.id) {
collapsed = viewStateContext.viewState.expanded.indexOf(node.id) === -1;
}
return {
element: node,
children: Iterator.map(Iterator.fromArray(node.children), child => asTreeElement(child, viewStateContext)),
children: node.hasChildren ? Iterator.map(Iterator.fromArray(node.children), child => asTreeElement(child, viewStateContext)) : [],
collapsible: node.hasChildren,
collapsed
};
@@ -245,9 +262,10 @@ export interface IAsyncDataTreeOptions<T, TFilterData = void> extends IAsyncData
}
export interface IAsyncDataTreeViewState {
readonly focus: string[];
readonly selection: string[];
readonly expanded: string[];
readonly focus?: string[];
readonly selection?: string[];
readonly expanded?: string[];
readonly scrollTop?: number;
}
interface IAsyncDataTreeViewStateContext<TInput, T> {
@@ -260,7 +278,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
private readonly tree: ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
private readonly root: IAsyncDataTreeNode<TInput, T>;
private readonly renderedNodes = new Map<null | T, IAsyncDataTreeNode<TInput, T>>();
private readonly nodes = new Map<null | T, IAsyncDataTreeNode<TInput, T>>();
private readonly sorter?: ITreeSorter<T>;
private readonly subTreeRefreshPromises = new Map<IAsyncDataTreeNode<TInput, T>, Promise<void>>();
@@ -280,12 +298,15 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
get onDidChangeSelection(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidChangeSelection, asTreeEvent); }
get onDidOpen(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidOpen, asTreeEvent); }
get onKeyDown(): Event<KeyboardEvent> { return this.tree.onKeyDown; }
get onMouseClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.tree.onMouseClick, asTreeMouseEvent); }
get onMouseDblClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.tree.onMouseDblClick, asTreeMouseEvent); }
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return Event.map(this.tree.onContextMenu, asTreeContextMenuEvent); }
get onDidFocus(): Event<void> { return this.tree.onDidFocus; }
get onDidBlur(): Event<void> { return this.tree.onDidBlur; }
get onDidUpdateOptions(): Event<IAsyncDataTreeOptionsUpdate> { return this.tree.onDidUpdateOptions; }
get filterOnType(): boolean { return this.tree.filterOnType; }
get openOnSingleClick(): boolean { return this.tree.openOnSingleClick; }
@@ -308,16 +329,11 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
this.tree = new ObjectTree(container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);
this.root = {
this.root = createAsyncDataTreeNode({
element: undefined!,
parent: null,
children: [],
state: AsyncDataTreeNodeState.Uninitialized,
hasChildren: true,
needsRefresh: false,
disposed: false,
slow: false
};
hasChildren: true
});
if (this.identityProvider) {
this.root = {
@@ -326,7 +342,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
};
}
this.renderedNodes.set(null, this.root);
this.nodes.set(null, this.root);
this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables);
}
@@ -365,6 +381,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return this.tree.renderHeight;
}
get firstVisibleElement(): T {
return this.tree.firstVisibleElement!.element as T;
}
get lastVisibleElement(): T {
return this.tree.lastVisibleElement!.element as T;
}
domFocus(): void {
this.tree.domFocus();
}
@@ -397,6 +421,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
this.tree.setFocus(viewStateContext.focus);
this.tree.setSelection(viewStateContext.selection);
}
if (viewState && typeof viewState.scrollTop === 'number') {
this.scrollTop = viewState.scrollTop;
}
}
async updateChildren(element: TInput | T = this.root.element, recursive = true, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
@@ -404,7 +432,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
throw new Error('Tree input not set');
}
if (this.root.state === AsyncDataTreeNodeState.Loading) {
if (this.root.loading) {
await this.subTreeRefreshPromises.get(this.root)!;
await Event.toPromise(this._onDidRender.event);
}
@@ -412,15 +440,24 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
await this.refreshAndRenderNode(this.getDataNode(element), recursive, ChildrenResolutionReason.Refresh, viewStateContext);
}
resort(element: TInput | T = this.root.element, recursive = true): void {
this.tree.resort(this.getDataNode(element), recursive);
}
hasNode(element: TInput | T): boolean {
return element === this.root.element || this.renderedNodes.has(element as T);
return element === this.root.element || this.nodes.has(element as T);
}
// View
refresh(element: T): void {
rerender(element?: T): void {
if (element === undefined) {
this.tree.rerender();
return;
}
const node = this.getDataNode(element);
this.tree.refresh(node);
this.tree.rerender(node);
}
updateWidth(element: T): void {
@@ -446,20 +483,20 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
throw new Error('Tree input not set');
}
if (this.root.state === AsyncDataTreeNodeState.Loading) {
if (this.root.loading) {
await this.subTreeRefreshPromises.get(this.root)!;
await Event.toPromise(this._onDidRender.event);
}
const node = this.getDataNode(element);
if (node !== this.root && node.state !== AsyncDataTreeNodeState.Loading && !this.tree.isCollapsed(node)) {
if (node !== this.root && !node.loading && !this.tree.isCollapsed(node)) {
return false;
}
const result = this.tree.expand(node === this.root ? null : node, recursive);
if (node.state === AsyncDataTreeNodeState.Loading) {
if (node.loading) {
await this.subTreeRefreshPromises.get(node)!;
await Event.toPromise(this._onDidRender.event);
}
@@ -565,16 +602,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return (node && node.element)!;
}
// List
get visibleNodeCount(): number {
return this.tree.visibleNodeCount;
}
// Implementation
private getDataNode(element: TInput | T): IAsyncDataTreeNode<TInput, T> {
const node: IAsyncDataTreeNode<TInput, T> | undefined = this.renderedNodes.get((element === this.root.element ? null : element) as T);
const node: IAsyncDataTreeNode<TInput, T> | undefined = this.nodes.get((element === this.root.element ? null : element) as T);
if (!node) {
throw new Error(`Data tree node not found: ${element}`);
@@ -626,39 +657,19 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
private async doRefreshSubTree(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
node.state = AsyncDataTreeNodeState.Loading;
node.loading = true;
try {
await this.doRefreshNode(node, recursive, viewStateContext);
const childrenToRefresh = await this.doRefreshNode(node, recursive, viewStateContext);
node.stale = false;
if (recursive) {
const childrenToRefresh = node.children
.filter(child => {
if (child.needsRefresh) {
child.needsRefresh = false;
return true;
}
// TODO@joao: is this still needed?
if (child.hasChildren && child.state === AsyncDataTreeNodeState.Loaded) {
return true;
}
if (!viewStateContext || !child.id) {
return false;
}
return viewStateContext.viewState.expanded.indexOf(child.id) > -1;
});
await Promise.all(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext)));
}
await Promise.all(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext)));
} finally {
node.state = AsyncDataTreeNodeState.Loaded;
node.loading = false;
}
}
private async doRefreshNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
private async doRefreshNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<IAsyncDataTreeNode<TInput, T>[]> {
node.hasChildren = !!this.dataSource.hasChildren(node.element!);
let childrenPromise: Promise<T[]>;
@@ -673,21 +684,20 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
this._onDidChangeNodeSlowState.fire(node);
}, _ => null);
childrenPromise = always(this.doGetChildren(node), () => slowTimeout.cancel());
childrenPromise = this.doGetChildren(node)
.finally(() => slowTimeout.cancel());
}
try {
const children = await childrenPromise;
this.setChildren(node, children, recursive, viewStateContext);
return this.setChildren(node, children, recursive, viewStateContext);
} catch (err) {
node.needsRefresh = true;
if (node !== this.root) {
this.tree.collapse(node === this.root ? null : node);
}
if (isPromiseCanceledError(err)) {
return;
return [];
}
throw err;
@@ -715,12 +725,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return children;
});
this.refreshPromises.set(node, result);
return always(result, () => this.refreshPromises.delete(node));
return result.finally(() => this.refreshPromises.delete(node));
}
private _onDidChangeCollapseState({ node, deep }: ICollapseStateChangeEvent<IAsyncDataTreeNode<TInput, T>, any>): void {
if (!node.collapsed && (node.element.state === AsyncDataTreeNodeState.Uninitialized || node.element.needsRefresh)) {
if (!node.collapsed && node.element.stale) {
if (deep) {
this.collapse(node.element.element as T);
} else {
@@ -730,7 +742,12 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
}
private setChildren(node: IAsyncDataTreeNode<TInput, T>, childrenElements: T[], recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
private setChildren(node: IAsyncDataTreeNode<TInput, T>, childrenElements: T[], recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): IAsyncDataTreeNode<TInput, T>[] {
// perf: if the node was and still is a leaf, avoid all this hassle
if (node.children.length === 0 && childrenElements.length === 0) {
return [];
}
let nodeChildren: Map<string, IAsyncDataTreeNode<TInput, T>> | undefined;
if (this.identityProvider) {
@@ -741,66 +758,57 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
}
let childrenToRefresh: IAsyncDataTreeNode<TInput, T>[] = [];
const children = childrenElements.map<IAsyncDataTreeNode<TInput, T>>(element => {
if (!this.identityProvider) {
const hasChildren = !!this.dataSource.hasChildren(element);
return {
return createAsyncDataTreeNode({
element,
parent: node,
children: [],
state: AsyncDataTreeNodeState.Uninitialized,
hasChildren,
needsRefresh: false,
disposed: false,
slow: false
};
hasChildren: !!this.dataSource.hasChildren(element),
});
}
const id = this.identityProvider.getId(element).toString();
const asyncDataTreeNode = nodeChildren!.get(id);
if (!asyncDataTreeNode) {
const childAsyncDataTreeNode: IAsyncDataTreeNode<TInput, T> = {
element,
parent: node,
children: [],
id,
state: AsyncDataTreeNodeState.Uninitialized,
hasChildren: !!this.dataSource.hasChildren(element),
needsRefresh: false,
disposed: false,
slow: false
};
if (asyncDataTreeNode) {
asyncDataTreeNode.element = element;
asyncDataTreeNode.stale = asyncDataTreeNode.stale || recursive;
asyncDataTreeNode.hasChildren = !!this.dataSource.hasChildren(element);
if (viewStateContext) {
if (viewStateContext.viewState.focus.indexOf(id) > -1) {
viewStateContext.focus.push(childAsyncDataTreeNode);
}
if (viewStateContext.viewState.selection.indexOf(id) > -1) {
viewStateContext.selection.push(childAsyncDataTreeNode);
}
if (recursive && !this.tree.isCollapsed(asyncDataTreeNode)) {
childrenToRefresh.push(asyncDataTreeNode);
}
return childAsyncDataTreeNode;
return asyncDataTreeNode;
}
asyncDataTreeNode.element = element;
const childAsyncDataTreeNode = createAsyncDataTreeNode({
element,
parent: node,
id,
hasChildren: !!this.dataSource.hasChildren(element)
});
if (asyncDataTreeNode.state === AsyncDataTreeNodeState.Loaded || asyncDataTreeNode.hasChildren !== !!this.dataSource.hasChildren(asyncDataTreeNode.element)) {
asyncDataTreeNode.needsRefresh = true;
if (viewStateContext && viewStateContext.viewState.focus && viewStateContext.viewState.focus.indexOf(id) > -1) {
viewStateContext.focus.push(childAsyncDataTreeNode);
}
return asyncDataTreeNode;
if (viewStateContext && viewStateContext.viewState.selection && viewStateContext.viewState.selection.indexOf(id) > -1) {
viewStateContext.selection.push(childAsyncDataTreeNode);
}
if (viewStateContext && viewStateContext.viewState.expanded && viewStateContext.viewState.expanded.indexOf(id) > -1) {
childrenToRefresh.push(childAsyncDataTreeNode);
}
return childAsyncDataTreeNode;
});
// perf: if the node was and still is a leaf, avoid all these expensive no-ops
if (node.children.length === 0 && childrenElements.length === 0) {
return;
}
node.children.splice(0, node.children.length, ...children);
return childrenToRefresh;
}
private render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
@@ -809,7 +817,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
const onDidCreateNode = (treeNode: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>) => {
if (treeNode.element.element) {
insertedElements.add(treeNode.element.element as T);
this.renderedNodes.set(treeNode.element.element as T, treeNode.element);
this.nodes.set(treeNode.element.element as T, treeNode.element);
}
};
@@ -817,7 +825,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
if (treeNode.element.element) {
if (!insertedElements.has(treeNode.element.element as T)) {
treeNode.element.disposed = true;
this.renderedNodes.delete(treeNode.element.element as T);
this.nodes.delete(treeNode.element.element as T);
}
}
};
@@ -853,7 +861,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
queue.push(...node.children);
}
return { focus, selection, expanded };
return { focus, selection, expanded, scrollTop: this.scrollTop };
}
dispose(): void {