|
2 | 2 | * Copyright (c) Microsoft Corporation. All rights reserved. |
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information. |
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | | -import { ContextProviderApiV1, ResolveRequest, SupportedContextItem } from '@github/copilot-language-server'; |
| 5 | +import { |
| 6 | + ContextProviderApiV1, |
| 7 | + ResolveRequest, |
| 8 | + SupportedContextItem, |
| 9 | + type ContextProvider, |
| 10 | +} from '@github/copilot-language-server'; |
6 | 11 | import * as vscode from 'vscode'; |
7 | 12 | import * as lsp from 'vscode-languageserver-protocol'; |
8 | 13 | import { RoslynLanguageServer } from '../server/roslynLanguageServer'; |
@@ -73,49 +78,105 @@ export function registerCopilotContextProviders( |
73 | 78 |
|
74 | 79 | devkit.activate().then(async () => { |
75 | 80 | try { |
76 | | - const copilotApi = vscode.extensions.getExtension<CopilotApi>('github.copilot'); |
77 | | - if (!copilotApi) { |
| 81 | + const copilotClientApi = await getCopilotClientApi(); |
| 82 | + const copilotChatApi = await getCopilotChatApi(); |
| 83 | + if (!copilotClientApi && !copilotChatApi) { |
78 | 84 | channel.debug( |
79 | | - 'Failed to find compatible version of GitHub Copilot extension installed. Skip registeration of Copilot context provider.' |
| 85 | + 'Failed to find compatible version of GitHub Copilot extension installed. Skip registration of Copilot context provider.' |
80 | 86 | ); |
81 | 87 | return; |
82 | 88 | } |
83 | 89 |
|
84 | | - const api = await copilotApi.activate(); |
85 | | - const contextProviderApi = await api.getContextProviderAPI('v1'); |
| 90 | + const provider: ContextProvider<SupportedContextItem> = { |
| 91 | + id: CSharpExtensionId, // use extension id as provider id for now |
| 92 | + selector: [{ language: 'csharp' }], |
| 93 | + resolver: { |
| 94 | + resolve: async (request, token) => { |
| 95 | + const contextResolveParam = createContextResolveParam(request); |
| 96 | + if (!contextResolveParam) { |
| 97 | + return []; |
| 98 | + } |
| 99 | + const items = await languageServer.sendRequest( |
| 100 | + resolveContextRequest, |
| 101 | + contextResolveParam, |
| 102 | + token |
| 103 | + ); |
| 104 | + channel.trace(`Copilot context provider resolved ${items.length} items`); |
| 105 | + return items; |
| 106 | + }, |
| 107 | + }, |
| 108 | + }; |
| 109 | + |
| 110 | + let installCount = 0; |
| 111 | + if (copilotClientApi) { |
| 112 | + const disposable = await installContextProvider(copilotClientApi, provider); |
| 113 | + if (disposable) { |
| 114 | + context.subscriptions.push(disposable); |
| 115 | + installCount++; |
| 116 | + } |
| 117 | + } |
| 118 | + if (copilotChatApi) { |
| 119 | + const disposable = await installContextProvider(copilotChatApi, provider); |
| 120 | + if (disposable) { |
| 121 | + context.subscriptions.push(disposable); |
| 122 | + installCount++; |
| 123 | + } |
| 124 | + } |
86 | 125 |
|
87 | | - if (!contextProviderApi) { |
| 126 | + if (installCount === 0) { |
88 | 127 | channel.debug( |
89 | | - 'Incompatible GitHub Copilot extension installed. Skip registeration of C# context providers.' |
| 128 | + 'Incompatible GitHub Copilot extension installed. Skip registration of C# context providers.' |
90 | 129 | ); |
91 | 130 | return; |
92 | 131 | } |
93 | | - |
94 | | - context.subscriptions.push( |
95 | | - contextProviderApi.registerContextProvider<SupportedContextItem>({ |
96 | | - id: CSharpExtensionId, // use extension id as provider id for now |
97 | | - selector: [{ language: 'csharp' }], |
98 | | - resolver: { |
99 | | - resolve: async (request, token) => { |
100 | | - const contextResolveParam = createContextResolveParam(request); |
101 | | - if (!contextResolveParam) { |
102 | | - return []; |
103 | | - } |
104 | | - const items = await languageServer.sendRequest( |
105 | | - resolveContextRequest, |
106 | | - contextResolveParam, |
107 | | - token |
108 | | - ); |
109 | | - channel.trace(`Copilot context provider resolved ${items.length} items`); |
110 | | - return items; |
111 | | - }, |
112 | | - }, |
113 | | - }) |
114 | | - ); |
115 | | - |
116 | 132 | channel.debug('Registration of C# context provider for GitHub Copilot extension succeeded.'); |
117 | 133 | } catch (error) { |
118 | 134 | channel.error('Failed to register Copilot context providers', error); |
119 | 135 | } |
120 | 136 | }); |
121 | 137 | } |
| 138 | + |
| 139 | +async function getCopilotClientApi(): Promise<CopilotApi | undefined> { |
| 140 | + const extension = vscode.extensions.getExtension<CopilotApi>('github.copilot'); |
| 141 | + if (!extension) { |
| 142 | + return undefined; |
| 143 | + } |
| 144 | + try { |
| 145 | + return await extension.activate(); |
| 146 | + } catch { |
| 147 | + return undefined; |
| 148 | + } |
| 149 | +} |
| 150 | + |
| 151 | +async function getCopilotChatApi(): Promise<CopilotApi | undefined> { |
| 152 | + type CopilotChatApi = { getAPI?(version: number): CopilotApi | undefined }; |
| 153 | + const extension = vscode.extensions.getExtension<CopilotChatApi>('github.copilot-chat'); |
| 154 | + if (!extension) { |
| 155 | + return undefined; |
| 156 | + } |
| 157 | + |
| 158 | + let exports: CopilotChatApi | undefined; |
| 159 | + try { |
| 160 | + exports = await extension.activate(); |
| 161 | + } catch { |
| 162 | + return undefined; |
| 163 | + } |
| 164 | + if (!exports || typeof exports.getAPI !== 'function') { |
| 165 | + return undefined; |
| 166 | + } |
| 167 | + return exports.getAPI(1); |
| 168 | +} |
| 169 | + |
| 170 | +async function installContextProvider( |
| 171 | + copilotAPI: CopilotApi, |
| 172 | + contextProvider: ContextProvider<SupportedContextItem> |
| 173 | +): Promise<vscode.Disposable | undefined> { |
| 174 | + const hasGetContextProviderAPI = typeof copilotAPI.getContextProviderAPI === 'function'; |
| 175 | + if (hasGetContextProviderAPI) { |
| 176 | + const contextAPI = await copilotAPI.getContextProviderAPI('v1'); |
| 177 | + if (contextAPI) { |
| 178 | + return contextAPI.registerContextProvider(contextProvider); |
| 179 | + } |
| 180 | + } |
| 181 | + return undefined; |
| 182 | +} |
0 commit comments