Skip to content

Commit e54e1e0

Browse files
committed
better typed Trie
1 parent e206d06 commit e54e1e0

2 files changed

Lines changed: 52 additions & 54 deletions

File tree

src/vs/base/browser/ui/list/treeModel.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import { ISpliceable } from 'vs/base/common/sequence';
99
import { IIterator } from 'vs/base/common/iterator';
1010

11-
export type Location = number[];
12-
1311
export interface ITreeElement<T> {
1412
readonly element: T;
1513
readonly children: ITreeElement<T>[];
@@ -119,7 +117,7 @@ export class TreeModel<T> {
119117

120118
constructor(private spliceable: ISpliceable<ITreeNode<T>>) { }
121119

122-
splice(start: Location, deleteCount: number, elements: ITreeElement<T>[] = []): IIterator<ITreeElement<T>> {
120+
splice(start: number[], deleteCount: number, elements: ITreeElement<T>[] = []): IIterator<ITreeElement<T>> {
123121
if (start.length === 0) {
124122
throw new Error('Invalid tree location');
125123
}
@@ -133,19 +131,19 @@ export class TreeModel<T> {
133131
return deletedIterator;
134132
}
135133

136-
getElement(location: Location): T | undefined {
134+
getElement(location: number[]): T | undefined {
137135
const node = this.findNode(location);
138136
return node && node.element;
139137
}
140138

141-
private findNode(location: Location): TreeNode<T> {
139+
private findNode(location: number[]): TreeNode<T> {
142140
const { parentNode } = this.findParentNode(location);
143141
const lastIndex = location[location.length - 1];
144142

145143
return parentNode.children[lastIndex];
146144
}
147145

148-
private findParentNode(location: Location, node: TreeNode<T> = this.root, listIndex: number = 0): { parentNode: TreeNode<T>; parentListIndex: number } {
146+
private findParentNode(location: number[], node: TreeNode<T> = this.root, listIndex: number = 0): { parentNode: TreeNode<T>; parentListIndex: number } {
149147
if (location.length === 1) {
150148
return { parentNode: node, parentListIndex: listIndex };
151149
}
@@ -167,29 +165,29 @@ export class TreeModel<T> {
167165
// { key: 1, children: {} }
168166
// { 1: { 2: {} } }
169167

170-
type TrieNodeMap<T> = { [key: string]: TrieNode<T> };
171-
type TrieNode<T> = { value: T | undefined, children: TrieNodeMap<T> };
168+
type TrieNode<K, T> = { value: T | undefined, children: Map<K, TrieNode<K, T>> };
172169

173-
export class Trie<T> {
170+
export class Trie<K, T> {
174171

175-
private root: TrieNode<T>;
172+
private root: TrieNode<K, T>;
176173

177174
constructor() {
178175
this.clear();
179176
}
180177

181-
set(path: string[], element: T): void {
178+
set(path: K[], element: T): void {
182179
if (path.length === 0) {
183180
throw new Error('Invalid path length');
184181
}
185182

186183
let node = this.root;
187184

188185
for (const key of path) {
189-
let child = node.children[key];
186+
let child = node.children.get(key);
190187

191188
if (!child) {
192-
child = node.children[key] = { value: undefined, children: Object.create(null) };
189+
child = { value: undefined, children: new Map<K, TrieNode<K, T>>() };
190+
node.children.set(key, child);
193191
}
194192

195193
node = child;
@@ -198,15 +196,15 @@ export class Trie<T> {
198196
node.value = element;
199197
}
200198

201-
get(path: string[]): T | undefined {
199+
get(path: K[]): T | undefined {
202200
if (path.length === 0) {
203201
throw new Error('Invalid path length');
204202
}
205203

206204
let node = this.root;
207205

208206
for (const key of path) {
209-
let child = node.children[key];
207+
let child = node.children.get(key);
210208

211209
if (!child) {
212210
return undefined;
@@ -218,16 +216,16 @@ export class Trie<T> {
218216
return node.value;
219217
}
220218

221-
delete(path: string[]): void {
219+
delete(path: K[]): void {
222220
if (path.length === 0) {
223221
throw new Error('Invalid path length');
224222
}
225223

226-
let nodePath: { key: string, node: TrieNode<T> }[] = [];
224+
let nodePath: { key: K, node: TrieNode<K, T> }[] = [];
227225
let node = this.root;
228226

229227
for (const key of path) {
230-
let child = node.children[key];
228+
let child = node.children.get(key);
231229

232230
if (!child) {
233231
return;
@@ -240,7 +238,7 @@ export class Trie<T> {
240238
for (let i = nodePath.length - 1; i >= 0; i--) {
241239
const { key, node } = nodePath[i];
242240

243-
delete node.children[key];
241+
node.children.delete(key);
244242

245243
if (Object.keys(node.children).length > 0) {
246244
return;
@@ -249,7 +247,7 @@ export class Trie<T> {
249247
}
250248

251249
clear(): void {
252-
this.root = { value: undefined, children: {} };
250+
this.root = { value: undefined, children: new Map<K, TrieNode<K, T>>() };
253251
}
254252
}
255253

@@ -261,18 +259,18 @@ export class CollapsibleTreeModel<T> {
261259
this.model = new TreeModel<T>(spliceable);
262260
}
263261

264-
splice(start: Location, deleteCount: number, elements: ITreeElement<T>[]): void {
262+
splice(start: number[], deleteCount: number, elements: ITreeElement<T>[]): void {
265263
this.model.splice(start, deleteCount, elements);
266264
}
267265

268-
expand(location: Location): boolean {
266+
expand(location: number[]): boolean {
269267

270268
// this.model.splice(start, deleteCount, elements);
271269
// const element = this.model.getElement()
272270
return false;
273271
}
274272

275-
collapse(location: Location): boolean {
273+
collapse(location: number[]): boolean {
276274
// const element = this.model.getElement(location);
277275
// const collapsedElement: ITreeElement<T> = { element, children: [] };
278276
// const deletedIterator = this.model.splice(location, 1, [collapsedElement]);

src/vs/base/test/browser/ui/list/treeModel.test.ts

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -149,58 +149,58 @@ suite('TreeModel2', () => {
149149
suite('Trie', function () {
150150

151151
test('simple test', () => {
152-
const trie = new Trie<string>();
153-
154-
trie.set(['0', '0', '0'], 'hello');
155-
assert.equal(trie.get(['0']), undefined);
156-
assert.equal(trie.get(['0', '0']), undefined);
157-
assert.equal(trie.get(['0', '0', '0']), 'hello');
158-
assert.equal(trie.get(['1', '0', '0']), undefined);
159-
assert.equal(trie.get(['0', '1', '0']), undefined);
160-
assert.equal(trie.get(['0', '0', '1']), undefined);
161-
assert.equal(trie.get(['0', '0', '0', '0']), undefined);
152+
const trie = new Trie<number, string>();
153+
154+
trie.set([0, 0, 0], 'hello');
155+
assert.equal(trie.get([0]), undefined);
156+
assert.equal(trie.get([0, 0]), undefined);
157+
assert.equal(trie.get([0, 0, 0]), 'hello');
158+
assert.equal(trie.get([1, 0, 0]), undefined);
159+
assert.equal(trie.get([0, 1, 0]), undefined);
160+
assert.equal(trie.get([0, 0, 1]), undefined);
161+
assert.equal(trie.get([0, 0, 0, 0]), undefined);
162162
});
163163

164164
test('clear', () => {
165-
const trie = new Trie<string>();
165+
const trie = new Trie<number, string>();
166166

167-
trie.set(['0', '0', '0'], 'hello');
168-
assert.equal(trie.get(['0', '0', '0']), 'hello');
167+
trie.set([0, 0, 0], 'hello');
168+
assert.equal(trie.get([0, 0, 0]), 'hello');
169169

170170
trie.clear();
171-
assert.equal(trie.get(['0', '0', '0']), undefined);
171+
assert.equal(trie.get([0, 0, 0]), undefined);
172172
});
173173

174174
test('delete', () => {
175-
const trie = new Trie<string>();
175+
const trie = new Trie<number, string>();
176176

177-
trie.set(['1', '2', '3'], 'hello');
178-
assert.equal(trie.get(['1', '2', '3']), 'hello');
177+
trie.set([1, 2, 3], 'hello');
178+
assert.equal(trie.get([1, 2, 3]), 'hello');
179179

180-
trie.delete(['1', '2', '3']);
181-
assert.equal(trie.get(['1', '2', '3']), undefined);
180+
trie.delete([1, 2, 3]);
181+
assert.equal(trie.get([1, 2, 3]), undefined);
182182
});
183183

184184
test('nested delete', () => {
185-
const trie = new Trie<string>();
185+
const trie = new Trie<number, string>();
186186

187-
trie.set(['1', '2', '3'], 'hello');
188-
assert.equal(trie.get(['1', '2', '3']), 'hello');
187+
trie.set([1, 2, 3], 'hello');
188+
assert.equal(trie.get([1, 2, 3]), 'hello');
189189

190-
trie.delete(['1']);
191-
assert.equal(trie.get(['1', '2', '3']), undefined);
190+
trie.delete([1]);
191+
assert.equal(trie.get([1, 2, 3]), undefined);
192192
});
193193

194194
test('map tests', () => {
195-
const trie = new Trie<string>();
195+
const trie = new Trie<number, string>();
196196

197-
trie.set(['0', '0', '0'], 'hello');
198-
assert.equal(trie.get(['0', '0', '0']), 'hello');
197+
trie.set([0, 0, 0], 'hello');
198+
assert.equal(trie.get([0, 0, 0]), 'hello');
199199

200-
trie.set(['0', '0'], 'world');
201-
assert.equal(trie.get(['0', '0']), 'world');
200+
trie.set([0, 0], 'world');
201+
assert.equal(trie.get([0, 0]), 'world');
202202

203-
trie.set(['0', '0', '1'], 'cool');
204-
assert.equal(trie.get(['0', '0', '1']), 'cool');
203+
trie.set([0, 0, 1], 'cool');
204+
assert.equal(trie.get([0, 0, 1]), 'cool');
205205
});
206206
});

0 commit comments

Comments
 (0)