@@ -41,27 +41,28 @@ function buildEdge(
4141 return ;
4242}
4343
44- function getRealCaller (
44+ function getRealIsCalled (
4545 globalOrderedRange : [ string , [ number , number ] ] , currDocSymbolInfo : DocSymbolInfo ,
4646) : [ string , vscode . Range , SymbolInfo ] | undefined {
4747
48- const [ currCallerName , currCallerRange ] = globalOrderedRange ;
49- const [ realCaller , shadow ] = currDocSymbolInfo . getSymbolWithShadowByRange ( currCallerName , currCallerRange , undefined ) ;
50- if ( realCaller === undefined ) {
48+ const [ isCalledName , isCalledRange ] = globalOrderedRange ;
49+ const [ realIsCalled , shadow ] = currDocSymbolInfo . getSymbolWithShadowByRange ( isCalledName , isCalledRange , undefined ) ;
50+ if ( realIsCalled === undefined ) {
5151 return undefined ;
5252 }
53- if ( shadow !== undefined && shadow . length !== 0 && isShadowed ( currCallerRange , shadow ) ) {
53+ if ( shadow !== undefined && shadow . length !== 0 && isShadowed ( isCalledRange , shadow ) ) {
5454 return undefined ;
5555 }
56- if ( isRangeIntExcludedRanges ( currCallerRange , currDocSymbolInfo . docRes . commentAndStringRange ) ) {
56+ if ( isRangeIntExcludedRanges ( isCalledRange , currDocSymbolInfo . docRes . commentAndStringRange ) ) {
5757 return undefined ;
5858 }
5959
6060 const callAppearRange = new vscode . Range (
61- currDocSymbolInfo . document . positionAt ( currCallerRange [ 0 ] ) ,
62- currDocSymbolInfo . document . positionAt ( currCallerRange [ 1 ] ) ,
61+ currDocSymbolInfo . document . positionAt ( isCalledRange [ 0 ] ) ,
62+ currDocSymbolInfo . document . positionAt ( isCalledRange [ 1 ] ) ,
6363 ) ;
64- return [ currCallerName , callAppearRange , realCaller ] ;
64+
65+ return [ isCalledName , callAppearRange , realIsCalled ] ;
6566}
6667
6768function genAllCallHierarchyItems (
@@ -73,44 +74,28 @@ function genAllCallHierarchyItems(
7374 const callHierarchyICs = callHrchyInfo . incomingCall ;
7475 const callHierarchyOGs = callHrchyInfo . outgoingCall ;
7576
76- // fileItem
77+ // make the file as definition, that is,
78+ // make the file as caller
7779 const fileName = currDocSymbolInfo . document . uri . path . split ( '/' ) . pop ( ) ;
78- const isCalledName = ( fileName !== undefined ) ? fileName : 'Untitled' ;
79- if ( ! callHierarchyOGs . has ( isCalledName ) ) {
80- callHierarchyOGs . set ( isCalledName , new Map < string , vscode . CallHierarchyOutgoingCall > ( ) ) ;
80+ const callerName = ( fileName !== undefined ) ? fileName : 'Untitled' ;
81+ if ( ! callHierarchyOGs . has ( callerName ) ) {
82+ callHierarchyOGs . set ( callerName , new Map < string , vscode . CallHierarchyOutgoingCall > ( ) ) ;
8183 }
8284
85+ // find isCalled ranges who is NOT visited. (orphans)
8386 for ( let i = 0 ; i < globalOrderedRanges . length ; ++ i ) {
8487 if ( visited . has ( i ) ) {
8588 continue ;
8689 }
8790
88- const realCallerRes = getRealCaller ( globalOrderedRanges [ i ] , currDocSymbolInfo ) ;
89- if ( realCallerRes === undefined ) {
90- continue ;
91- }
92- const [ currCallerName , callAppearRange , realCaller ] = realCallerRes ;
93- const realCallerStr = realCaller . stringify ( ) ;
94- if ( callHrchyItems . get ( currCallerName ) === undefined ) {
95- callHrchyItems . set ( currCallerName , new Map ( [ [ realCallerStr , buildCallHierarchyItem ( realCaller ) ] ] ) ) ;
96- }
97- const toItem = callHrchyItems . get ( currCallerName ) ?. get ( realCallerStr ) ;
98-
99- // make the range circle back
100- const fromItem = new vscode . CallHierarchyItem (
101- vscode . SymbolKind . Namespace , isCalledName , currDocSymbolInfo . document . uri . path , currDocSymbolInfo . document . uri ,
102- realCaller . loc . range , realCaller . loc . range
91+ const isCalledRange = globalOrderedRanges [ i ] ;
92+ // only build IncomingCall Edge since the file cannot be called,
93+ // that is, cannot be `toItems`
94+ buildEdgeForIsCalledRange (
95+ isCalledRange ,
96+ currDocSymbolInfo , callHrchyItems , callHierarchyICs , callHierarchyOGs ,
97+ callerName , undefined , undefined
10398 ) ;
104-
105- if ( ! callHierarchyICs . has ( currCallerName ) ) {
106- callHierarchyICs . set ( currCallerName , new Map < string , vscode . CallHierarchyIncomingCall > ( ) ) ;
107- }
108-
109- buildEdge (
110- callHierarchyICs . get ( currCallerName ) ! , realCallerStr , fromItem ,
111- callHierarchyOGs . get ( isCalledName ) ! , undefined , toItem , [ callAppearRange ]
112- ) ;
113-
11499 }
115100 return callHrchyInfo ;
116101}
@@ -119,6 +104,7 @@ function genAllCallHierarchyItems(
119104function genAllCallHierarchyItemsNonOrphan (
120105 currDocSymbolInfo : DocSymbolInfo , globalOrderedRanges : [ string , [ number , number ] ] [ ]
121106) : [ CallHrchyInfo , Set < number > ] {
107+ // init
122108 const visited : Set < number > = new Set ( ) ;
123109
124110 const callHrchyItems : Map < string , Map < string , vscode . CallHierarchyItem > > =
@@ -134,69 +120,108 @@ function genAllCallHierarchyItemsNonOrphan(
134120 return a . numRange [ 0 ] - b . numRange [ 0 ] ;
135121 } ) ;
136122
123+ // iterate all globalDef as caller
124+ // for example a() {b, c}, `a` as the caller
137125 for ( const info of infos ) {
138- const isCalledName = info . name ;
139- const infoStr = info . stringify ( ) ;
140- if ( callHrchyItems . get ( isCalledName ) === undefined ) {
141- callHrchyItems . set ( isCalledName , new Map ( [ [ infoStr , buildCallHierarchyItem ( info ) ] ] ) ) ;
126+ const callerName = info . name ;
127+ const callerSymbolStr = info . stringify ( ) ;
128+
129+ if ( callHrchyItems . get ( callerName ) === undefined ) {
130+ callHrchyItems . set ( callerName , new Map ( [ [ callerSymbolStr , buildCallHierarchyItem ( info ) ] ] ) ) ;
142131 }
143- const fromItem = callHrchyItems . get ( isCalledName ) ?. get ( infoStr ) ;
132+ const fromItem = callHrchyItems . get ( callerName ) ?. get ( callerSymbolStr ) ;
144133 if ( fromItem === undefined ) {
145134 continue ;
146135 }
147136
148- // caller's range
149- const callerRange = info . globalDefRange ;
150- if ( callerRange === undefined ) {
137+ // isCalled is in this range
138+ // for example a() {b, c}, `b` and `c` are in the range
139+ const isCalledRange = info . globalDefRange ;
140+ if ( isCalledRange === undefined ) {
151141 continue ;
152142 }
153143
154- if ( ! callHierarchyOGs . has ( isCalledName ) ) {
155- callHierarchyOGs . set ( isCalledName , new Map < string , vscode . CallHierarchyOutgoingCall > ( ) ) ;
144+ if ( ! callHierarchyOGs . has ( callerName ) ) {
145+ callHierarchyOGs . set ( callerName , new Map < string , vscode . CallHierarchyOutgoingCall > ( ) ) ;
156146 }
157147
158- const idxStart = bisectRight ( globalOrderedRanges , callerRange [ 0 ] , item => item [ 1 ] [ 0 ] ) ;
159- const idxEnd = bisectRight ( globalOrderedRanges , callerRange [ 1 ] , item => item [ 1 ] [ 0 ] ) ;
148+ const idxStart = bisectRight ( globalOrderedRanges , isCalledRange [ 0 ] , item => item [ 1 ] [ 0 ] ) ;
149+ const idxEnd = bisectRight ( globalOrderedRanges , isCalledRange [ 1 ] , item => item [ 1 ] [ 0 ] ) ;
150+
151+ // find possible isCalleds ranges
160152 for ( let i = idxStart ; i < idxEnd ; ++ i ) {
161153 visited . add ( i ) ;
162154
163- const realCallerRes = getRealCaller ( globalOrderedRanges [ i ] , currDocSymbolInfo ) ;
164- if ( realCallerRes === undefined ) {
165- continue ;
166- }
167- const [ currCallerName , callAppearRange , realCaller ] = realCallerRes ;
168- const realCallerStr = realCaller . stringify ( ) ;
169- if ( callHrchyItems . get ( currCallerName ) === undefined ) {
170- callHrchyItems . set ( currCallerName , new Map ( [ [ realCallerStr , buildCallHierarchyItem ( realCaller ) ] ] ) ) ;
171- }
172- const toItem = callHrchyItems . get ( currCallerName ) ?. get ( realCallerStr ) ;
173-
174- // this is kind of twisted,
175- // from-to relation represents the curr context
176- // definition must be the ISCALLED, execution must be the CALLER, curr context is not matter
177- // we are creating two directional edges
178- //
179- // fromItems |
180- // \ | / |
181- // key: 1. currCaller 2. isCalled |
182- // / | \ |
183- // toItems \|/
184- //
185- // that is, our dictionary needs the opposite info to build an edge
186- if ( ! callHierarchyICs . has ( currCallerName ) ) {
187- callHierarchyICs . set ( currCallerName , new Map < string , vscode . CallHierarchyIncomingCall > ( ) ) ;
188- }
189-
190- buildEdge (
191- callHierarchyICs . get ( currCallerName ) ! , realCallerStr , fromItem ,
192- callHierarchyOGs . get ( isCalledName ) ! , infoStr , toItem , [ callAppearRange ]
155+ const isCalledRange = globalOrderedRanges [ i ] ;
156+ buildEdgeForIsCalledRange (
157+ isCalledRange ,
158+ currDocSymbolInfo , callHrchyItems , callHierarchyICs , callHierarchyOGs ,
159+ callerName , callerSymbolStr , fromItem
193160 ) ;
194-
195161 }
162+
196163 }
197164
198165 return [ currCallHierarchyInfo , visited ] ;
166+ }
199167
168+ function buildEdgeForIsCalledRange (
169+ isCalledRange : [ string , [ number , number ] ] ,
170+ currDocSymbolInfo : DocSymbolInfo , callHrchyItems : Map < string , Map < string , vscode . CallHierarchyItem > > ,
171+ callHierarchyICs : Map < string , Map < string , vscode . CallHierarchyIncomingCall > > ,
172+ callHierarchyOGs : Map < string , Map < string , vscode . CallHierarchyOutgoingCall > > ,
173+ callerName : string , callerSymbolStr : string | undefined , fromItem : vscode . CallHierarchyItem | undefined ,
174+ ) {
175+ const realIsCalledRes = getRealIsCalled ( isCalledRange , currDocSymbolInfo ) ;
176+ if ( realIsCalledRes === undefined ) {
177+ return ;
178+ }
179+
180+ const [ isCalledName , callAppearRange , realIsCalled ] = realIsCalledRes ;
181+
182+ fromItem = ( fromItem === undefined ) ?
183+ // when the file is the caller, the file has no `range`.
184+ // Therefore, make the range circle back, that is,
185+ // let the range points to the isCalled itself
186+ new vscode . CallHierarchyItem (
187+ vscode . SymbolKind . Namespace , callerName ,
188+ currDocSymbolInfo . document . uri . path , currDocSymbolInfo . document . uri ,
189+ realIsCalled . loc . range , realIsCalled . loc . range
190+ ) : fromItem ;
191+
192+ const realIsCalledStr = realIsCalled . stringify ( ) ;
193+ if ( callHrchyItems . get ( isCalledName ) === undefined ) {
194+ callHrchyItems . set ( isCalledName , new Map ( [ [ realIsCalledStr , buildCallHierarchyItem ( realIsCalled ) ] ] ) ) ;
195+ }
196+ const toItem = callHrchyItems . get ( isCalledName ) ?. get ( realIsCalledStr ) ;
197+
198+ // we are creating two directional edges
199+ //
200+ // IncomingCall OutgoingCall
201+ //
202+ // fromItems
203+ // |
204+ // |
205+ // \|/
206+ // key: 1. isCalled 2. caller
207+ // |
208+ // |
209+ // \|/
210+ // toItems
211+ //
212+ // note that
213+ // `fromItems` is constructed from caller and
214+ // `toItems` is constructed from isCalled.
215+ // that is, our dictionary needs two infos to build an edge
216+ if ( ! callHierarchyICs . has ( isCalledName ) ) {
217+ callHierarchyICs . set ( isCalledName , new Map < string , vscode . CallHierarchyIncomingCall > ( ) ) ;
218+ }
219+
220+ buildEdge (
221+ callHierarchyICs . get ( isCalledName ) ! , realIsCalledStr , fromItem ,
222+ callHierarchyOGs . get ( callerName ) ! , callerSymbolStr , toItem ,
223+ [ callAppearRange ]
224+ ) ;
200225}
201226
202227
0 commit comments