Skip to content

Commit 1ac59fc

Browse files
committed
Remove Copilot completion request cancellation.
1 parent 9efde54 commit 1ac59fc

File tree

4 files changed

+41
-20
lines changed

4 files changed

+41
-20
lines changed

Extension/src/LanguageServer/client.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -804,9 +804,9 @@ export interface Client {
804804
getShowConfigureIntelliSenseButton(): boolean;
805805
setShowConfigureIntelliSenseButton(show: boolean): void;
806806
addTrustedCompiler(path: string): Promise<void>;
807-
getIncludes(maxDepth: number, token: vscode.CancellationToken): Promise<GetIncludesResult>;
807+
getIncludes(maxDepth: number): Promise<GetIncludesResult>;
808808
getChatContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ChatContextResult>;
809-
getProjectContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ProjectContextResult>;
809+
getProjectContext(uri: vscode.Uri): Promise<ProjectContextResult>;
810810
}
811811

812812
export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client {
@@ -2228,11 +2228,11 @@ export class DefaultClient implements Client {
22282228
await this.languageClient.sendNotification(DidOpenNotification, params);
22292229
}
22302230

2231-
public async getIncludes(maxDepth: number, token: vscode.CancellationToken): Promise<GetIncludesResult> {
2231+
public async getIncludes(maxDepth: number): Promise<GetIncludesResult> {
22322232
const params: GetIncludesParams = { maxDepth: maxDepth };
22332233
await this.ready;
2234-
return DefaultClient.withLspCancellationHandling(
2235-
() => this.languageClient.sendRequest(IncludesRequest, params, token), token);
2234+
return DefaultClient.withoutLspCancellationHandling(
2235+
() => this.languageClient.sendRequest(IncludesRequest, params));
22362236
}
22372237

22382238
public async getChatContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ChatContextResult> {
@@ -2242,11 +2242,11 @@ export class DefaultClient implements Client {
22422242
() => this.languageClient.sendRequest(CppContextRequest, params, token), token);
22432243
}
22442244

2245-
public async getProjectContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ProjectContextResult> {
2245+
public async getProjectContext(uri: vscode.Uri): Promise<ProjectContextResult> {
22462246
const params: TextDocumentIdentifier = { uri: uri.toString() };
2247-
await withCancellation(this.ready, token);
2248-
return DefaultClient.withLspCancellationHandling(
2249-
() => this.languageClient.sendRequest(ProjectContextRequest, params, token), token);
2247+
await this.ready;
2248+
return DefaultClient.withoutLspCancellationHandling(
2249+
() => this.languageClient.sendRequest(ProjectContextRequest, params));
22502250
}
22512251

22522252
/**
@@ -2348,6 +2348,27 @@ export class DefaultClient implements Client {
23482348
return result;
23492349
}
23502350

2351+
// This is used to avoid processing unnecessary LSP cancel requests during a Copilot completion
2352+
// when the result could still be used in 2 minutes in its cache before it sends another request.
2353+
private static async withoutLspCancellationHandling<T>(task: () => Promise<T>): Promise<T> {
2354+
let result: T;
2355+
2356+
try {
2357+
result = await task();
2358+
} catch (e: any) {
2359+
if (e instanceof ResponseError && e.code === ServerCancelled) {
2360+
// This can occur if the user switches files and makes edits fast enough.
2361+
// It doesn't seem like a very important scenario, so cancelling seems fine, even though
2362+
// not cancelling would allow the value to be cached if the user switches back to that file.
2363+
throw new vscode.CancellationError();
2364+
} else {
2365+
throw e;
2366+
}
2367+
}
2368+
2369+
return result;
2370+
}
2371+
23512372
private callTaskWithTimeout<T>(task: () => Thenable<T>, ms: number, cancelToken?: vscode.CancellationTokenSource): Promise<T> {
23522373
let timer: NodeJS.Timeout;
23532374

@@ -4151,7 +4172,7 @@ class NullClient implements Client {
41514172
getShowConfigureIntelliSenseButton(): boolean { return false; }
41524173
setShowConfigureIntelliSenseButton(show: boolean): void { }
41534174
addTrustedCompiler(path: string): Promise<void> { return Promise.resolve(); }
4154-
getIncludes(maxDepth: number, token: vscode.CancellationToken): Promise<GetIncludesResult> { return Promise.resolve({} as GetIncludesResult); }
4175+
getIncludes(maxDepth: number): Promise<GetIncludesResult> { return Promise.resolve({} as GetIncludesResult); }
41554176
getChatContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ChatContextResult> { return Promise.resolve({} as ChatContextResult); }
4156-
getProjectContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ProjectContextResult> { return Promise.resolve({} as ProjectContextResult); }
4177+
getProjectContext(uri: vscode.Uri): Promise<ProjectContextResult> { return Promise.resolve({} as ProjectContextResult); }
41574178
}

Extension/src/LanguageServer/copilotProviders.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ export async function registerRelatedFilesProvider(): Promise<void> {
3838
for (const languageId of ['c', 'cpp', 'cuda-cpp']) {
3939
api.registerRelatedFilesProvider(
4040
{ extensionId: util.extensionContext.extension.id, languageId },
41-
async (uri: vscode.Uri, context: { flags: Record<string, unknown> }, token: vscode.CancellationToken) => {
41+
async (uri: vscode.Uri, context: { flags: Record<string, unknown> }) => {
4242
const start = performance.now();
4343
const telemetryProperties: Record<string, string> = {};
4444
const telemetryMetrics: Record<string, number> = {};
4545
try {
46-
const getIncludesHandler = async () => (await getIncludesWithCancellation(1, token))?.includedFiles.map(file => vscode.Uri.file(file)) ?? [];
46+
const getIncludesHandler = async () => (await getIncludes(1))?.includedFiles.map(file => vscode.Uri.file(file)) ?? [];
4747
const getTraitsHandler = async () => {
48-
const projectContext = await getProjectContext(uri, context, token);
48+
const projectContext = await getProjectContext(uri, context);
4949

5050
if (!projectContext) {
5151
return undefined;
@@ -154,9 +154,9 @@ export async function registerRelatedFilesProvider(): Promise<void> {
154154
}
155155
}
156156

157-
async function getIncludesWithCancellation(maxDepth: number, token: vscode.CancellationToken): Promise<GetIncludesResult> {
157+
async function getIncludes(maxDepth: number): Promise<GetIncludesResult> {
158158
const activeClient = getActiveClient();
159-
const includes = await activeClient.getIncludes(maxDepth, token);
159+
const includes = await activeClient.getIncludes(maxDepth);
160160
const wksFolder = activeClient.RootUri?.toString();
161161

162162
if (!wksFolder) {

Extension/src/LanguageServer/lmTool.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ function filterCompilerArguments(compiler: string, compilerArguments: string[],
127127
return result;
128128
}
129129

130-
export async function getProjectContext(uri: vscode.Uri, context: { flags: Record<string, unknown> }, token: vscode.CancellationToken): Promise<ProjectContext | undefined> {
130+
export async function getProjectContext(uri: vscode.Uri, context: { flags: Record<string, unknown> }): Promise<ProjectContext | undefined> {
131131
const telemetryProperties: Record<string, string> = {};
132132
const telemetryMetrics: Record<string, number> = {};
133133
try {
134-
const projectContext = await checkDuration<ProjectContextResult | undefined>(async () => await getClients()?.ActiveClient?.getProjectContext(uri, token) ?? undefined);
134+
const projectContext = await checkDuration<ProjectContextResult | undefined>(async () => await getClients()?.ActiveClient?.getProjectContext(uri) ?? undefined);
135135
telemetryMetrics["duration"] = projectContext.duration;
136136
if (!projectContext.result) {
137137
return undefined;

Extension/test/scenarios/SingleRootProject/tests/lmTool.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ describe('CppConfigurationLanguageModelTool Tests', () => {
200200
}
201201
});
202202

203-
const result = await getProjectContext(mockTextDocumentStub.uri, context, new vscode.CancellationTokenSource().token);
203+
const result = await getProjectContext(mockTextDocumentStub.uri, context);
204204

205205
ok(result, 'result should not be undefined');
206206
ok(result.language === 'C++');
@@ -364,7 +364,7 @@ describe('CppConfigurationLanguageModelTool Tests', () => {
364364
}
365365
});
366366

367-
const result = await getProjectContext(mockTextDocumentStub.uri, { flags: {} }, new vscode.CancellationTokenSource().token);
367+
const result = await getProjectContext(mockTextDocumentStub.uri, { flags: {} });
368368

369369
ok(telemetryStub.calledOnce, 'Telemetry should be called once');
370370
ok(telemetryStub.calledWithMatch('ProjectContext', sinon.match({

0 commit comments

Comments
 (0)