Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 89 additions & 83 deletions Extension/src/LanguageServer/Providers/callHierarchyProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,93 +220,99 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
this.client = client;
}

public async prepareCallHierarchy(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.CallHierarchyItem | undefined> {
await this.client.ready;

workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
workspaceReferences.clearViews();

const range: vscode.Range | undefined = document.getWordRangeAtPosition(position);
if (range === undefined) {
return undefined;
}

// Listen to a cancellation for this request. When this request is cancelled,
// use a local cancellation source to explicitly cancel a token.
const cancelSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
const cancellationTokenListener: vscode.Disposable = token.onCancellationRequested(() => {
cancelSource.cancel();
public prepareCallHierarchy(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.CallHierarchyItem | undefined> {
return this.client.enqueue(async () => {
if (token.isCancellationRequested) {
throw new vscode.CancellationError();
}

workspaceReferences.clearViews();

const range: vscode.Range | undefined = document.getWordRangeAtPosition(position);
if (range === undefined) {
return undefined;
}

// Listen to a cancellation for this request. When this request is cancelled,
// use a local cancellation source to explicitly cancel a token.
const cancelSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
const cancellationTokenListener: vscode.Disposable = token.onCancellationRequested(() => {
cancelSource.cancel();
});
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(_sender => {
cancelSource.cancel();
});

let result: vscode.CallHierarchyItem[] | undefined;
try {
result = await sendPrepareCallHierarchyRequest(this.client, document.uri, position, cancelSource.token);
} finally {
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}

if (cancelSource.token.isCancellationRequested) {
throw new vscode.CancellationError();
}
if (!result || result.length === 0) {
return undefined;
}

this.isEntryRootNodeTelemetry = true;
return result[0];
});
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(_sender => {
cancelSource.cancel();
});

let result: vscode.CallHierarchyItem[] | undefined;
try {
result = await sendPrepareCallHierarchyRequest(this.client, document.uri, position, cancelSource.token);
} finally {
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}

if (cancelSource.token.isCancellationRequested) {
throw new vscode.CancellationError();
}
if (!result || result.length === 0) {
return undefined;
}

this.isEntryRootNodeTelemetry = true;
return result[0];
}

public async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
await this.client.ready;
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);

const CallHierarchyCallsToEvent: string = "CallHierarchyCallsTo";
if (item === undefined) {
this.logTelemetry(CallHierarchyCallsToEvent, CallHierarchyRequestStatus.Failed);
return undefined;
}

// Listen to a cancellation for this request. When this request is cancelled,
// use a local cancellation source to explicitly cancel a token.
let requestCanceled: CancellationSender | undefined;
const cancelSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
const cancellationTokenListener: vscode.Disposable = token.onCancellationRequested(() => {
requestCanceled = CancellationSender.ProviderToken;
cancelSource.cancel();
});
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(sender => {
requestCanceled = sender;
cancelSource.cancel();
public provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
return this.client.enqueue(async () => {
if (token.isCancellationRequested) {
throw new vscode.CancellationError();
}

const CallHierarchyCallsToEvent: string = "CallHierarchyCallsTo";
if (item === undefined) {
this.logTelemetry(CallHierarchyCallsToEvent, CallHierarchyRequestStatus.Failed);
return undefined;
}

// Listen to a cancellation for this request. When this request is cancelled,
// use a local cancellation source to explicitly cancel a token.
let requestCanceled: CancellationSender | undefined;
const cancelSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
const cancellationTokenListener: vscode.Disposable = token.onCancellationRequested(() => {
requestCanceled = CancellationSender.ProviderToken;
cancelSource.cancel();
});
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(sender => {
requestCanceled = sender;
cancelSource.cancel();
});

// Send the request to the language server.
let result: vscode.CallHierarchyIncomingCall[] | undefined;
let progressBarDuration: number | undefined;
try {
result = await sendCallHierarchyCallsToRequest(this.client, item, cancelSource.token);
} finally {
// Reset anything that can be cleared before processing the result.
progressBarDuration = workspaceReferences.getCallHierarchyProgressBarDuration();
workspaceReferences.resetProgressBar();
workspaceReferences.resetReferences();
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}

// Process the result.
if (cancelSource.token.isCancellationRequested || result === undefined || requestCanceled !== undefined) {
const requestStatus: CallHierarchyRequestStatus = requestCanceled === CancellationSender.User ?
CallHierarchyRequestStatus.CanceledByUser : CallHierarchyRequestStatus.Canceled;
this.logTelemetry(CallHierarchyCallsToEvent, requestStatus, progressBarDuration);
throw new vscode.CancellationError();
}

this.logTelemetry(CallHierarchyCallsToEvent, CallHierarchyRequestStatus.Succeeded, progressBarDuration);
return result.length !== 0 ? result : undefined;
});

// Send the request to the language server.
let result: vscode.CallHierarchyIncomingCall[] | undefined;
let progressBarDuration: number | undefined;
try {
result = await sendCallHierarchyCallsToRequest(this.client, item, cancelSource.token);
} finally {
// Reset anything that can be cleared before processing the result.
progressBarDuration = workspaceReferences.getCallHierarchyProgressBarDuration();
workspaceReferences.resetProgressBar();
workspaceReferences.resetReferences();
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}

// Process the result.
if (cancelSource.token.isCancellationRequested || result === undefined || requestCanceled !== undefined) {
const requestStatus: CallHierarchyRequestStatus = requestCanceled === CancellationSender.User ?
CallHierarchyRequestStatus.CanceledByUser : CallHierarchyRequestStatus.Canceled;
this.logTelemetry(CallHierarchyCallsToEvent, requestStatus, progressBarDuration);
throw new vscode.CancellationError();
}

this.logTelemetry(CallHierarchyCallsToEvent, CallHierarchyRequestStatus.Succeeded, progressBarDuration);
return result.length !== 0 ? result : undefined;
}

public async provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyOutgoingCall[] | undefined> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as vscode from 'vscode';
import { Position, RequestType, ResponseError } from 'vscode-languageclient';
import { DefaultClient, workspaceReferences } from '../client';
import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { CancellationSender, ReferenceInfo, ReferenceType, ReferencesParams, ReferencesResult } from '../references';
import { ReferenceInfo, ReferenceType, ReferencesParams, ReferencesResult } from '../references';

const FindAllReferencesRequest: RequestType<ReferencesParams, ReferencesResult, void> =
new RequestType<ReferencesParams, ReferencesResult, void>('cpptools/findAllReferences');
Expand Down Expand Up @@ -62,43 +62,46 @@ export class FindAllReferencesProvider implements vscode.ReferenceProvider {
this.client = client;
}

public async provideReferences(document: vscode.TextDocument, position: vscode.Position, context: vscode.ReferenceContext, token: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
await this.client.ready;
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
public provideReferences(document: vscode.TextDocument, position: vscode.Position, context: vscode.ReferenceContext, token: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
return this.client.enqueue(async () => {
if (token.isCancellationRequested) {
throw new vscode.CancellationError();
}

// Listen to a cancellation for this request. When this request is cancelled,
// use a local cancellation source to explicitly cancel a token.
const cancelSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
const cancellationTokenListener: vscode.Disposable = token.onCancellationRequested(() => { cancelSource.cancel(); });
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(_sender => { cancelSource.cancel(); });
// Listen to a cancellation for this request. When this request is cancelled,
// use a local cancellation source to explicitly cancel a token.
const cancelSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
const cancellationTokenListener: vscode.Disposable = token.onCancellationRequested(() => { cancelSource.cancel(); });
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(_sender => { cancelSource.cancel(); });

// Send the request to the language server.
let result: FindAllReferencesResult | undefined;
try {
result = await sendFindAllReferencesRequest(this.client, document.uri, position, cancelSource.token);
} finally {
// Reset anything that can be cleared before processing the result.
workspaceReferences.resetProgressBar();
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}
// Send the request to the language server.
let result: FindAllReferencesResult | undefined;
try {
result = await sendFindAllReferencesRequest(this.client, document.uri, position, cancelSource.token);
} finally {
// Reset anything that can be cleared before processing the result.
workspaceReferences.resetProgressBar();
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}

// Process the result.
if (cancelSource.token.isCancellationRequested || !result) {
// Return undefined instead of vscode.CancellationError to avoid the following error message from VS Code:
// "Cannot destructure property 'range' of 'e.location' as it is undefined."
// TODO: per issue https://github.com/microsoft/vscode/issues/169698
// vscode.CancellationError is expected, so when VS Code fixes the error use vscode.CancellationError again.
workspaceReferences.resetReferences();
return undefined;
} else if (result.referencesResult.referenceInfos.length > 0) {
// Display other reference types in panel or channel view.
// Note: ReferencesManager.resetReferences is called in ReferencesManager.showResultsInPanelView
workspaceReferences.showResultsInPanelView(result.referencesResult);
} else {
workspaceReferences.resetReferences();
}
// Process the result.
if (cancelSource.token.isCancellationRequested || !result) {
// Return undefined instead of vscode.CancellationError to avoid the following error message from VS Code:
// "Cannot destructure property 'range' of 'e.location' as it is undefined."
// TODO: per issue https://github.com/microsoft/vscode/issues/169698
// vscode.CancellationError is expected, so when VS Code fixes the error use vscode.CancellationError again.
workspaceReferences.resetReferences();
return undefined;
} else if (result.referencesResult.referenceInfos.length > 0) {
// Display other reference types in panel or channel view.
// Note: ReferencesManager.resetReferences is called in ReferencesManager.showResultsInPanelView
workspaceReferences.showResultsInPanelView(result.referencesResult);
} else {
workspaceReferences.resetReferences();
}

return result.locations;
return result.locations;
});
}
}
Loading
Loading