Skip to content

Commit a019e93

Browse files
committed
Fix
1 parent fbdf735 commit a019e93

File tree

7 files changed

+138
-134
lines changed

7 files changed

+138
-134
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
"ms-dotnettools.vscode-dotnet-runtime"
8888
],
8989
"dependencies": {
90-
"@github/copilot-language-server": "1.262.0",
90+
"@github/copilot-language-server": "1.262.0",
9191
"@microsoft/servicehub-framework": "4.2.99-beta",
9292
"@octokit/rest": "^20.0.1",
9393
"@types/cross-spawn": "6.0.2",

src/csharpDevKitExports.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export interface CSharpDevKitExports {
1414
hasServerProcessLoaded: () => boolean;
1515
serverProcessLoaded: vscode.Event<void>;
1616
setupTelemetryEnvironmentAsync: (env: NodeJS.ProcessEnv) => Promise<string | undefined>;
17+
copilotCapabilities?: Map<string, string>;
1718
}

src/lsptoolshost/activate.ts

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ import { TelemetryEventNames } from '../shared/telemetryEventNames';
2727
import { WorkspaceStatus } from './workspace/workspaceStatus';
2828
import { ProjectContextStatus } from './projectContext/projectContextStatus';
2929
import { RoslynLanguageServer } from './server/roslynLanguageServer';
30-
import { registerCopilotExtensions } from './copilot/copilot';
30+
import { registerCopilotRelatedFilesProvider } from './copilot/relatedFilesProvider';
31+
import { registerCopilotContextProviders } from './copilot/contextProviders';
3132

3233
let _channel: vscode.LogOutputChannel;
3334
let _traceChannel: vscode.OutputChannel;
@@ -59,22 +60,22 @@ export async function activateRoslynLanguageServer(
5960
context.extensionPath
6061
);
6162
const additionalExtensionPaths = scanExtensionPlugins();
62-
const copilotExtensionPath = getCopilotPluginPath();
6363

6464
const languageServer = await RoslynLanguageServer.initializeAsync(
6565
platformInfo,
6666
hostExecutableResolver,
6767
context,
6868
reporter,
69-
additionalExtensionPaths.concat(copilotExtensionPath ? [copilotExtensionPath] : []),
69+
additionalExtensionPaths,
7070
languageServerEvents,
7171
_channel,
7272
_traceChannel
7373
);
7474

7575
registerLanguageStatusItems(context, languageServer, languageServerEvents);
7676
registerMiscellaneousFileNotifier(context, languageServer);
77-
registerCopilotExtensions(context, languageServer, copilotExtensionPath, _channel);
77+
registerCopilotRelatedFilesProvider(context, languageServer, _channel);
78+
registerCopilotContextProviders(context, languageServer, _channel);
7879

7980
// Register any commands that need to be handled by the extension.
8081
registerCommands(context, languageServer, hostExecutableResolver, _channel);
@@ -118,16 +119,6 @@ export async function activateRoslynLanguageServer(
118119
const extensionsFromOptions = languageServerOptions.extensionsPaths ?? [];
119120
return extensionsFromPackageJson.concat(extensionsFromOptions);
120121
}
121-
122-
function getCopilotPluginPath(): string | undefined {
123-
const copilotLoadPath = getCSharpDevKit()?.packageJSON.contributes?.['csharpCopilotExtensionLoadPath'];
124-
if (copilotLoadPath) {
125-
_channel.trace(`CSharp DevKit contributes csharpCopilotExtensionLoadPath: ${copilotLoadPath}`);
126-
return path.join(getCSharpDevKit()!.extensionPath, copilotLoadPath);
127-
}
128-
129-
return undefined;
130-
}
131122
}
132123

