Skip to content

Commit dc0ba67

Browse files
authored
Merge branch 'main' into seanmcm/1_32_0_changelog
2 parents 6ad793f + 775fd69 commit dc0ba67

File tree

4 files changed

+330
-142
lines changed

4 files changed

+330
-142
lines changed

Extension/src/LanguageServer/Providers/callHierarchyProvider.ts

Lines changed: 143 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,129 @@ const CallHierarchyCallsToRequest: RequestType<CallHierarchyParams, CallHierarch
8888
const CallHierarchyCallsFromRequest: RequestType<CallHierarchyParams, CallHierarchyCallsItemResult, void> =
8989
new RequestType<CallHierarchyParams, CallHierarchyCallsItemResult, void>('cpptools/callHierarchyCallsFrom');
9090

91+
function makeVscodeCallHierarchyItem(client: DefaultClient, item: CallHierarchyItem): vscode.CallHierarchyItem {
92+
const containerDetail: string = (item.detail !== "") ? `${item.detail} - ` : "";
93+
const itemUri: vscode.Uri = vscode.Uri.file(item.file);
94+
95+
// Get file detail
96+
const isInWorkspace: boolean = client.RootUri !== undefined &&
97+
itemUri.fsPath.startsWith(client.RootUri.fsPath);
98+
const dirPath: string = isInWorkspace ?
99+
path.relative(client.RootPath, path.dirname(item.file)) : path.dirname(item.file);
100+
const fileDetail: string = dirPath.length === 0 ?
101+
`${path.basename(item.file)}` : `${path.basename(item.file)} (${dirPath})`;
102+
103+
return new vscode.CallHierarchyItem(
104+
item.kind,
105+
item.name,
106+
containerDetail + fileDetail,
107+
itemUri,
108+
makeVscodeRange(item.range),
109+
makeVscodeRange(item.selectionRange));
110+
}
111+
112+
function createIncomingCalls(client: DefaultClient, calls: CallHierarchyCallsItem[]): vscode.CallHierarchyIncomingCall[] {
113+
const result: vscode.CallHierarchyIncomingCall[] = [];
114+
115+
for (const call of calls) {
116+
const item: vscode.CallHierarchyItem = makeVscodeCallHierarchyItem(client, call.item);
117+
const ranges: vscode.Range[] = [];
118+
call.fromRanges.forEach(r => {
119+
ranges.push(makeVscodeRange(r));
120+
});
121+
122+
const incomingCall: vscode.CallHierarchyIncomingCall =
123+
new vscode.CallHierarchyIncomingCall(item, ranges);
124+
result.push(incomingCall);
125+
}
126+
127+
return result;
128+
}
129+
130+
function createOutgoingCalls(client: DefaultClient, calls: CallHierarchyCallsItem[]): vscode.CallHierarchyOutgoingCall[] {
131+
const result: vscode.CallHierarchyOutgoingCall[] = [];
132+
133+
for (const call of calls) {
134+
const item: vscode.CallHierarchyItem = makeVscodeCallHierarchyItem(client, call.item);
135+
const ranges: vscode.Range[] = [];
136+
call.fromRanges.forEach(r => {
137+
ranges.push(makeVscodeRange(r));
138+
});
139+
140+
const outgoingCall: vscode.CallHierarchyOutgoingCall =
141+
new vscode.CallHierarchyOutgoingCall(item, ranges);
142+
result.push(outgoingCall);
143+
}
144+
145+
return result;
146+
}
147+
148+
export async function sendPrepareCallHierarchyRequest(client: DefaultClient, uri: vscode.Uri, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.CallHierarchyItem[] | undefined> {
149+
const params: CallHierarchyParams = {
150+
textDocument: { uri: uri.toString() },
151+
position: Position.create(position.line, position.character)
152+
};
153+
let response: CallHierarchyItemResult;
154+
try {
155+
response = await client.languageClient.sendRequest(CallHierarchyItemRequest, params, token);
156+
} catch (e: any) {
157+
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
158+
return undefined;
159+
}
160+
throw e;
161+
}
162+
163+
if (token.isCancellationRequested) {
164+
return undefined;
165+
}
166+
167+
return response.item === undefined ? [] : [makeVscodeCallHierarchyItem(client, response.item)];
168+
}
169+
170+
export async function sendCallHierarchyCallsToRequest(client: DefaultClient, item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
171+
const params: CallHierarchyParams = {
172+
textDocument: { uri: item.uri.toString() },
173+
position: Position.create(item.selectionRange.start.line, item.selectionRange.start.character)
174+
};
175+
let response: CallHierarchyCallsItemResult;
176+
try {
177+
response = await client.languageClient.sendRequest(CallHierarchyCallsToRequest, params, token);
178+
} catch (e: any) {
179+
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
180+
return undefined;
181+
}
182+
throw e;
183+
}
184+
185+
if (token.isCancellationRequested) {
186+
return undefined;
187+
}
188+
189+
return response.calls.length !== 0 ? createIncomingCalls(client, response.calls) : [];
190+
}
191+
192+
export async function sendCallHierarchyCallsFromRequest(client: DefaultClient, item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyOutgoingCall[] | undefined> {
193+
const params: CallHierarchyParams = {
194+
textDocument: { uri: item.uri.toString() },
195+
position: Position.create(item.selectionRange.start.line, item.selectionRange.start.character)
196+
};
197+
let response: CallHierarchyCallsItemResult;
198+
try {
199+
response = await client.languageClient.sendRequest(CallHierarchyCallsFromRequest, params, token);
200+
} catch (e: any) {
201+
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
202+
return undefined;
203+
}
204+
throw e;
205+
}
206+
207+
if (token.isCancellationRequested) {
208+
return undefined;
209+
}
210+
211+
return response.calls.length !== 0 ? createOutgoingCalls(client, response.calls) : [];
212+
}
213+
91214
export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
92215
// Indicates whether a request is from an entry root node (e.g. top function in the call tree).
93216
private isEntryRootNodeTelemetry: boolean = false;
@@ -118,33 +241,23 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
118241
cancelSource.cancel();
119242
});
120243

