@@ -11,58 +11,48 @@ import { URI } from 'vs/base/common/uri';
1111import { mapValues } from 'vs/base/common/collections' ;
1212import { PathIterator } from 'vs/base/common/map' ;
1313
14- export interface ILeafNode < T , C = void > {
14+ export interface IResourceNode < T , C = void > {
1515 readonly uri : URI ;
1616 readonly relativePath : string ;
1717 readonly name : string ;
18- readonly element : T ;
18+ readonly element : T | undefined ;
19+ readonly children : Iterator < IResourceNode < T , C > > ;
20+ readonly childrenCount : number ;
21+ readonly parent : IResourceNode < T , C > | undefined ;
1922 readonly context : C ;
23+ get ( childName : string ) : IResourceNode < T , C > | undefined ;
2024}
2125
22- export interface IBranchNode < T , C = void > {
23- readonly uri : URI ;
24- readonly relativePath : string ;
25- readonly name : string ;
26- readonly size : number ;
27- readonly children : Iterator < INode < T , C > > ;
28- readonly parent : IBranchNode < T , C > | undefined ;
29- readonly context : C ;
30- get ( childName : string ) : INode < T , C > | undefined ;
31- }
32-
33- export type INode < T , C > = IBranchNode < T , C > | ILeafNode < T , C > ;
34-
35- // Internals
36-
37- class Node < C > {
38-
39- @memoize
40- get name ( ) : string { return paths . posix . basename ( this . relativePath ) ; }
41-
42- constructor ( readonly uri : URI , readonly relativePath : string , readonly context : C ) { }
43- }
44-
45- class BranchNode < T , C > extends Node < C > implements IBranchNode < T , C > {
26+ class Node < T , C > implements IResourceNode < T , C > {
4627
47- private _children = new Map < string , BranchNode < T , C > | LeafNode < T , C > > ( ) ;
28+ private _children = new Map < string , Node < T , C > > ( ) ;
4829
49- get size ( ) : number {
30+ get childrenCount ( ) : number {
5031 return this . _children . size ;
5132 }
5233
53- get children ( ) : Iterator < BranchNode < T , C > | LeafNode < T , C > > {
34+ get children ( ) : Iterator < Node < T , C > > {
5435 return Iterator . fromArray ( mapValues ( this . _children ) ) ;
5536 }
5637
57- constructor ( uri : URI , relativePath : string , context : C , readonly parent : IBranchNode < T , C > | undefined = undefined ) {
58- super ( uri , relativePath , context ) ;
38+ @memoize
39+ get name ( ) : string {
40+ return paths . posix . basename ( this . relativePath ) ;
5941 }
6042
61- get ( path : string ) : BranchNode < T , C > | LeafNode < T , C > | undefined {
43+ constructor (
44+ readonly uri : URI ,
45+ readonly relativePath : string ,
46+ readonly context : C ,
47+ public element : T | undefined = undefined ,
48+ readonly parent : IResourceNode < T , C > | undefined = undefined
49+ ) { }
50+
51+ get ( path : string ) : Node < T , C > | undefined {
6252 return this . _children . get ( path ) ;
6353 }
6454
65- set ( path : string , child : BranchNode < T , C > | LeafNode < T , C > ) : void {
55+ set ( path : string , child : Node < T , C > ) : void {
6656 this . _children . set ( path , child ) ;
6757 }
6858
@@ -75,45 +65,38 @@ class BranchNode<T, C> extends Node<C> implements IBranchNode<T, C> {
7565 }
7666}
7767
78- class LeafNode < T , C > extends Node < C > implements ILeafNode < T , C > {
79-
80- constructor ( uri : URI , path : string , context : C , readonly element : T ) {
81- super ( uri , path , context ) ;
82- }
83- }
84-
85- function collect < T , C > ( node : INode < T , C > , result : T [ ] ) : T [ ] {
86- if ( ResourceTree . isBranchNode ( node ) ) {
87- Iterator . forEach ( node . children , child => collect ( child , result ) ) ;
88- } else {
68+ function collect < T , C > ( node : IResourceNode < T , C > , result : T [ ] ) : T [ ] {
69+ if ( typeof node . element !== 'undefined' ) {
8970 result . push ( node . element ) ;
9071 }
9172
73+ Iterator . forEach ( node . children , child => collect ( child , result ) ) ;
74+
9275 return result ;
9376}
9477
9578export class ResourceTree < T extends NonNullable < any > , C > {
9679
97- readonly root : BranchNode < T , C > ;
98-
99- static isBranchNode < T , C > ( obj : any ) : obj is IBranchNode < T , C > {
100- return obj instanceof BranchNode ;
101- }
80+ readonly root : Node < T , C > ;
10281
103- static getRoot < T , C > ( node : IBranchNode < T , C > ) : IBranchNode < T , C > {
82+ static getRoot < T , C > ( node : IResourceNode < T , C > ) : IResourceNode < T , C > {
10483 while ( node . parent ) {
10584 node = node . parent ;
10685 }
10786
10887 return node ;
10988 }
11089
111- static collect < T , C > ( node : INode < T , C > ) : T [ ] {
90+ static collect < T , C > ( node : IResourceNode < T , C > ) : T [ ] {
11291 return collect ( node , [ ] ) ;
11392 }
11493
94+ static isResourceNode < T , C > ( obj : any ) : obj is IResourceNode < T , C > {
95+ return obj instanceof Node ;
96+ }
97+
11598 constructor ( context : C , rootURI : URI = URI . file ( '/' ) ) {
116- this . root = new BranchNode ( rootURI , '' , context ) ;
99+ this . root = new Node ( rootURI , '' , context ) ;
117100 }
118101
119102 add ( uri : URI , element : T ) : void {
@@ -129,26 +112,17 @@ export class ResourceTree<T extends NonNullable<any>, C> {
129112 let child = node . get ( name ) ;
130113
131114 if ( ! child ) {
132- if ( iterator . hasNext ( ) ) {
133- child = new BranchNode ( joinPath ( this . root . uri , path ) , path , this . root . context , node ) ;
134- node . set ( name , child ) ;
135- } else {
136- child = new LeafNode ( uri , path , this . root . context , element ) ;
137- node . set ( name , child ) ;
138- return ;
139- }
140- }
141-
142- if ( ! ( child instanceof BranchNode ) ) {
143- if ( iterator . hasNext ( ) ) {
144- throw new Error ( 'Inconsistent tree: can\'t override leaf with branch.' ) ;
145- }
146-
147- // replace
148- node . set ( name , new LeafNode ( uri , path , this . root . context , element ) ) ;
149- return ;
115+ child = new Node (
116+ joinPath ( this . root . uri , path ) ,
117+ path ,
118+ this . root . context ,
119+ iterator . hasNext ( ) ? undefined : element ,
120+ node
121+ ) ;
122+
123+ node . set ( name , child ) ;
150124 } else if ( ! iterator . hasNext ( ) ) {
151- throw new Error ( 'Inconsistent tree: can\'t override branch with leaf.' ) ;
125+ child . element = element ;
152126 }
153127
154128 node = child ;
@@ -167,33 +141,22 @@ export class ResourceTree<T extends NonNullable<any>, C> {
167141 return this . _delete ( this . root , iterator ) ;
168142 }
169143
170- private _delete ( node : BranchNode < T , C > , iterator : PathIterator ) : T | undefined {
144+ private _delete ( node : Node < T , C > , iterator : PathIterator ) : T | undefined {
171145 const name = iterator . value ( ) ;
172146 const child = node . get ( name ) ;
173147
174148 if ( ! child ) {
175149 return undefined ;
176150 }
177151
178- // not at end
179152 if ( iterator . hasNext ( ) ) {
180- if ( child instanceof BranchNode ) {
181- const result = this . _delete ( child , iterator . next ( ) ) ;
153+ const result = this . _delete ( child , iterator . next ( ) ) ;
182154
183- if ( typeof result !== 'undefined' && child . size === 0 ) {
184- node . delete ( name ) ;
185- }
186-
187- return result ;
188- } else {
189- throw new Error ( 'Inconsistent tree: Expected a branch, found a leaf instead.' ) ;
155+ if ( typeof result !== 'undefined' && child . childrenCount === 0 ) {
156+ node . delete ( name ) ;
190157 }
191- }
192158
193- //at end
194- if ( child instanceof BranchNode ) {
195- // TODO: maybe we can allow this
196- throw new Error ( 'Inconsistent tree: Expected a leaf, found a branch instead.' ) ;
159+ return result ;
197160 }
198161
199162 node . delete ( name ) ;
@@ -203,4 +166,22 @@ export class ResourceTree<T extends NonNullable<any>, C> {
203166 clear ( ) : void {
204167 this . root . clear ( ) ;
205168 }
169+
170+ getNode ( uri : URI ) : IResourceNode < T , C > | undefined {
171+ const key = relativePath ( this . root . uri , uri ) || uri . fsPath ;
172+ const iterator = new PathIterator ( false ) . reset ( key ) ;
173+ let node = this . root ;
174+
175+ while ( true ) {
176+ const name = iterator . value ( ) ;
177+ const child = node . get ( name ) ;
178+
179+ if ( ! child || ! iterator . hasNext ( ) ) {
180+ return child ;
181+ }
182+
183+ node = child ;
184+ iterator . next ( ) ;
185+ }
186+ }
206187}
0 commit comments