133124
function registerLanguageStatusItems(

src/lsptoolshost/copilot/contextProviders.ts

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as vscode from 'vscode';
77
import * as lsp from 'vscode-languageserver-protocol';
88
import { RoslynLanguageServer } from '../server/roslynLanguageServer';
99
import { CSharpExtensionId } from '../../constants/csharpExtensionId';
10+
import { getCSharpDevKit } from '../../utils/getCSharpDevKit';
1011

1112
export interface DocumentContext {
1213
textDocument: lsp.TextDocumentIdentifier;
@@ -20,8 +21,10 @@ export interface ContextResolveParam {
2021
data?: any;
2122
}
2223

24+
const resolveContextMethodName = 'roslyn/resolveContext';
25+
const resolveContextMethodSupportedVersion = '1';
2326
const resolveContextRequest = new lsp.RequestType<ContextResolveParam, SupportedContextItem[], void>(
24-
'roslyn/resolveContext',
27+
resolveContextMethodName,
2528
lsp.ParameterStructures.auto
2629
);
2730

@@ -55,35 +58,63 @@ function createContextResolveParam(request: ResolveRequest): ContextResolveParam
5558
return contextResolveParam;
5659
}
5760

58-
export async function registerCopilotContextProviders(
59-
copilotExt: CopilotApi | undefined,
61+
export function registerCopilotContextProviders(
6062
context: vscode.ExtensionContext,
6163
languageServer: RoslynLanguageServer,
6264
channel: vscode.LogOutputChannel
6365
) {
64-
const contextProviderApi = await copilotExt?.getContextProviderAPI('v1');
65-
66-
if (!contextProviderApi) {
67-
channel.debug('Incompatible GitHub Copilot extension installed. Skip registeration of C# context providers.');
66+
const copilotApi = vscode.extensions.getExtension<CopilotApi>('github.copilot');
67+
if (!copilotApi) {
68+
channel.debug(
69+
'Failed to find comnpatible version of GitHub Copilot extension installed. Skip registeration of Copilot context provider.'
70+
);
6871
return;
6972
}
7073

71-
context.subscriptions.push(
72-
contextProviderApi.registerContextProvider<SupportedContextItem>({
73-
id: CSharpExtensionId, // use extension id as provider id for now
74-
selector: [{ language: 'csharp' }],
75-
resolver: {
76-
resolve: async (request, token) => {
77-
const contextResolveParam = createContextResolveParam(request);
78-
if (!contextResolveParam) {
79-
return [];
80-
}
81-
const traits = await languageServer.sendRequest(resolveContextRequest, contextResolveParam, token);
82-
return traits;
83-
},
84-
},
85-
})
86-
);
74+
copilotApi.activate().then(async (api) => {
75+
try {
76+
const contextProviderApi = await api.getContextProviderAPI('v1');
77+
78+
if (!contextProviderApi) {
79+
channel.debug(
80+
'Incompatible GitHub Copilot extension installed. Skip registeration of C# context providers.'
81+
);
82+
return;
83+
}
84+
85+
const devkitExports = await getCSharpDevKit()?.activate();
86+
const contextResolveVersion = devkitExports?.copilotCapabilities?.get(resolveContextMethodName);
87+
if (contextResolveVersion === undefined || contextResolveVersion !== resolveContextMethodSupportedVersion) {
88+
channel.debug(
89+
'Unsupported resolveContext method version. Skip registration of Copilot context provider.'
90+
);
91+
return;
92+
}
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 traits = await languageServer.sendRequest(
105+
resolveContextRequest,
106+
contextResolveParam,
107+
token
108+
);
109+
return traits;
110+
},
111+
},
112+
})
113+
);
87114

88-
channel.debug('Registration of C# context provider for GitHub Copilot extension succeeded.');
115+
channel.debug('Registration of C# context provider for GitHub Copilot extension succeeded.');
116+
} catch (error) {
117+
channel.error('Failed to register Copilot context providers', error);
118+
}
119+
});
89120
}

src/lsptoolshost/copilot/copilot.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/lsptoolshost/copilot/relatedFilesProvider.ts

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -28,71 +28,77 @@ interface CopilotRelatedFilesProviderRegistration {
2828
): vscode.Disposable;
2929
}
3030

