@@ -18,7 +18,12 @@ enum ItemType {
1818 Node = `node` ,
1919}
2020
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 ;
2227
2328export class MRTreeDataProvider implements vscode . TreeDataProvider < ListItem < ITreeNode > > {
2429 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
100105 return ( element as MRItem ) . getChildren ( diffStat ) ;
101106 } ) ;
102107 } else if ( element . contextValue === ItemType . Node ) {
103- ( element as FileNode ) . makeTree ( ) ;
104108 return ( element as FileNode ) . getChildren ( ) ;
105109 }
106110
@@ -145,22 +149,65 @@ export class MRItem extends ListItem<string | number> {
145149 } ;
146150
147151 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 ) ;
155153
156154 return [
157155 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 ) ) ,
159157 ] ;
160158 }
161- }
162159
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+ }
164211
165212export class FileNode extends ListItem < IFileNode > {
166213 contextValue = ItemType . Node ;
@@ -177,11 +224,13 @@ export class FileNode extends ListItem<IFileNode> {
177224
178225 public makeTree ( ) {
179226 if ( this . collapsibleState === vscode . TreeItemCollapsibleState . None ) {
180- return [ ] ;
227+ return ;
181228 }
229+ this . children = ( this . value . children || [ ] ) ?. map ( f => new FileNode ( f . name , f , ( f . children || [ ] ) ?. length > 0 ? vscode . TreeItemCollapsibleState . Expanded : vscode . TreeItemCollapsibleState . None ) ) ;
182230 }
183231
184232 async getChildren ( ) {
233+ this . makeTree ( ) ;
185234 return this . children ;
186235 }
187236
0 commit comments