@@ -186,42 +186,50 @@ async function generateFlowDiagramFromCallHierarchy(
186
186
item : vscode . CallHierarchyItem ,
187
187
incomingCalls : vscode . CallHierarchyIncomingCall [ ] | undefined
188
188
) : Promise < { nodes : any [ ] , edges : any [ ] } > {
189
- let nodes = [ {
190
- id : 0 ,
189
+ let newNodes = new Map ( ) ;
190
+ let newEdges : any [ ] = [ ] ;
191
+
192
+ // Add root node
193
+ const rootKey = `${ item . uri . fsPath } ::${ item . name } ` ;
194
+ newNodes . set ( rootKey , {
195
+ id : 1 ,
191
196
label : item . name ,
192
197
color : getRandomPastelColor ( ) ,
193
198
file : item . uri . fsPath ,
194
199
line : item . range . start . line ,
195
200
character : item . selectionRange . start . character
196
- } ] ;
197
-
198
- let edges : { from : number , to : number , count : number } [ ] = [ ] ;
201
+ } ) ;
199
202
200
203
if ( incomingCalls ) {
201
- let callCounts = new Map < string , number > ( ) ;
202
- for ( let call of incomingCalls ) {
203
- const key = `${ call . from . name } -${ item . name } ` ;
204
- callCounts . set ( key , ( callCounts . get ( key ) || 0 ) + call . fromRanges . length ) ;
205
- }
204
+ incomingCalls . forEach ( ( call , index ) => {
205
+ const callerKey = `${ call . from . uri . fsPath } ::${ call . from . name } ` ;
206
+
207
+ // Only add the node if it's not already in our map
208
+ if ( ! newNodes . has ( callerKey ) ) {
209
+ newNodes . set ( callerKey , {
210
+ id : newNodes . size + 1 , // ID based on map size
211
+ label : call . from . name ,
212
+ color : getRandomPastelColor ( ) ,
213
+ file : call . from . uri . fsPath ,
214
+ line : call . from . range . start . line ,
215
+ character : call . from . selectionRange . start . character
216
+ } ) ;
217
+ }
206
218
207
- let i = 1 ;
208
- for ( let [ key , count ] of callCounts ) {
209
- const [ fromName ] = key . split ( '-' ) ;
210
- const caller = incomingCalls . find ( call => call . from . name === fromName ) ! ;
211
- nodes . push ( {
212
- id : i ,
213
- label : fromName ,
214
- color : getRandomPastelColor ( ) ,
215
- file : caller . from . uri . fsPath ,
216
- line : caller . from . range . start . line ,
217
- character : caller . from . selectionRange . start . character
219
+ // Add edge using the node's actual ID
220
+ const callerId = newNodes . get ( callerKey ) . id ;
221
+ newEdges . push ( {
222
+ from : callerId ,
223
+ to : 1 , // Root node's ID is always 1
224
+ count : call . fromRanges . length
218
225
} ) ;
219
- edges . push ( { from : i , to : 0 , count : count } ) ;
220
- i ++ ;
221
- }
226
+ } ) ;
222
227
}
223
228
224
- return { nodes, edges} ;
229
+ return {
230
+ nodes : Array . from ( newNodes . values ( ) ) ,
231
+ edges : newEdges
232
+ } ;
225
233
}
226
234
227
235
async function goToDefinition ( nodeId : number ) {
@@ -560,24 +568,52 @@ function getWebviewContent(data: {nodes: any[], edges: any[]}) {
560
568
}
561
569
562
570
function mergeFlowData ( newData : { nodes : any [ ] , edges : any [ ] } ) {
563
- for ( const newNode of newData . nodes ) {
564
- const existingNode = globalData . nodes . find ( n => n . label === newNode . label && n . file === newNode . file ) ;
565
- if ( ! existingNode ) {
571
+ // Create a map of existing nodes by file+label combination
572
+ const existingNodesMap = new Map (
573
+ globalData . nodes . map ( node => [ `${ node . file } -${ node . label } ` , node ] )
574
+ ) ;
575
+
576
+ // Process new nodes
577
+ newData . nodes . forEach ( newNode => {
578
+ const key = `${ newNode . file } -${ newNode . label } ` ;
579
+ if ( ! existingNodesMap . has ( key ) ) {
580
+ // If node doesn't exist, add it with a new ID
566
581
newNode . id = nextNodeId ++ ;
567
582
globalData . nodes . push ( newNode ) ;
583
+ existingNodesMap . set ( key , newNode ) ;
568
584
}
569
- }
585
+ } ) ;
570
586
571
- for ( const newEdge of newData . edges ) {
572
- const fromNode = globalData . nodes . find ( n => n . label === newData . nodes [ newEdge . from ] . label && n . file === newData . nodes [ newEdge . from ] . file ) ;
573
- const toNode = globalData . nodes . find ( n => n . label === newData . nodes [ newEdge . to ] . label && n . file === newData . nodes [ newEdge . to ] . file ) ;
587
+ // Process new edges
588
+ newData . edges . forEach ( newEdge => {
589
+ // Find the actual node IDs from our existing nodes
590
+ const fromNode = newData . nodes [ newEdge . from - 1 ] ;
591
+ const toNode = newData . nodes [ newEdge . to - 1 ] ;
592
+
574
593
if ( fromNode && toNode ) {
575
- const existingEdge = globalData . edges . find ( e => e . from === fromNode . id && e . to === toNode . id ) ;
576
- if ( ! existingEdge ) {
577
- globalData . edges . push ( { from : fromNode . id , to : toNode . id } ) ;
594
+ const fromKey = `${ fromNode . file } -${ fromNode . label } ` ;
595
+ const toKey = `${ toNode . file } -${ toNode . label } ` ;
596
+
597
+ const actualFromNode = existingNodesMap . get ( fromKey ) ;
598
+ const actualToNode = existingNodesMap . get ( toKey ) ;
599
+
600
+ if ( actualFromNode && actualToNode ) {
601
+ // Check if edge already exists
602
+ const edgeExists = globalData . edges . some ( e =>
603
+ e . from === actualFromNode . id &&
604
+ e . to === actualToNode . id
605
+ ) ;
606
+
607
+ if ( ! edgeExists ) {
608
+ globalData . edges . push ( {
609
+ from : actualFromNode . id ,
610
+ to : actualToNode . id ,
611
+ count : newEdge . count
612
+ } ) ;
613
+ }
578
614
}
579
615
}
580
- }
616
+ } ) ;
581
617
}
582
618
583
619
export function deactivate ( ) { }
0 commit comments