@@ -88,6 +88,157 @@ const CallHierarchyCallsToRequest: RequestType<CallHierarchyParams, CallHierarch
8888const CallHierarchyCallsFromRequest : RequestType < CallHierarchyParams , CallHierarchyCallsItemResult , void > =
8989 new RequestType < CallHierarchyParams , CallHierarchyCallsItemResult , void > ( 'cpptools/callHierarchyCallsFrom' ) ;
9090
91+ interface CallHierarchyRequestResult < T > {
92+ result ?: T ;
93+ cancelled : boolean ;
94+ }
95+
96+ function makeVscodeCallHierarchyItem ( client : DefaultClient , item : CallHierarchyItem ) : vscode . CallHierarchyItem {
97+ const containerDetail : string = ( item . detail !== "" ) ? `${ item . detail } - ` : "" ;
98+ const itemUri : vscode . Uri = vscode . Uri . file ( item . file ) ;
99+
100+ // Get file detail
101+ const isInWorkspace : boolean = client . RootUri !== undefined &&
102+ itemUri . fsPath . startsWith ( client . RootUri ?. fsPath ) ;
103+ const dirPath : string = isInWorkspace ?
104+ path . relative ( client . RootPath , path . dirname ( item . file ) ) : path . dirname ( item . file ) ;
105+ const fileDetail : string = dirPath . length === 0 ?
106+ `${ path . basename ( item . file ) } ` : `${ path . basename ( item . file ) } (${ dirPath } )` ;
107+
108+ return new vscode . CallHierarchyItem (
109+ item . kind ,
110+ item . name ,
111+ containerDetail + fileDetail ,
112+ itemUri ,
113+ makeVscodeRange ( item . range ) ,
114+ makeVscodeRange ( item . selectionRange ) ) ;
115+ }
116+
117+ function createIncomingCalls ( client : DefaultClient , calls : CallHierarchyCallsItem [ ] ) : vscode . CallHierarchyIncomingCall [ ] {
118+ const result : vscode . CallHierarchyIncomingCall [ ] = [ ] ;
119+
120+ for ( const call of calls ) {
121+ const item : vscode . CallHierarchyItem = makeVscodeCallHierarchyItem ( client , call . item ) ;
122+ const ranges : vscode . Range [ ] = [ ] ;
123+ call . fromRanges . forEach ( r => {
124+ ranges . push ( makeVscodeRange ( r ) ) ;
125+ } ) ;
126+
127+ const incomingCall : vscode . CallHierarchyIncomingCall =
128+ new vscode . CallHierarchyIncomingCall ( item , ranges ) ;
129+ result . push ( incomingCall ) ;
130+ }
131+
132+ return result ;
133+ }
134+
135+ function createOutgoingCalls ( client : DefaultClient , calls : CallHierarchyCallsItem [ ] ) : vscode . CallHierarchyOutgoingCall [ ] {
136+ const result : vscode . CallHierarchyOutgoingCall [ ] = [ ] ;
137+
138+ for ( const call of calls ) {
139+ const item : vscode . CallHierarchyItem = makeVscodeCallHierarchyItem ( client , call . item ) ;
140+ const ranges : vscode . Range [ ] = [ ] ;
141+ call . fromRanges . forEach ( r => {
142+ ranges . push ( makeVscodeRange ( r ) ) ;
143+ } ) ;
144+
145+ const outgoingCall : vscode . CallHierarchyOutgoingCall =
146+ new vscode . CallHierarchyOutgoingCall ( item , ranges ) ;
147+ result . push ( outgoingCall ) ;
148+ }
149+
150+ return result ;
151+ }
152+
153+ export async function sendPrepareCallHierarchyRequest ( client : DefaultClient , document : vscode . TextDocument , position : vscode . Position , token : vscode . CancellationToken ) : Promise < CallHierarchyRequestResult < vscode . CallHierarchyItem > > {
154+ const range : vscode . Range | undefined = document . getWordRangeAtPosition ( position ) ;
155+ if ( range === undefined ) {
156+ return { cancelled : false } ;
157+ }
158+
159+ await client . ready ;
160+
161+ const params : CallHierarchyParams = {
162+ textDocument : { uri : document . uri . toString ( ) } ,
163+ position : Position . create ( position . line , position . character )
164+ } ;
165+
166+ let response : CallHierarchyItemResult ;
167+ try {
168+ response = await client . languageClient . sendRequest ( CallHierarchyItemRequest , params , token ) ;
169+ } catch ( e : any ) {
170+ if ( e instanceof ResponseError && ( e . code === RequestCancelled || e . code === ServerCancelled ) ) {
171+ return { cancelled : true } ;
172+ }
173+ throw e ;
174+ }
175+
176+ if ( token . isCancellationRequested ) {
177+ return { cancelled : true } ;
178+ }
179+
180+ return {
181+ cancelled : false ,
182+ result : response . item ? makeVscodeCallHierarchyItem ( client , response . item ) : undefined
183+ } ;
184+ }
185+
186+ export async function sendCallHierarchyIncomingCallsRequest ( client : DefaultClient , item : vscode . CallHierarchyItem , token : vscode . CancellationToken ) : Promise < CallHierarchyRequestResult < vscode . CallHierarchyIncomingCall [ ] > > {
187+ await client . ready ;
188+
189+ const params : CallHierarchyParams = {
190+ textDocument : { uri : item . uri . toString ( ) } ,
191+ position : Position . create ( item . selectionRange . start . line , item . selectionRange . start . character )
192+ } ;
193+
194+ let response : CallHierarchyCallsItemResult ;
195+ try {
196+ response = await client . languageClient . sendRequest ( CallHierarchyCallsToRequest , params , token ) ;
197+ } catch ( e : any ) {
198+ if ( e instanceof ResponseError && ( e . code === RequestCancelled || e . code === ServerCancelled ) ) {
199+ return { cancelled : true } ;
200+ }
201+ throw e ;
202+ }
203+
204+ if ( token . isCancellationRequested ) {
205+ return { cancelled : true } ;
206+ }
207+
208+ return {
209+ cancelled : false ,
210+ result : response . calls . length !== 0 ? createIncomingCalls ( client , response . calls ) : undefined
211+ } ;
212+ }
213+
214+ export async function sendCallHierarchyOutgoingCallsRequest ( client : DefaultClient , item : vscode . CallHierarchyItem , token : vscode . CancellationToken ) : Promise < CallHierarchyRequestResult < vscode . CallHierarchyOutgoingCall [ ] > > {
215+ await client . ready ;
216+
217+ const params : CallHierarchyParams = {
218+ textDocument : { uri : item . uri . toString ( ) } ,
219+ position : Position . create ( item . selectionRange . start . line , item . selectionRange . start . character )
220+ } ;
221+
222+ let response : CallHierarchyCallsItemResult ;
223+ try {
224+ response = await client . languageClient . sendRequest ( CallHierarchyCallsFromRequest , params , token ) ;
225+ } catch ( e : any ) {
226+ if ( e instanceof ResponseError && ( e . code === RequestCancelled || e . code === ServerCancelled ) ) {
227+ return { cancelled : true } ;
228+ }
229+ throw e ;
230+ }
231+
232+ if ( token . isCancellationRequested ) {
233+ return { cancelled : true } ;
234+ }
235+
236+ return {
237+ cancelled : false ,
238+ result : response . calls . length !== 0 ? createOutgoingCalls ( client , response . calls ) : undefined
239+ } ;
240+ }
241+
91242export class CallHierarchyProvider implements vscode . CallHierarchyProvider {
92243 // Indicates whether a request is from an entry root node (e.g. top function in the call tree).
93244 private isEntryRootNodeTelemetry : boolean = false ;
@@ -98,16 +249,9 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
98249 }
99250
100251 public async prepareCallHierarchy ( document : vscode . TextDocument , position : vscode . Position , token : vscode . CancellationToken ) : Promise < vscode . CallHierarchyItem | undefined > {
101- await this . client . ready ;
102-
103252 workspaceReferences . cancelCurrentReferenceRequest ( CancellationSender . NewRequest ) ;
104253 workspaceReferences . clearViews ( ) ;
105254
106- const range : vscode . Range | undefined = document . getWordRangeAtPosition ( position ) ;
107- if ( range === undefined ) {
108- return undefined ;
109- }
110-
111255 // Listen to a cancellation for this request. When this request is cancelled,
112256 // use a local cancellation source to explicitly cancel a token.
113257 const cancelSource : vscode . CancellationTokenSource = new vscode . CancellationTokenSource ( ) ;
@@ -118,37 +262,26 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
118262 cancelSource . cancel ( ) ;
119263 } ) ;
120264
121- const params : CallHierarchyParams = {
122- textDocument : { uri : document . uri . toString ( ) } ,
123- position : Position . create ( position . line , position . character )
124- } ;
125- let response : CallHierarchyItemResult ;
265+ let result : CallHierarchyRequestResult < vscode . CallHierarchyItem > ;
126266 try {
127- response = await this . client . languageClient . sendRequest ( CallHierarchyItemRequest , params , cancelSource . token ) ;
128- } catch ( e : any ) {
129- if ( e instanceof ResponseError && ( e . code === RequestCancelled || e . code === ServerCancelled ) ) {
130- return undefined ;
131- }
132- throw e ;
133- }
134- finally {
267+ result = await sendPrepareCallHierarchyRequest ( this . client , document , position , cancelSource . token ) ;
268+ } finally {
135269 cancellationTokenListener . dispose ( ) ;
136270 requestCanceledListener . dispose ( ) ;
137271 }
138272
139- if ( cancelSource . token . isCancellationRequested ) {
273+ if ( cancelSource . token . isCancellationRequested || result . cancelled ) {
140274 throw new vscode . CancellationError ( ) ;
141275 }
142- if ( response . item === undefined ) {
276+ if ( result . result === undefined ) {
143277 return undefined ;
144278 }
145279
146280 this . isEntryRootNodeTelemetry = true ;
147- return this . makeVscodeCallHierarchyItem ( response . item ) ;
281+ return result . result ;
148282 }
149283
150284 public async provideCallHierarchyIncomingCalls ( item : vscode . CallHierarchyItem , token : vscode . CancellationToken ) : Promise < vscode . CallHierarchyIncomingCall [ ] | undefined > {
151- await this . client . ready ;
152285 workspaceReferences . cancelCurrentReferenceRequest ( CancellationSender . NewRequest ) ;
153286
154287 const CallHierarchyCallsToEvent : string = "CallHierarchyCallsTo" ;
@@ -171,40 +304,30 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
171304 } ) ;
172305
173306 // Send the request to the language server.
174- let result : vscode . CallHierarchyIncomingCall [ ] | undefined ;
175- const params : CallHierarchyParams = {
176- textDocument : { uri : item . uri . toString ( ) } ,
177- position : Position . create ( item . selectionRange . start . line , item . selectionRange . start . character )
178- } ;
179- let response : CallHierarchyCallsItemResult | undefined ;
180- let cancelled : boolean = false ;
307+ let result : CallHierarchyRequestResult < vscode . CallHierarchyIncomingCall [ ] > ;
181308 try {
182- response = await this . client . languageClient . sendRequest ( CallHierarchyCallsToRequest , params , cancelSource . token ) ;
183- } catch ( e : any ) {
184- cancelled = e instanceof ResponseError && ( e . code === RequestCancelled || e . code === ServerCancelled ) ;
185- if ( ! cancelled ) {
186- throw e ;
187- }
309+ result = await sendCallHierarchyIncomingCallsRequest ( this . client , item , cancelSource . token ) ;
310+ } finally {
311+ cancellationTokenListener . dispose ( ) ;
312+ requestCanceledListener . dispose ( ) ;
188313 }
314+
189315 // Reset anything that can be cleared before processing the result.
190316 const progressBarDuration : number | undefined = workspaceReferences . getCallHierarchyProgressBarDuration ( ) ;
191317 workspaceReferences . resetProgressBar ( ) ;
192318 workspaceReferences . resetReferences ( ) ;
193- cancellationTokenListener . dispose ( ) ;
194- requestCanceledListener . dispose ( ) ;
195319
196320 // Process the result.
197- if ( cancelSource . token . isCancellationRequested || cancelled || requestCanceled !== undefined ) {
321+ if ( cancelSource . token . isCancellationRequested || result . cancelled || requestCanceled !== undefined ) {
198322 const requestStatus : CallHierarchyRequestStatus = requestCanceled === CancellationSender . User ?
199323 CallHierarchyRequestStatus . CanceledByUser : CallHierarchyRequestStatus . Canceled ;
200324 this . logTelemetry ( CallHierarchyCallsToEvent , requestStatus , progressBarDuration ) ;
201325 throw new vscode . CancellationError ( ) ;
202- } else if ( response && response . calls . length !== 0 ) {
203- result = this . createIncomingCalls ( response . calls ) ;
204326 }
205327
328+ const incomingCalls : vscode . CallHierarchyIncomingCall [ ] | undefined = result . result ;
206329 this . logTelemetry ( CallHierarchyCallsToEvent , CallHierarchyRequestStatus . Succeeded , progressBarDuration ) ;
207- return result ;
330+ return incomingCalls ;
208331 }
209332
210333 public async provideCallHierarchyOutgoingCalls ( item : vscode . CallHierarchyItem , token : vscode . CancellationToken ) : Promise < vscode . CallHierarchyOutgoingCall [ ] | undefined > {
@@ -214,89 +337,15 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
214337 return undefined ;
215338 }
216339
217- await this . client . ready ;
218-
219- let result : vscode . CallHierarchyOutgoingCall [ ] | undefined ;
220- const params : CallHierarchyParams = {
221- textDocument : { uri : item . uri . toString ( ) } ,
222- position : Position . create ( item . selectionRange . start . line , item . selectionRange . start . character )
223- } ;
224- let response : CallHierarchyCallsItemResult | undefined ;
225- let cancelled : boolean = false ;
226- try {
227- response = await this . client . languageClient . sendRequest ( CallHierarchyCallsFromRequest , params , token ) ;
228- } catch ( e : any ) {
229- cancelled = e instanceof ResponseError && ( e . code === RequestCancelled || e . code === ServerCancelled ) ;
230- if ( ! cancelled ) {
231- throw e ;
232- }
233- }
234- if ( token . isCancellationRequested || cancelled ) {
340+ const result : CallHierarchyRequestResult < vscode . CallHierarchyOutgoingCall [ ] > =
341+ await sendCallHierarchyOutgoingCallsRequest ( this . client , item , token ) ;
342+ if ( token . isCancellationRequested || result . cancelled ) {
235343 this . logTelemetry ( CallHierarchyCallsFromEvent , CallHierarchyRequestStatus . Canceled ) ;
236344 throw new vscode . CancellationError ( ) ;
237- } else if ( response && response . calls . length !== 0 ) {
238- result = this . createOutgoingCalls ( response . calls ) ;
239345 }
240346
241347 this . logTelemetry ( CallHierarchyCallsFromEvent , CallHierarchyRequestStatus . Succeeded ) ;
242- return result ;
243- }
244-
245- private makeVscodeCallHierarchyItem ( item : CallHierarchyItem ) : vscode . CallHierarchyItem {
246- const containerDetail : string = ( item . detail !== "" ) ? `${ item . detail } - ` : "" ;
247- const itemUri : vscode . Uri = vscode . Uri . file ( item . file ) ;
248-
249- // Get file detail
250- const isInWorkspace : boolean = this . client . RootUri !== undefined &&
251- itemUri . fsPath . startsWith ( this . client . RootUri ?. fsPath ) ;
252- const dirPath : string = isInWorkspace ?
253- path . relative ( this . client . RootPath , path . dirname ( item . file ) ) : path . dirname ( item . file ) ;
254- const fileDetail : string = dirPath . length === 0 ?
255- `${ path . basename ( item . file ) } ` : `${ path . basename ( item . file ) } (${ dirPath } )` ;
256-
257- return new vscode . CallHierarchyItem (
258- item . kind ,
259- item . name ,
260- containerDetail + fileDetail ,
261- itemUri ,
262- makeVscodeRange ( item . range ) ,
263- makeVscodeRange ( item . selectionRange ) ) ;
264- }
265-
266- private createIncomingCalls ( calls : CallHierarchyCallsItem [ ] ) : vscode . CallHierarchyIncomingCall [ ] {
267- const result : vscode . CallHierarchyIncomingCall [ ] = [ ] ;
268-
269- for ( const call of calls ) {
270- const item : vscode . CallHierarchyItem = this . makeVscodeCallHierarchyItem ( call . item ) ;
271- const ranges : vscode . Range [ ] = [ ] ;
272- call . fromRanges . forEach ( r => {
273- ranges . push ( makeVscodeRange ( r ) ) ;
274- } ) ;
275-
276- const incomingCall : vscode . CallHierarchyIncomingCall =
277- new vscode . CallHierarchyIncomingCall ( item , ranges ) ;
278- result . push ( incomingCall ) ;
279- }
280-
281- return result ;
282- }
283-
284- private createOutgoingCalls ( calls : CallHierarchyCallsItem [ ] ) : vscode . CallHierarchyOutgoingCall [ ] {
285- const result : vscode . CallHierarchyOutgoingCall [ ] = [ ] ;
286-
287- for ( const call of calls ) {
288- const item : vscode . CallHierarchyItem = this . makeVscodeCallHierarchyItem ( call . item ) ;
289- const ranges : vscode . Range [ ] = [ ] ;
290- call . fromRanges . forEach ( r => {
291- ranges . push ( makeVscodeRange ( r ) ) ;
292- } ) ;
293-
294- const outgoingCall : vscode . CallHierarchyOutgoingCall =
295- new vscode . CallHierarchyOutgoingCall ( item , ranges ) ;
296- result . push ( outgoingCall ) ;
297- }
298-
299- return result ;
348+ return result . result ;
300349 }
301350
302351 private logTelemetry ( eventName : string , requestStatus : CallHierarchyRequestStatus , progressBarDuration ?: number ) : void {
0 commit comments