Skip to content

Commit 2690d22

Browse files
authored
nes: fix snippet vs trait identification & implementation of getContextItemsOnTimeout (#401)
* nes: fix: correctly identify code snippets by checking the type shape also, do not include info that's then not used * nes: extract conversion methods * nes: fix implementation of getContextItemsOnTimeout
1 parent 3d2e56e commit 2690d22

File tree

1 file changed

+37
-26
lines changed

1 file changed

+37
-26
lines changed

src/extension/languageContextProvider/vscode-node/languageContextProviderService.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { type CancellationToken, languages, type TextDocument, type Disposable a
77
import { Copilot } from '../../../platform/inlineCompletions/common/api';
88
import { ILanguageContextProviderService } from '../../../platform/languageContextProvider/common/languageContextProviderService';
99
import { ContextItem, ContextKind, SnippetContext, TraitContext } from '../../../platform/languageServer/common/languageContextService';
10+
import { filterMap } from '../../../util/common/arrays';
1011
import { AsyncIterableObject } from '../../../util/vs/base/common/async';
1112
import { Disposable, toDisposable } from '../../../util/vs/base/common/lifecycle';
1213
import { URI } from '../../../util/vs/base/common/uri';
@@ -38,55 +39,57 @@ export class LanguageContextProviderService extends Disposable implements ILangu
3839
public getContextItems(doc: TextDocument, request: Copilot.ResolveRequest, cancellationToken: CancellationToken): AsyncIterable<ContextItem> {
3940
const providers = this.getContextProviders(doc);
4041

41-
const items = new AsyncIterableObject<{ context: Copilot.SupportedContextItem; timeStamp: number; onTimeout: boolean }>(async emitter => {
42+
const items = new AsyncIterableObject<Copilot.SupportedContextItem>(async emitter => {
4243
async function runProvider(provider: Copilot.ContextProvider<Copilot.SupportedContextItem>) {
4344
const langCtx = provider.resolver.resolve(request, cancellationToken);
4445
if (typeof (langCtx as any)[Symbol.asyncIterator] === 'function') {
4546
for await (const context of langCtx as AsyncIterable<Copilot.SupportedContextItem>) {
46-
emitter.emitOne({ context, timeStamp: Date.now(), onTimeout: false });
47+
emitter.emitOne(context);
4748
}
4849
return;
4950
}
5051
const result = await langCtx;
5152
if (Array.isArray(result)) {
5253
for (const context of result) {
53-
emitter.emitOne({ context, timeStamp: Date.now(), onTimeout: false });
54+
emitter.emitOne(context);
5455
}
5556
} else if (typeof (result as any)[Symbol.asyncIterator] !== 'function') {
5657
// Only push if it's a single SupportedContextItem, not an AsyncIterable
57-
emitter.emitOne({ context: result as Copilot.SupportedContextItem, timeStamp: Date.now(), onTimeout: false });
58+
emitter.emitOne(result as Copilot.SupportedContextItem);
5859
}
5960
}
6061

6162
await Promise.allSettled(providers.map(runProvider));
6263
});
6364

64-
const contextItems = items.map(item => {
65-
const isSnippet = item && typeof item === 'object' && (item as any).uri !== undefined;
66-
if (isSnippet) {
67-
const ctx = item.context as Copilot.CodeSnippet;
68-
return {
69-
kind: ContextKind.Snippet,
70-
priority: this.convertImportanceToPriority(ctx.importance),
71-
uri: URI.parse(ctx.uri),
72-
value: ctx.value
73-
} satisfies SnippetContext;
74-
} else {
75-
const ctx = item.context as Copilot.Trait;
76-
return {
77-
kind: ContextKind.Trait,
78-
priority: this.convertImportanceToPriority(ctx.importance),
79-
name: ctx.name,
80-
value: ctx.value,
81-
} satisfies TraitContext;
82-
}
83-
});
65+
const contextItems = items.map(v => LanguageContextProviderService.convertCopilotContextItem(v));
8466

8567
return contextItems;
8668
}
8769

70+
private static convertCopilotContextItem(item: Copilot.SupportedContextItem): ContextItem {
71+
const isSnippet = item && typeof item === 'object' && (item as any).uri !== undefined;
72+
if (isSnippet) {
73+
const ctx = item as Copilot.CodeSnippet;
74+
return {
75+
kind: ContextKind.Snippet,
76+
priority: LanguageContextProviderService.convertImportanceToPriority(ctx.importance),
77+
uri: URI.parse(ctx.uri),
78+
value: ctx.value
79+
} satisfies SnippetContext;
80+
} else {
81+
const ctx = item as Copilot.Trait;
82+
return {
83+
kind: ContextKind.Trait,
84+
priority: LanguageContextProviderService.convertImportanceToPriority(ctx.importance),
85+
name: ctx.name,
86+
value: ctx.value,
87+
} satisfies TraitContext;
88+
}
89+
}
90+
8891
// importance is coined by the copilot extension and must be an integer in [0, 100], while priority is by the chat extension and spans [0, 1]
89-
private convertImportanceToPriority(importance: number | undefined): number {
92+
private static convertImportanceToPriority(importance: number | undefined): number {
9093
if (importance === undefined || importance < 0) {
9194
return 0;
9295
}
@@ -97,7 +100,15 @@ export class LanguageContextProviderService extends Disposable implements ILangu
97100
}
98101

99102
public getContextItemsOnTimeout(doc: TextDocument, request: Copilot.ResolveRequest): ContextItem[] {
100-
return [];
103+
const providers = this.getContextProviders(doc);
104+
105+
const unprocessedResults = filterMap(providers, p => p.resolver.resolveOnTimeout?.(request));
106+
107+
const copilotCtxItems = unprocessedResults.flat();
108+
109+
const ctxItems = copilotCtxItems.map(v => LanguageContextProviderService.convertCopilotContextItem(v));
110+
111+
return ctxItems;
101112
}
102113

103114
}

0 commit comments

Comments
 (0)