Skip to content

Commit 967d43e

Browse files
committed
tree.getElementPath
1 parent e54e1e0 commit 967d43e

2 files changed

Lines changed: 41 additions & 25 deletions

File tree

src/vs/base/common/arrays.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export function tail2<T>(arr: T[]): [T[], T] {
2424
return [arr.slice(0, arr.length - 1), arr[arr.length - 1]];
2525
}
2626

27+
export function last<T>(arr: T[]): T {
28+
return arr[arr.length - 1];
29+
}
30+
2731
export function equals<T>(one: ReadonlyArray<T>, other: ReadonlyArray<T>, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
2832
if (one.length !== other.length) {
2933
return false;

src/vs/base/common/tree.ts

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,53 +5,65 @@
55

66
'use strict';
77

8-
import { clamp } from './numbers';
8+
import { tail2, last } from 'vs/base/common/arrays';
99

1010
export interface ITreeNode<T> {
1111
readonly element: T;
1212
readonly children: ITreeNode<T>[];
1313
}
1414

15-
function clone<T>(nodes: ITreeNode<T>[]): ITreeNode<T>[] {
16-
return nodes.map(({ element, children }) => ({ element, children: clone(children) }));
17-
}
18-
1915
export class Tree<T> {
2016

21-
private root: ITreeNode<T>[] = [];
17+
private root: ITreeNode<T> = { element: undefined, children: [] };
2218

2319
splice(start: number[], deleteCount: number, nodes: ITreeNode<T>[] = []): ITreeNode<T>[] {
2420
if (start.length === 0) {
25-
throw new Error('invalid tree location');
21+
throw new Error('Invalid tree location');
2622
}
2723

28-
const children = this.findChildren(start);
29-
const index = start[start.length - 1];
30-
return children.splice(index, deleteCount, ...clone(nodes));
24+
const [rest, index] = tail2(start);
25+
const parentPath = this.getNodePath(rest);
26+
const parent = last(parentPath);
27+
28+
return parent.children.splice(index, deleteCount, ...nodes);
3129
}
3230

33-
getElement(location: number[]): T | undefined {
34-
const node = this.findElement(location);
35-
return node && node.element;
31+
getElement(location: number[]): T {
32+
if (location.length === 0) {
33+
throw new Error('Invalid tree location');
34+
}
35+
36+
const nodePath = this.getNodePath(location);
37+
const node = last(nodePath);
38+
39+
return node.element;
3640
}
3741

38-
getNodes(): ITreeNode<T>[] {
39-
return clone(this.root);
42+
getElementPath(location: number[]): T[] {
43+
if (location.length === 0) {
44+
throw new Error('Invalid tree location');
45+
}
46+
47+
const nodePath = this.getNodePath(location);
48+
return nodePath.map(node => node.element);
4049
}
4150

42-
private findElement(location: number[]): ITreeNode<T> {
43-
const children = this.findChildren(location);
44-
const lastIndex = clamp(location[location.length - 1], 0, children.length);
45-
return children[lastIndex];
51+
getNodes(): ITreeNode<T>[] {
52+
return this.root.children;
4653
}
4754

48-
private findChildren(location: number[], children: ITreeNode<T>[] = this.root): ITreeNode<T>[] {
49-
if (location.length === 1) {
50-
return children;
55+
private getNodePath(location: number[], node: ITreeNode<T> = this.root): ITreeNode<T>[] {
56+
if (location.length === 0) {
57+
return [node];
58+
}
59+
60+
let [index, ...rest] = location;
61+
62+
if (index < 0 || index >= node.children.length) {
63+
throw new Error('Invalid location');
5164
}
5265

53-
let [i, ...rest] = location;
54-
i = clamp(i, 0, children.length);
55-
return this.findChildren(rest, children[i].children);
66+
const child = node.children[index];
67+
return [node, ...this.getNodePath(rest, child)];
5668
}
5769
}

0 commit comments

Comments
 (0)