@@ -41,27 +41,28 @@ function buildEdge(
41
41
return ;
42
42
}
43
43
44
- function getRealCaller (
44
+ function getRealIsCalled (
45
45
globalOrderedRange : [ string , [ number , number ] ] , currDocSymbolInfo : DocSymbolInfo ,
46
46
) : [ string , vscode . Range , SymbolInfo ] | undefined {
47
47
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 ) {
51
51
return undefined ;
52
52
}
53
- if ( shadow !== undefined && shadow . length !== 0 && isShadowed ( currCallerRange , shadow ) ) {
53
+ if ( shadow !== undefined && shadow . length !== 0 && isShadowed ( isCalledRange , shadow ) ) {
54
54
return undefined ;
55
55
}
56
- if ( isRangeIntExcludedRanges ( currCallerRange , currDocSymbolInfo . docRes . commentAndStringRange ) ) {
56
+ if ( isRangeIntExcludedRanges ( isCalledRange , currDocSymbolInfo . docRes . commentAndStringRange ) ) {
57
57
return undefined ;
58
58
}
59
59
60
60
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 ] ) ,
63
63
) ;
64
- return [ currCallerName , callAppearRange , realCaller ] ;
64
+
65
+ return [ isCalledName , callAppearRange , realIsCalled ] ;
65
66
}
66
67
67
68
function genAllCallHierarchyItems (
@@ -73,44 +74,28 @@ function genAllCallHierarchyItems(
73
74
const callHierarchyICs = callHrchyInfo . incomingCall ;
74
75
const callHierarchyOGs = callHrchyInfo . outgoingCall ;
75
76
76
- // fileItem
77
+ // make the file as definition, that is,
78
+ // make the file as caller
77
79
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 > ( ) ) ;
81
83
}
82
84
85
+ // find isCalled ranges who is NOT visited. (orphans)
83
86
for ( let i = 0 ; i < globalOrderedRanges . length ; ++ i ) {
84
87
if ( visited . has ( i ) ) {
85
88
continue ;
86
89
}
87
90
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
103
98
) ;
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
-
114
99
}
115
100
return callHrchyInfo ;
116
101
}
@@ -119,6 +104,7 @@ function genAllCallHierarchyItems(
119
104
function genAllCallHierarchyItemsNonOrphan (
120
105
currDocSymbolInfo : DocSymbolInfo , globalOrderedRanges : [ string , [ number , number ] ] [ ]
121
106
) : [ CallHrchyInfo , Set < number > ] {
107
+ // init
122
108
const visited : Set < number > = new Set ( ) ;
123
109
124
110
const callHrchyItems : Map < string , Map < string , vscode . CallHierarchyItem > > =
@@ -134,69 +120,108 @@ function genAllCallHierarchyItemsNonOrphan(
134
120
return a . numRange [ 0 ] - b . numRange [ 0 ] ;
135
121
} ) ;
136
122
123
+ // iterate all globalDef as caller
124
+ // for example a() {b, c}, `a` as the caller
137
125
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 ) ] ] ) ) ;
142
131
}
143
- const fromItem = callHrchyItems . get ( isCalledName ) ?. get ( infoStr ) ;
132
+ const fromItem = callHrchyItems . get ( callerName ) ?. get ( callerSymbolStr ) ;
144
133
if ( fromItem === undefined ) {
145
134
continue ;
146
135
}
147
136
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 ) {
151
141
continue ;
152
142
}
153
143
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 > ( ) ) ;
156
146
}
157
147
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
160
152
for ( let i = idxStart ; i < idxEnd ; ++ i ) {
161
153
visited . add ( i ) ;
162
154
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
193
160
) ;
194
-
195
161
}
162
+
196
163
}
197
164
198
165
return [ currCallHierarchyInfo , visited ] ;
166
+ }
199
167
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
+ ) ;
200
225
}
201
226
202
227
0 commit comments