Merge from vscode 011858832762aaff245b2336fb1c38166e7a10fb (#4663)

This commit is contained in:
Anthony Dresser
2019-03-22 13:07:54 -07:00
committed by GitHub
parent f5c9174c2f
commit 4a87a24235
296 changed files with 2531 additions and 2472 deletions

View File

@@ -25,7 +25,7 @@ export class ContextSubMenu extends SubmenuAction {
export interface IContextMenuDelegate {
getAnchor(): HTMLElement | { x: number; y: number; width?: number; height?: number; };
getActions(): Array<IAction | ContextSubMenu>;
getActionItem?(action: IAction): IActionItem | null;
getActionItem?(action: IAction): IActionItem | undefined;
getActionsContext?(event?: IContextMenuEvent): any;
getKeyBinding?(action: IAction): ResolvedKeybinding | undefined;
getMenuClassName?(): string;

View File

@@ -364,7 +364,7 @@ export interface ActionTrigger {
}
export interface IActionItemProvider {
(action: IAction): IActionItem | null;
(action: IAction): IActionItem | undefined;
}
export interface IActionBarOptions {
@@ -609,7 +609,7 @@ export class ActionBar extends Disposable implements IActionRunner {
e.stopPropagation();
}));
let item: IActionItem | null = null;
let item: IActionItem | undefined;
if (this.options.actionItemProvider) {
item = this.options.actionItemProvider(action);

View File

@@ -118,7 +118,7 @@ export class ContextView extends Disposable {
this._register(toDisposable(() => this.setContainer(null)));
}
public setContainer(container: HTMLElement | null): void {
setContainer(container: HTMLElement | null): void {
if (this.container) {
this.toDisposeOnSetContainer = dispose(this.toDisposeOnSetContainer);
this.container.removeChild(this.view);
@@ -146,7 +146,7 @@ export class ContextView extends Disposable {
}
}
public show(delegate: IDelegate): void {
show(delegate: IDelegate): void {
if (this.isVisible()) {
this.hide();
}
@@ -173,7 +173,7 @@ export class ContextView extends Disposable {
}
}
public layout(): void {
layout(): void {
if (!this.isVisible()) {
return;
}
@@ -258,7 +258,7 @@ export class ContextView extends Disposable {
this.view.style.width = 'initial';
}
public hide(data?: any): void {
hide(data?: any): void {
if (this.delegate && this.delegate.onHide) {
this.delegate.onHide(data);
}
@@ -288,7 +288,7 @@ export class ContextView extends Disposable {
}
}
public dispose(): void {
dispose(): void {
this.hide();
super.dispose();

View File

@@ -247,7 +247,7 @@ export class DropdownMenu extends BaseDropdown {
getAnchor: () => this.element,
getActions: () => this.actions,
getActionsContext: () => this.menuOptions ? this.menuOptions.context : null,
getActionItem: action => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : null,
getActionItem: action => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : undefined,
getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : undefined,
getMenuClassName: () => this.menuClassName,
onHide: () => this.onHide(),

View File

@@ -63,7 +63,7 @@ const DefaultOptions = {
setRowLineHeight: true,
supportDynamicHeights: false,
dnd: {
getDragElements(e) { return [e]; },
getDragElements<T>(e: T) { return [e]; },
getDragURI() { return null; },
onDragStart(): void { },
onDragOver() { return false; },

View File

@@ -860,8 +860,8 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate<I
this.selectionDetailsPane.innerText = '';
const selectedIndex = e.indexes[0];
const description = this.options[selectedIndex].description || null;
const descriptionIsMarkdown = this.options[selectedIndex].descriptionIsMarkdown || null;
const description = this.options[selectedIndex].description;
const descriptionIsMarkdown = this.options[selectedIndex].descriptionIsMarkdown;
if (description) {
if (descriptionIsMarkdown) {

View File

@@ -75,10 +75,10 @@ export class ToolBar extends Disposable {
);
this.toggleMenuActionItem!.setActionContext(this.actionBar.context);
return this.toggleMenuActionItem || null;
return this.toggleMenuActionItem;
}
return options.actionItemProvider ? options.actionItemProvider(action) : null;
return options.actionItemProvider ? options.actionItemProvider(action) : undefined;
}
}));
}

View File

@@ -805,7 +805,7 @@ class Trait<T> {
onDidModelSplice({ insertedNodes, deletedNodes }: ITreeModelSpliceEvent<T, any>): void {
if (!this.identityProvider) {
const set = this.createNodeSet();
const visit = node => set.delete(node);
const visit = (node: ITreeNode<T, any>) => set.delete(node);
deletedNodes.forEach(node => dfs(node, visit));
this.set(values(set));
return;
@@ -816,8 +816,8 @@ class Trait<T> {
this.nodes.forEach(node => nodesByIdentity.set(identityProvider.getId(node.element).toString(), node));
const toDeleteByIdentity = new Map<string, ITreeNode<T, any>>();
const toRemoveSetter = node => toDeleteByIdentity.set(identityProvider.getId(node.element).toString(), node);
const toRemoveDeleter = node => toDeleteByIdentity.delete(identityProvider.getId(node.element).toString());
const toRemoveSetter = (node: ITreeNode<T, any>) => toDeleteByIdentity.set(identityProvider.getId(node.element).toString(), node);
const toRemoveDeleter = (node: { element: T; }) => toDeleteByIdentity.delete(identityProvider.getId(node.element).toString());
deletedNodes.forEach(node => dfs(node, toRemoveSetter));
insertedNodes.forEach(node => dfs(node, toRemoveDeleter));

View File

@@ -16,6 +16,7 @@ import { IDragAndDropData } from 'vs/base/browser/dnd';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
import { toggleClass } from 'vs/base/browser/dom';
import { values } from 'vs/base/common/map';
interface IAsyncDataTreeNode<TInput, T> {
element: TInput | T;
@@ -26,7 +27,6 @@ interface IAsyncDataTreeNode<TInput, T> {
hasChildren: boolean;
stale: boolean;
slow: boolean;
disposed: boolean;
}
interface IAsyncDataTreeNodeRequiredProps<TInput, T> extends Partial<IAsyncDataTreeNode<TInput, T>> {
@@ -41,7 +41,6 @@ function createAsyncDataTreeNode<TInput, T>(props: IAsyncDataTreeNodeRequiredPro
children: [],
loading: false,
stale: true,
disposed: false,
slow: false
};
}
@@ -274,6 +273,11 @@ interface IAsyncDataTreeViewStateContext<TInput, T> {
readonly focus: IAsyncDataTreeNode<TInput, T>[];
}
function dfs<TInput, T>(node: IAsyncDataTreeNode<TInput, T>, fn: (node: IAsyncDataTreeNode<TInput, T>) => void): void {
fn(node);
node.children.forEach(child => dfs(child, fn));
}
export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable {
private readonly tree: ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
@@ -629,11 +633,6 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
private async refreshNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
if (node.disposed) {
console.error('Async data tree node is disposed');
return;
}
let result: Promise<void> | undefined;
this.subTreeRefreshPromises.forEach((refreshPromise, refreshNode) => {
@@ -748,37 +747,47 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return [];
}
let nodeChildren: Map<string, IAsyncDataTreeNode<TInput, T>> | undefined;
const nodesToForget = new Map<T, IAsyncDataTreeNode<TInput, T>>();
const childrenTreeNodesById = new Map<string, ITreeNode<IAsyncDataTreeNode<TInput, T> | null, TFilterData>>();
if (this.identityProvider) {
nodeChildren = new Map();
for (const child of node.children) {
nodesToForget.set(child.element as T, child);
for (const child of node.children) {
nodeChildren.set(child.id!, child);
if (this.identityProvider) {
childrenTreeNodesById.set(child.id!, this.tree.getNode(child));
}
}
let childrenToRefresh: IAsyncDataTreeNode<TInput, T>[] = [];
const childrenToRefresh: IAsyncDataTreeNode<TInput, T>[] = [];
const children = childrenElements.map<IAsyncDataTreeNode<TInput, T>>(element => {
if (!this.identityProvider) {
return createAsyncDataTreeNode({
element,
parent: node,
hasChildren: !!this.dataSource.hasChildren(element),
hasChildren: !!this.dataSource.hasChildren(element)
});
}
const id = this.identityProvider.getId(element).toString();
const asyncDataTreeNode = nodeChildren!.get(id);
const childNode = childrenTreeNodesById.get(id);
if (childNode) {
const asyncDataTreeNode = childNode.element!;
nodesToForget.delete(asyncDataTreeNode.element as T);
this.nodes.delete(asyncDataTreeNode.element as T);
this.nodes.set(element, asyncDataTreeNode);
if (asyncDataTreeNode) {
asyncDataTreeNode.element = element;
asyncDataTreeNode.stale = asyncDataTreeNode.stale || recursive;
asyncDataTreeNode.hasChildren = !!this.dataSource.hasChildren(element);
if (recursive && !this.tree.isCollapsed(asyncDataTreeNode)) {
childrenToRefresh.push(asyncDataTreeNode);
if (recursive) {
if (childNode.collapsed) {
dfs(asyncDataTreeNode, node => node.stale = true);
} else {
childrenToRefresh.push(asyncDataTreeNode);
}
}
return asyncDataTreeNode;
@@ -806,33 +815,22 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return childAsyncDataTreeNode;
});
for (const node of values(nodesToForget)) {
dfs(node, node => this.nodes.delete(node.element as T));
}
for (const child of children) {
this.nodes.set(child.element as T, child);
}
node.children.splice(0, node.children.length, ...children);
return childrenToRefresh;
}
private render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
const insertedElements = new Set<T>();
const onDidCreateNode = (treeNode: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>) => {
if (treeNode.element.element) {
insertedElements.add(treeNode.element.element as T);
this.nodes.set(treeNode.element.element as T, treeNode.element);
}
};
const onDidDeleteNode = (treeNode: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>) => {
if (treeNode.element.element) {
if (!insertedElements.has(treeNode.element.element as T)) {
treeNode.element.disposed = true;
this.nodes.delete(treeNode.element.element as T);
}
}
};
const children = node.children.map(c => asTreeElement(c, viewStateContext));
this.tree.setChildren(node === this.root ? null : node, children, onDidCreateNode, onDidDeleteNode);
this.tree.setChildren(node === this.root ? null : node, children);
this._onDidRender.fire();
}

View File

@@ -198,8 +198,17 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
}
getNode(element: T | null = null): ITreeNode<T | null, TFilterData> {
const location = this.getElementLocation(element);
return this.model.getNode(location);
if (element === null) {
return this.model.getNode(this.model.rootRef);
}
const node = this.nodes.get(element);
if (!node) {
throw new Error(`Tree element not found: ${element}`);
}
return node;
}
getNodeLocation(node: ITreeNode<T, TFilterData>): T {