31-
export async function registerCopilotRelatedFilesProvider(
32-
copilotExt: CopilotRelatedFilesProviderRegistration | undefined,
31+
export function registerCopilotRelatedFilesProvider(
3332
context: vscode.ExtensionContext,
3433
languageServer: RoslynLanguageServer,
3534
channel: vscode.LogOutputChannel
3635
) {
37-
if (!copilotExt) {
36+
const copilotApi = vscode.extensions.getExtension<CopilotRelatedFilesProviderRegistration>('github.copilot');
37+
if (!copilotApi) {
3838
channel.debug(
39-
'Incompatible GitHub Copilot extension installed. Skip registeration of C# related files provider.'
39+
'Failed to find comnpatible version of GitHub Copilot extension installed. Skip registeration of Copilot related files provider.'
4040
);
4141
return;
4242
}
4343

44-
const id = {
45-
extensionId: CSharpExtensionId,
46-
languageId: 'csharp',
47-
};
44+
copilotApi.activate().then(async (api) => {
45+
try {
46+
const id = {
47+
extensionId: CSharpExtensionId,
48+
languageId: 'csharp',
49+
};
4850

49-
context.subscriptions.push(
50-
copilotExt.registerRelatedFilesProvider(id, async (uri, _, token) => {
51-
const buildResult = (
52-
activeDocumentUri: vscode.Uri,
53-
reports: CopilotRelatedDocumentsReport[],
54-
builder: vscode.Uri[]
55-
) => {
56-
if (reports) {
57-
for (const report of reports) {
58-
if (report._vs_file_paths) {
59-
for (const filePath of report._vs_file_paths) {
60-
// The Roslyn related document service would return the active document as related file to itself
61-
// if the code contains reference to the types defined in the same document. Skip it so the active file
62-
// won't be used as additonal context.
63-
const relatedUri = vscode.Uri.file(filePath);
64-
if (relatedUri.fsPath !== activeDocumentUri.fsPath) {
65-
builder.push(relatedUri);
51+
context.subscriptions.push(
52+
api.registerRelatedFilesProvider(id, async (uri, _, token) => {
53+
const buildResult = (
54+
activeDocumentUri: vscode.Uri,
55+
reports: CopilotRelatedDocumentsReport[],
56+
builder: vscode.Uri[]
57+
) => {
58+
if (reports) {
59+
for (const report of reports) {
60+
if (report._vs_file_paths) {
61+
for (const filePath of report._vs_file_paths) {
62+
// The Roslyn related document service would return the active document as related file to itself
63+
// if the code contains reference to the types defined in the same document. Skip it so the active file
64+
// won't be used as additonal context.
65+
const relatedUri = vscode.Uri.file(filePath);
66+
if (relatedUri.fsPath !== activeDocumentUri.fsPath) {
67+
builder.push(relatedUri);
68+
}
69+
}
6670
}
6771
}
6872
}
73+
};
74+
const relatedFiles: vscode.Uri[] = [];
75+
const uriString = UriConverter.serialize(uri);
76+
const textDocument = TextDocumentIdentifier.create(uriString);
77+
try {
78+
await languageServer.sendRequestWithProgress(
79+
CopilotRelatedDocumentsRequest.type,
80+
{
81+
_vs_textDocument: textDocument,
82+
position: {
83+
line: 0,
84+
character: 0,
85+
},
86+
},
87+
async (r) => buildResult(uri, r, relatedFiles),
88+
token
89+
);
90+
} catch (e) {
91+
if (e instanceof Error) {
92+
channel.appendLine(e.message);
93+
}
6994
}
70-
}
71-
};
72-
const relatedFiles: vscode.Uri[] = [];
73-
const uriString = UriConverter.serialize(uri);
74-
const textDocument = TextDocumentIdentifier.create(uriString);
75-
try {
76-
await languageServer.sendRequestWithProgress(
77-
CopilotRelatedDocumentsRequest.type,
78-
{
79-
_vs_textDocument: textDocument,
80-
position: {
81-
line: 0,
82-
character: 0,
83-
},
84-
},
85-
async (r) => buildResult(uri, r, relatedFiles),
86-
token
87-
);
88-
} catch (e) {
89-
if (e instanceof Error) {
90-
channel.appendLine(e.message);
91-
}
92-
}
93-
return { entries: relatedFiles };
94-
})
95-
);
95+
return { entries: relatedFiles };
96+
})
97+
);
9698

97-
channel.debug('Registration of C# related files provider for GitHub Copilot extension succeeded.');
99+
channel.debug('Registration of C# related files provider for GitHub Copilot extension succeeded.');
100+
} catch (error) {
101+
channel.error('Failed to register Copilot related files providers', error);
102+
}
103+
});
98104
}

src/lsptoolshost/server/roslynLanguageServer.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ export class RoslynLanguageServer {
644644
const csharpDevKitArgs = this.getCSharpDevKitExportArgs(additionalExtensionPaths);
645645
args = args.concat(csharpDevKitArgs);
646646

647-
await this.setupDevKitEnvironment(dotnetInfo.env, csharpDevkitExtension);
647+
await this.setupDevKitEnvironment(dotnetInfo.env, csharpDevkitExtension, additionalExtensionPaths, channel);
648648
} else {
649649
// C# Dev Kit is not installed - continue C#-only activation.
650650
channel.info('Activating C# standalone...');
@@ -1016,17 +1016,30 @@ export class RoslynLanguageServer {
10161016

10171017
private static async setupDevKitEnvironment(
10181018
env: NodeJS.ProcessEnv,
1019-
csharpDevkitExtension: vscode.Extension<CSharpDevKitExports>
1019+
csharpDevkitExtension: vscode.Extension<CSharpDevKitExports>,
1020+
additionalExtensionPaths: string[],
1021+
channel: vscode.LogOutputChannel
10201022
): Promise<void> {
10211023
const exports: CSharpDevKitExports = await csharpDevkitExtension.activate();
10221024

10231025
// setupTelemetryEnvironmentAsync was a later addition to devkit (not in preview 1)
10241026
// so it may not exist in whatever version of devkit the user has installed
1025-
if (!exports.setupTelemetryEnvironmentAsync) {
1026-
return;
1027+
if (exports.setupTelemetryEnvironmentAsync) {
1028+
await exports.setupTelemetryEnvironmentAsync(env);
10271029
}
10281030

1029-
await exports.setupTelemetryEnvironmentAsync(env);
1031+
const copilotServerExtensionfolder =
1032+
exports.components['@microsoft/visualstudio.copilot.roslyn.languageserver'];
1033+
if (copilotServerExtensionfolder) {
1034+
const copilotServerExtensionFullPath = path.join(
1035+
copilotServerExtensionfolder,
1036+
'Microsoft.VisualStudio.Copilot.Roslyn.LanguageServer.dll'
1037+
);
1038+
additionalExtensionPaths.push(copilotServerExtensionFullPath);
1039+
channel.trace(
1040+
`CSharp DevKit contributes csharpCopilotExtensionLoadPath: ${copilotServerExtensionFullPath}`
1041+
);
1042+
}
10301043
}
10311044

10321045
/**

0 commit comments

Comments
 (0)