chore(vscode): update to 1.53.2
These conflicts will be resolved in the following commits. We do it this way so that PR review is possible.
This commit is contained in:
@ -3,8 +3,10 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
|
||||
import { ICollapseStateChangeEvent, ITreeElement, ITreeFilter, ITreeFilterDataResult, ITreeModel, ITreeNode, TreeVisibility, ITreeModelSpliceEvent, TreeError } from 'vs/base/browser/ui/tree/tree';
|
||||
import { tail2 } from 'vs/base/common/arrays';
|
||||
import { LcsDiff } from 'vs/base/common/diff/diff';
|
||||
import { Emitter, Event, EventBufferer } from 'vs/base/common/event';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { ISpliceable } from 'vs/base/common/sequence';
|
||||
@ -41,6 +43,34 @@ export interface IIndexTreeModelOptions<T, TFilterData> {
|
||||
readonly autoExpandSingleChildren?: boolean;
|
||||
}
|
||||
|
||||
export interface IIndexTreeModelSpliceOptions<T, TFilterData> {
|
||||
/**
|
||||
* If set, child updates will recurse the given number of levels even if
|
||||
* items in the splice operation are unchanged. `Infinity` is a valid value.
|
||||
*/
|
||||
readonly diffDepth?: number;
|
||||
|
||||
/**
|
||||
* Identity provider used to optimize splice() calls in the IndexTree. If
|
||||
* this is not present, optimized splicing is not enabled.
|
||||
*
|
||||
* Warning: if this is present, calls to `setChildren()` will not replace
|
||||
* or update nodes if their identity is the same, even if the elements are
|
||||
* different. For this, you should call `rerender()`.
|
||||
*/
|
||||
readonly diffIdentityProvider?: IIdentityProvider<T>;
|
||||
|
||||
/**
|
||||
* Callback for when a node is created.
|
||||
*/
|
||||
onDidCreateNode?: (node: ITreeNode<T, TFilterData>) => void;
|
||||
|
||||
/**
|
||||
* Callback for when a node is deleted.
|
||||
*/
|
||||
onDidDeleteNode?: (node: ITreeNode<T, TFilterData>) => void
|
||||
}
|
||||
|
||||
interface CollapsibleStateUpdate {
|
||||
readonly collapsible: boolean;
|
||||
}
|
||||
@ -110,18 +140,95 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
location: number[],
|
||||
deleteCount: number,
|
||||
toInsert: Iterable<ITreeElement<T>> = Iterable.empty(),
|
||||
onDidCreateNode?: (node: ITreeNode<T, TFilterData>) => void,
|
||||
onDidDeleteNode?: (node: ITreeNode<T, TFilterData>) => void
|
||||
options: IIndexTreeModelSpliceOptions<T, TFilterData> = {},
|
||||
): void {
|
||||
if (location.length === 0) {
|
||||
throw new TreeError(this.user, 'Invalid tree location');
|
||||
}
|
||||
|
||||
if (options.diffIdentityProvider) {
|
||||
this.spliceSmart(options.diffIdentityProvider, location, deleteCount, toInsert, options);
|
||||
} else {
|
||||
this.spliceSimple(location, deleteCount, toInsert, options);
|
||||
}
|
||||
}
|
||||
|
||||
private spliceSmart(
|
||||
identity: IIdentityProvider<T>,
|
||||
location: number[],
|
||||
deleteCount: number,
|
||||
toInsertIterable: Iterable<ITreeElement<T>> = Iterable.empty(),
|
||||
options: IIndexTreeModelSpliceOptions<T, TFilterData>,
|
||||
recurseLevels = options.diffDepth ?? 0,
|
||||
) {
|
||||
const { parentNode } = this.getParentNodeWithListIndex(location);
|
||||
const toInsert = [...toInsertIterable];
|
||||
const index = location[location.length - 1];
|
||||
const diff = new LcsDiff(
|
||||
{ getElements: () => parentNode.children.map(e => identity.getId(e.element).toString()) },
|
||||
{
|
||||
getElements: () => [
|
||||
...parentNode.children.slice(0, index),
|
||||
...toInsert,
|
||||
...parentNode.children.slice(index + deleteCount),
|
||||
].map(e => identity.getId(e.element).toString())
|
||||
},
|
||||
).ComputeDiff(false);
|
||||
|
||||
// if we were given a 'best effort' diff, use default behavior
|
||||
if (diff.quitEarly) {
|
||||
return this.spliceSimple(location, deleteCount, toInsert, options);
|
||||
}
|
||||
|
||||
const locationPrefix = location.slice(0, -1);
|
||||
const recurseSplice = (fromOriginal: number, fromModified: number, count: number) => {
|
||||
if (recurseLevels > 0) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
fromOriginal--;
|
||||
fromModified--;
|
||||
this.spliceSmart(
|
||||
identity,
|
||||
[...locationPrefix, fromOriginal, 0],
|
||||
Number.MAX_SAFE_INTEGER,
|
||||
toInsert[fromModified].children,
|
||||
options,
|
||||
recurseLevels - 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let lastStartO = Math.min(parentNode.children.length, index + deleteCount);
|
||||
let lastStartM = toInsert.length;
|
||||
for (const change of diff.changes.sort((a, b) => b.originalStart - a.originalStart)) {
|
||||
recurseSplice(lastStartO, lastStartM, lastStartO - (change.originalStart + change.originalLength));
|
||||
lastStartO = change.originalStart;
|
||||
lastStartM = change.modifiedStart - index;
|
||||
|
||||
this.spliceSimple(
|
||||
[...locationPrefix, lastStartO],
|
||||
change.originalLength,
|
||||
Iterable.slice(toInsert, lastStartM, lastStartM + change.modifiedLength),
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
// at this point, startO === startM === count since any remaining prefix should match
|
||||
recurseSplice(lastStartO, lastStartM, lastStartO);
|
||||
}
|
||||
|
||||
private spliceSimple(
|
||||
location: number[],
|
||||
deleteCount: number,
|
||||
toInsert: Iterable<ITreeElement<T>> = Iterable.empty(),
|
||||
{ onDidCreateNode, onDidDeleteNode }: IIndexTreeModelSpliceOptions<T, TFilterData>,
|
||||
) {
|
||||
const { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location);
|
||||
const treeListElementsToInsert: ITreeNode<T, TFilterData>[] = [];
|
||||
const nodesToInsertIterator = Iterable.map(toInsert, el => this.createTreeNode(el, parentNode, parentNode.visible ? TreeVisibility.Visible : TreeVisibility.Hidden, revealed, treeListElementsToInsert, onDidCreateNode));
|
||||
|
||||
const lastIndex = location[location.length - 1];
|
||||
const lastHadChildren = parentNode.children.length > 0;
|
||||
|
||||
// figure out what's the visible child start index right before the
|
||||
// splice point
|
||||
@ -190,6 +297,11 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
deletedNodes.forEach(visit);
|
||||
}
|
||||
|
||||
const currentlyHasChildren = parentNode.children.length > 0;
|
||||
if (lastHadChildren !== currentlyHasChildren) {
|
||||
this.setCollapsible(location.slice(0, -1), currentlyHasChildren);
|
||||
}
|
||||
|
||||
this._onDidSplice.fire({ insertedNodes: nodesToInsert, deletedNodes });
|
||||
|
||||
let node: IIndexTreeNode<T, TFilterData> | undefined = parentNode;
|
||||
|
Reference in New Issue
Block a user