55 */
66
77import CodeGraph , { findNearestCodeGraphRoot } from '../index' ;
8- import type { Node , SearchResult , Subgraph , TaskContext , NodeKind } from '../types' ;
8+ import type { Node , Edge , SearchResult , Subgraph , TaskContext , NodeKind } from '../types' ;
99import { createHash } from 'crypto' ;
1010import { writeFileSync } from 'fs' ;
1111import { clamp } from '../utils' ;
@@ -475,19 +475,28 @@ export class ToolHandler {
475475 const cg = this . getCodeGraph ( args . projectPath as string | undefined ) ;
476476 const limit = clamp ( ( args . limit as number ) || 20 , 1 , 100 ) ;
477477
478- const match = this . findSymbol ( cg , symbol ) ;
479- if ( ! match ) {
478+ const allMatches = this . findAllSymbols ( cg , symbol ) ;
479+ if ( allMatches . nodes . length === 0 ) {
480480 return this . textResult ( `Symbol "${ symbol } " not found in the codebase` ) ;
481481 }
482482
483- const callers = cg . getCallers ( match . node . id ) ;
483+ // Aggregate callers across all matching symbols
484+ const seen = new Set < string > ( ) ;
485+ const allCallers : Node [ ] = [ ] ;
486+ for ( const node of allMatches . nodes ) {
487+ for ( const c of cg . getCallers ( node . id ) ) {
488+ if ( ! seen . has ( c . node . id ) ) {
489+ seen . add ( c . node . id ) ;
490+ allCallers . push ( c . node ) ;
491+ }
492+ }
493+ }
484494
485- if ( callers . length === 0 ) {
486- return this . textResult ( `No callers found for "${ symbol } "${ match . note } ` ) ;
495+ if ( allCallers . length === 0 ) {
496+ return this . textResult ( `No callers found for "${ symbol } "${ allMatches . note } ` ) ;
487497 }
488498
489- const callerNodes = callers . slice ( 0 , limit ) . map ( c => c . node ) ;
490- const formatted = this . formatNodeList ( callerNodes , `Callers of ${ symbol } ` ) + match . note ;
499+ const formatted = this . formatNodeList ( allCallers . slice ( 0 , limit ) , `Callers of ${ symbol } ` ) + allMatches . note ;
491500 return this . textResult ( this . truncateOutput ( formatted ) ) ;
492501 }
493502
@@ -501,19 +510,28 @@ export class ToolHandler {
501510 const cg = this . getCodeGraph ( args . projectPath as string | undefined ) ;
502511 const limit = clamp ( ( args . limit as number ) || 20 , 1 , 100 ) ;
503512
504- const match = this . findSymbol ( cg , symbol ) ;
505- if ( ! match ) {
513+ const allMatches = this . findAllSymbols ( cg , symbol ) ;
514+ if ( allMatches . nodes . length === 0 ) {
506515 return this . textResult ( `Symbol "${ symbol } " not found in the codebase` ) ;
507516 }
508517
509- const callees = cg . getCallees ( match . node . id ) ;
518+ // Aggregate callees across all matching symbols
519+ const seen = new Set < string > ( ) ;
520+ const allCallees : Node [ ] = [ ] ;
521+ for ( const node of allMatches . nodes ) {
522+ for ( const c of cg . getCallees ( node . id ) ) {
523+ if ( ! seen . has ( c . node . id ) ) {
524+ seen . add ( c . node . id ) ;
525+ allCallees . push ( c . node ) ;
526+ }
527+ }
528+ }
510529
511- if ( callees . length === 0 ) {
512- return this . textResult ( `No callees found for "${ symbol } "${ match . note } ` ) ;
530+ if ( allCallees . length === 0 ) {
531+ return this . textResult ( `No callees found for "${ symbol } "${ allMatches . note } ` ) ;
513532 }
514533
515- const calleeNodes = callees . slice ( 0 , limit ) . map ( c => c . node ) ;
516- const formatted = this . formatNodeList ( calleeNodes , `Callees of ${ symbol } ` ) + match . note ;
534+ const formatted = this . formatNodeList ( allCallees . slice ( 0 , limit ) , `Callees of ${ symbol } ` ) + allMatches . note ;
517535 return this . textResult ( this . truncateOutput ( formatted ) ) ;
518536 }
519537
@@ -527,14 +545,37 @@ export class ToolHandler {
527545 const cg = this . getCodeGraph ( args . projectPath as string | undefined ) ;
528546 const depth = clamp ( ( args . depth as number ) || 2 , 1 , 10 ) ;
529547
530- const match = this . findSymbol ( cg , symbol ) ;
531- if ( ! match ) {
548+ const allMatches = this . findAllSymbols ( cg , symbol ) ;
549+ if ( allMatches . nodes . length === 0 ) {
532550 return this . textResult ( `Symbol "${ symbol } " not found in the codebase` ) ;
533551 }
534552
535- const impact = cg . getImpactRadius ( match . node . id , depth ) ;
553+ // Aggregate impact across all matching symbols
554+ const mergedNodes = new Map < string , Node > ( ) ;
555+ const mergedEdges : Edge [ ] = [ ] ;
556+ const seenEdges = new Set < string > ( ) ;
536557
537- const formatted = this . formatImpact ( symbol , impact ) + match . note ;
558+ for ( const node of allMatches . nodes ) {
559+ const impact = cg . getImpactRadius ( node . id , depth ) ;
560+ for ( const [ id , n ] of impact . nodes ) {
561+ mergedNodes . set ( id , n ) ;
562+ }
563+ for ( const e of impact . edges ) {
564+ const key = `${ e . source } ->${ e . target } :${ e . kind } ` ;
565+ if ( ! seenEdges . has ( key ) ) {
566+ seenEdges . add ( key ) ;
567+ mergedEdges . push ( e ) ;
568+ }
569+ }
570+ }
571+
572+ const mergedImpact = {
573+ nodes : mergedNodes ,
574+ edges : mergedEdges ,
575+ roots : allMatches . nodes . map ( n => n . id ) ,
576+ } ;
577+
578+ const formatted = this . formatImpact ( symbol , mergedImpact ) + allMatches . note ;
538579 return this . textResult ( this . truncateOutput ( formatted ) ) ;
539580 }
540581
@@ -822,6 +863,31 @@ export class ToolHandler {
822863 return { node : results [ 0 ] ! . node , note : '' } ;
823864 }
824865
866+ /**
867+ * Find ALL symbols matching a name. Used by callers/callees/impact to aggregate
868+ * results across all matching symbols (e.g., multiple classes with an `execute` method).
869+ */
870+ private findAllSymbols ( cg : CodeGraph , symbol : string ) : { nodes : Node [ ] ; note : string } {
871+ const results = cg . searchNodes ( symbol , { limit : 50 } ) ;
872+
873+ if ( results . length === 0 ) {
874+ return { nodes : [ ] , note : '' } ;
875+ }
876+
877+ const exactMatches = results . filter ( r => r . node . name === symbol ) ;
878+
879+ if ( exactMatches . length <= 1 ) {
880+ const node = exactMatches [ 0 ] ?. node ?? results [ 0 ] ! . node ;
881+ return { nodes : [ node ] , note : '' } ;
882+ }
883+
884+ const locations = exactMatches . map ( r =>
885+ `${ r . node . kind } at ${ r . node . filePath } :${ r . node . startLine } `
886+ ) ;
887+ const note = `\n\n> **Note:** Aggregated results across ${ exactMatches . length } symbols named "${ symbol } ": ${ locations . join ( ', ' ) } ` ;
888+ return { nodes : exactMatches . map ( r => r . node ) , note } ;
889+ }
890+
825891 /**
826892 * Truncate output if it exceeds the maximum length
827893 */
0 commit comments