@@ -18,7 +18,12 @@ enum ItemType {
18
18
Node = `node` ,
19
19
}
20
20
21
- type ITreeNode = string | number | IMRDiffStat | IMRPathItem ;
21
+ interface IFileNode extends IMRPathItem {
22
+ parentPath ?: string ;
23
+ children ?: IFileNode [ ]
24
+ }
25
+
26
+ type ITreeNode = string | number | IMRDiffStat | IFileNode ;
22
27
23
28
export class MRTreeDataProvider implements vscode . TreeDataProvider < ListItem < ITreeNode > > {
24
29
private _onDidChangeTreeData : vscode . EventEmitter < ListItem < ITreeNode > | undefined | void > = new vscode . EventEmitter < ListItem < ITreeNode > | undefined | void > ( ) ;
@@ -100,7 +105,6 @@ export class MRTreeDataProvider implements vscode.TreeDataProvider<ListItem<ITre
100
105
return ( element as MRItem ) . getChildren ( diffStat ) ;
101
106
} ) ;
102
107
} else if ( element . contextValue === ItemType . Node ) {
103
- ( element as FileNode ) . makeTree ( ) ;
104
108
return ( element as FileNode ) . getChildren ( ) ;
105
109
}
106
110
@@ -145,22 +149,65 @@ export class MRItem extends ListItem<string | number> {
145
149
} ;
146
150
147
151
async getChildren ( diffStat : IMRDiffStat ) : Promise < ListItem < string | number | IFileNode > [ ] > {
148
- const files = diffStat . paths . map ( p => {
149
- const pathArr = p . path . split ( `/` ) ;
150
- const name = pathArr [ 0 ] ;
151
- const childPath = pathArr . slice ( 1 ) ;
152
- const expandStatus = childPath . length > 0 ? vscode . TreeItemCollapsibleState . Expanded : vscode . TreeItemCollapsibleState . None ;
153
- return new FileNode ( name , { ...p , name, childPath } , expandStatus ) ;
154
- } ) ;
152
+ const files = this . _transformTree ( diffStat . paths ) ;
155
153
156
154
return [
157
155
new ListItem ( `Description` , `mr-desc` , vscode . TreeItemCollapsibleState . None ) ,
158
- ...files ,
156
+ ...files . map ( f => new FileNode ( f . name , f , ( f . children || [ ] ) ?. length > 0 ? vscode . TreeItemCollapsibleState . Expanded : vscode . TreeItemCollapsibleState . None ) ) ,
159
157
] ;
160
158
}
161
- }
162
159
163
- type IFileNode = IMRPathItem ;
160
+ private _transformTree ( paths : IMRPathItem [ ] ) {
161
+ let nodes : IFileNode [ ] = [ ] ;
162
+ paths . forEach ( p => {
163
+ nodes = this . _makeTree ( p , nodes ) ;
164
+ } ) ;
165
+
166
+ return nodes ;
167
+ }
168
+
169
+ private _makeTree ( node : IFileNode , nodes : IFileNode [ ] = [ ] ) {
170
+ const rawArr = node . path . split ( `/` ) ;
171
+
172
+ rawArr . forEach ( ( i , idx ) => {
173
+ const curPath = rawArr . slice ( 0 , idx + 1 ) . join ( `/` ) ;
174
+ const parentPath = rawArr . slice ( 0 , idx ) . join ( `/` ) ;
175
+ const f = { ...node , name : i , path : curPath , parentPath, children : [ ] } ;
176
+ nodes = this . _insert ( f , nodes ) ;
177
+ } ) ;
178
+
179
+ return nodes ;
180
+ }
181
+
182
+ private _insert ( node : IFileNode , nodes : IFileNode [ ] ) {
183
+ const hasSameRootNode = nodes . find ( i => i . path === node . path ) ;
184
+
185
+ for ( const i of nodes ) {
186
+ if ( i . parentPath === node . parentPath ) {
187
+ if ( hasSameRootNode ) {
188
+ break ;
189
+ }
190
+
191
+ nodes = nodes . concat ( node ) ;
192
+ } else if ( node . path === `${ i . path } /${ node . name } ` ) {
193
+ const existed = i . children ?. find ( i => i . path === node . path ) ;
194
+ if ( existed ) {
195
+ break ;
196
+ }
197
+
198
+ i . children = ( i . children || [ ] ) . concat ( node ) ;
199
+ } else {
200
+ i . children = this . _insert ( node , i . children || [ ] ) ;
201
+ }
202
+ }
203
+
204
+ if ( ! nodes . length && ! node . parentPath ) {
205
+ nodes = nodes . concat ( node ) ;
206
+ }
207
+
208
+ return nodes ;
209
+ }
210
+ }
164
211
165
212
export class FileNode extends ListItem < IFileNode > {
166
213
contextValue = ItemType . Node ;
@@ -177,11 +224,13 @@ export class FileNode extends ListItem<IFileNode> {
177
224
178
225
public makeTree ( ) {
179
226
if ( this . collapsibleState === vscode . TreeItemCollapsibleState . None ) {
180
- return [ ] ;
227
+ return ;
181
228
}
229
+ this . children = ( this . value . children || [ ] ) ?. map ( f => new FileNode ( f . name , f , ( f . children || [ ] ) ?. length > 0 ? vscode . TreeItemCollapsibleState . Expanded : vscode . TreeItemCollapsibleState . None ) ) ;
182
230
}
183
231
184
232
async getChildren ( ) {
233
+ this . makeTree ( ) ;
185
234
return this . children ;
186
235
}
187
236
0 commit comments