121-
const params: CallHierarchyParams = {
122-
textDocument: { uri: document.uri.toString() },
123-
position: Position.create(position.line, position.character)
124-
};
125-
let response: CallHierarchyItemResult;
244+
let result: vscode.CallHierarchyItem[] | undefined;
126245
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 {
246+
result = await sendPrepareCallHierarchyRequest(this.client, document.uri, position, cancelSource.token);
247+
} finally {
135248
cancellationTokenListener.dispose();
136249
requestCanceledListener.dispose();
137250
}
138251

139252
if (cancelSource.token.isCancellationRequested) {
140253
throw new vscode.CancellationError();
141254
}
142-
if (response.item === undefined) {
255+
if (!result || result.length === 0) {
143256
return undefined;
144257
}
145258

146259
this.isEntryRootNodeTelemetry = true;
147-
return this.makeVscodeCallHierarchyItem(response.item);
260+
return result[0];
148261
}
149262

150263
public async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
@@ -172,39 +285,28 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
172285

173286
// Send the request to the language server.
174287
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;
288+
let progressBarDuration: number | undefined;
181289
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-
}
290+
result = await sendCallHierarchyCallsToRequest(this.client, item, cancelSource.token);
291+
} finally {
292+
// Reset anything that can be cleared before processing the result.
293+
progressBarDuration = workspaceReferences.getCallHierarchyProgressBarDuration();
294+
workspaceReferences.resetProgressBar();
295+
workspaceReferences.resetReferences();
296+
cancellationTokenListener.dispose();
297+
requestCanceledListener.dispose();
188298
}
189-
// Reset anything that can be cleared before processing the result.
190-
const progressBarDuration: number | undefined = workspaceReferences.getCallHierarchyProgressBarDuration();
191-
workspaceReferences.resetProgressBar();
192-
workspaceReferences.resetReferences();
193-
cancellationTokenListener.dispose();
194-
requestCanceledListener.dispose();
195299

196300
// Process the result.
197-
if (cancelSource.token.isCancellationRequested || cancelled || requestCanceled !== undefined) {
301+
if (cancelSource.token.isCancellationRequested || result === undefined || requestCanceled !== undefined) {
198302
const requestStatus: CallHierarchyRequestStatus = requestCanceled === CancellationSender.User ?
199303
CallHierarchyRequestStatus.CanceledByUser : CallHierarchyRequestStatus.Canceled;
200304
this.logTelemetry(CallHierarchyCallsToEvent, requestStatus, progressBarDuration);
201305
throw new vscode.CancellationError();
202-
} else if (response && response.calls.length !== 0) {
203-
result = this.createIncomingCalls(response.calls);
204306
}
205307

206308
this.logTelemetry(CallHierarchyCallsToEvent, CallHierarchyRequestStatus.Succeeded, progressBarDuration);
207-
return result;
309+
return result.length !== 0 ? result : undefined;
208310
}
209311

210312
public async provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyOutgoingCall[] | undefined> {
@@ -216,87 +318,15 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
216318

217319
await this.client.ready;
218320

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) {
321+
const result: vscode.CallHierarchyOutgoingCall[] | undefined =
322+
await sendCallHierarchyCallsFromRequest(this.client, item, token);
323+
if (token.isCancellationRequested || result === undefined) {
235324
this.logTelemetry(CallHierarchyCallsFromEvent, CallHierarchyRequestStatus.Canceled);
236325
throw new vscode.CancellationError();
237-
} else if (response && response.calls.length !== 0) {
238-
result = this.createOutgoingCalls(response.calls);
239326
}
240327

241328
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;
329+
return result.length !== 0 ? result : undefined;
300330
}
301331

302332
private logTelemetry(eventName: string, requestStatus: CallHierarchyRequestStatus, progressBarDuration?: number): void {

0 commit comments

Comments
 (0)