44 *--------------------------------------------------------------------------------------------*/
55
66import { URI } from 'vs/base/common/uri' ;
7+ import { memoize } from 'vs/base/common/decorators' ;
8+ import * as paths from 'vs/base/common/path' ;
9+ import { Iterator } from 'vs/base/common/iterator' ;
710
8- export const enum NodeType {
9- Branch ,
10- Leaf
11+ export interface ILeafNode < T > {
12+ readonly path : string ;
13+ readonly name : string ;
14+ readonly element : T ;
1115}
1216
13- export interface LeafNode < T > {
14- readonly type : NodeType . Leaf ;
15- readonly element : T ;
17+ export interface IBranchNode < T > {
18+ readonly path : string ;
19+ readonly name : string ;
20+ readonly size : number ;
21+ readonly children : Iterator < INode < T > > ;
22+ get ( childName : string ) : INode < T > | undefined ;
23+ }
24+
25+ export type INode < T > = IBranchNode < T > | ILeafNode < T > ;
26+
27+ export function isBranchNode < T > ( obj : any ) : obj is IBranchNode < T > {
28+ return obj instanceof BranchNode ;
1629}
1730
18- export interface BranchNode < T > {
19- readonly type : NodeType . Branch ;
20- readonly children : Map < string , Node < T > > ;
31+ // Internals
32+
33+ class Node {
34+
35+ @memoize
36+ get name ( ) : string { return paths . posix . basename ( this . path ) ; }
37+
38+ constructor ( readonly path : string ) { }
2139}
2240
23- export type Node < T > = BranchNode < T > | LeafNode < T > ;
41+ class BranchNode < T > extends Node implements IBranchNode < T > {
42+
43+ private _children = new Map < string , BranchNode < T > | LeafNode < T > > ( ) ;
44+
45+ get size ( ) : number {
46+ return this . _children . size ;
47+ }
48+
49+ get children ( ) : Iterator < BranchNode < T > | LeafNode < T > > {
50+ return Iterator . fromIterableIterator ( this . _children . values ( ) ) ;
51+ }
52+
53+ get ( path : string ) : BranchNode < T > | LeafNode < T > | undefined {
54+ return this . _children . get ( path ) ;
55+ }
56+
57+ set ( path : string , child : BranchNode < T > | LeafNode < T > ) : void {
58+ this . _children . set ( path , child ) ;
59+ }
60+
61+ delete ( path : string ) : void {
62+ this . _children . delete ( path ) ;
63+ }
64+ }
65+
66+ class LeafNode < T > extends Node implements ILeafNode < T > {
67+
68+ constructor ( path : string , readonly element : T ) {
69+ super ( path ) ;
70+ }
71+ }
2472
2573export class ResourceTree < T extends NonNullable < any > > {
2674
27- readonly root : BranchNode < T > = { type : NodeType . Branch , children : new Map ( ) } ;
75+ readonly root = new BranchNode < T > ( '' ) ;
2876
2977 constructor ( ) { }
3078
3179 add ( uri : URI , element : T ) : void {
3280 const parts = uri . fsPath . split ( / [ \\ \/ ] / ) . filter ( p => ! ! p ) ;
3381 let node = this . root ;
82+ let path = this . root . path ;
3483
3584 for ( let i = 0 ; i < parts . length ; i ++ ) {
3685 const name = parts [ i ] ;
37- let child = node . children . get ( name ) ;
86+ path = path + '/' + name ;
87+
88+ let child = node . get ( name ) ;
3889
3990 if ( ! child ) {
4091 if ( i < parts . length - 1 ) {
41- child = { type : NodeType . Branch , children : new Map ( ) } ;
42- node . children . set ( name , child ) ;
92+ child = new BranchNode ( path ) ;
93+ node . set ( name , child ) ;
4394 } else {
44- child = { type : NodeType . Leaf , element } ;
45- node . children . set ( name , child ) ;
95+ child = new LeafNode ( path , element ) ;
96+ node . set ( name , child ) ;
4697 return ;
4798 }
4899 }
49100
50- if ( child . type === NodeType . Leaf ) {
101+ if ( ! ( child instanceof BranchNode ) ) {
51102 if ( i < parts . length - 1 ) {
52103 throw new Error ( 'Inconsistent tree: can\'t override leaf with branch.' ) ;
53104 }
54105
55106 // replace
56- node . children . set ( name , { type : NodeType . Leaf , element } ) ;
107+ node . set ( name , new LeafNode ( path , element ) ) ;
57108 return ;
58109 } else if ( i === parts . length - 1 ) {
59110 throw new Error ( 'Inconsistent tree: can\'t override branch with leaf.' ) ;
@@ -70,34 +121,34 @@ export class ResourceTree<T extends NonNullable<any>> {
70121
71122 private _delete ( node : BranchNode < T > , parts : string [ ] , index : number ) : T | undefined {
72123 const name = parts [ index ] ;
73- const child = node . children . get ( name ) ;
124+ const child = node . get ( name ) ;
74125
75126 if ( ! child ) {
76127 return undefined ;
77128 }
78129
79130 // not at end
80131 if ( index < parts . length - 1 ) {
81- if ( child . type === NodeType . Leaf ) {
82- throw new Error ( 'Inconsistent tree: Expected a branch, found a leaf instead.' ) ;
83- } else {
132+ if ( child instanceof BranchNode ) {
84133 const result = this . _delete ( child , parts , index + 1 ) ;
85134
86- if ( typeof result !== 'undefined' && child . children . size === 0 ) {
87- node . children . delete ( name ) ;
135+ if ( typeof result !== 'undefined' && child . size === 0 ) {
136+ node . delete ( name ) ;
88137 }
89138
90139 return result ;
140+ } else {
141+ throw new Error ( 'Inconsistent tree: Expected a branch, found a leaf instead.' ) ;
91142 }
92143 }
93144
94145 //at end
95- if ( child . type === NodeType . Branch ) {
146+ if ( child instanceof BranchNode ) {
96147 // TODO: maybe we can allow this
97148 throw new Error ( 'Inconsistent tree: Expected a leaf, found a branch instead.' ) ;
98149 }
99150
100- node . children . delete ( name ) ;
151+ node . delete ( name ) ;
101152 return child . element ;
102153 }
103154}
0 commit comments