@@ -7,6 +7,7 @@ import { type CancellationToken, languages, type TextDocument, type Disposable a
7
7
import { Copilot } from '../../../platform/inlineCompletions/common/api' ;
8
8
import { ILanguageContextProviderService } from '../../../platform/languageContextProvider/common/languageContextProviderService' ;
9
9
import { ContextItem , ContextKind , SnippetContext , TraitContext } from '../../../platform/languageServer/common/languageContextService' ;
10
+ import { filterMap } from '../../../util/common/arrays' ;
10
11
import { AsyncIterableObject } from '../../../util/vs/base/common/async' ;
11
12
import { Disposable , toDisposable } from '../../../util/vs/base/common/lifecycle' ;
12
13
import { URI } from '../../../util/vs/base/common/uri' ;
@@ -38,55 +39,57 @@ export class LanguageContextProviderService extends Disposable implements ILangu
38
39
public getContextItems ( doc : TextDocument , request : Copilot . ResolveRequest , cancellationToken : CancellationToken ) : AsyncIterable < ContextItem > {
39
40
const providers = this . getContextProviders ( doc ) ;
40
41
41
- const items = new AsyncIterableObject < { context : Copilot . SupportedContextItem ; timeStamp : number ; onTimeout : boolean } > ( async emitter => {
42
+ const items = new AsyncIterableObject < Copilot . SupportedContextItem > ( async emitter => {
42
43
async function runProvider ( provider : Copilot . ContextProvider < Copilot . SupportedContextItem > ) {
43
44
const langCtx = provider . resolver . resolve ( request , cancellationToken ) ;
44
45
if ( typeof ( langCtx as any ) [ Symbol . asyncIterator ] === 'function' ) {
45
46
for await ( const context of langCtx as AsyncIterable < Copilot . SupportedContextItem > ) {
46
- emitter . emitOne ( { context, timeStamp : Date . now ( ) , onTimeout : false } ) ;
47
+ emitter . emitOne ( context ) ;
47
48
}
48
49
return ;
49
50
}
50
51
const result = await langCtx ;
51
52
if ( Array . isArray ( result ) ) {
52
53
for ( const context of result ) {
53
- emitter . emitOne ( { context, timeStamp : Date . now ( ) , onTimeout : false } ) ;
54
+ emitter . emitOne ( context ) ;
54
55
}
55
56
} else if ( typeof ( result as any ) [ Symbol . asyncIterator ] !== 'function' ) {
56
57
// 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 ) ;
58
59
}
59
60
}
60
61
61
62
await Promise . allSettled ( providers . map ( runProvider ) ) ;
62
63
} ) ;
63
64
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 ) ) ;
84
66
85
67
return contextItems ;
86
68
}
87
69
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
+
88
91
// 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 {
90
93
if ( importance === undefined || importance < 0 ) {
91
94
return 0 ;
92
95
}
@@ -97,7 +100,15 @@ export class LanguageContextProviderService extends Disposable implements ILangu
97
100
}
98
101
99
102
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 ;
101
112
}
102
113
103
114
}
0 commit comments