Skip to content

Commit

Permalink
Prototype extension API support
Browse files Browse the repository at this point in the history
Adds a new experimental API to the C# extension that allows other extensions to communicate with the C# language server. This API is not yet finalized and may change in the future. Relates to dotnet/roslyn#68696.
  • Loading branch information
333fred committed Jul 1, 2023
1 parent 8336b18 commit b357805
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 27 deletions.
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
"mocha.enabled": true,
"omnisharp.autoStart": false,
"editor.formatOnSave": false,
"eslint.lintTask.enable": true
}
"eslint.lintTask.enable": true,
"dotnet.defaultSolution": "disable"
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 20 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "csharp",
"publisher": "ms-dotnettools",
"version": "2.0.0-placeholder",
"version": "2.0.261-g1c11b4e4dd",
"description": "Base language support for C#",
"displayName": "C#",
"author": "Microsoft Corporation",
Expand Down Expand Up @@ -866,17 +866,17 @@
"items": {
"type": "string"
},
"description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"description": "Array of symbol server URLs (example: http://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"default": []
},
"searchMicrosoftSymbolServer": {
"type": "boolean",
"description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"searchNuGetOrgSymbolServer": {
"type": "boolean",
"description": "If 'true' the NuGet.org symbol server (https\u200b://symbols.nuget.org\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the NuGet.org symbol server (https://symbols.nuget.org/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"cachePath": {
Expand Down Expand Up @@ -1540,17 +1540,17 @@
"items": {
"type": "string"
},
"description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"description": "Array of symbol server URLs (example: http://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"default": []
},
"csharp.debug.symbolOptions.searchMicrosoftSymbolServer": {
"type": "boolean",
"description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"csharp.debug.symbolOptions.searchNuGetOrgSymbolServer": {
"type": "boolean",
"description": "If 'true' the NuGet.org symbol server (https\u200b://symbols.nuget.org\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the NuGet.org symbol server (https://symbols.nuget.org/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"csharp.debug.symbolOptions.cachePath": {
Expand Down Expand Up @@ -2292,17 +2292,17 @@
"items": {
"type": "string"
},
"description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"description": "Array of symbol server URLs (example: http://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"default": []
},
"searchMicrosoftSymbolServer": {
"type": "boolean",
"description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"searchNuGetOrgSymbolServer": {
"type": "boolean",
"description": "If 'true' the NuGet.org symbol server (https\u200b://symbols.nuget.org\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the NuGet.org symbol server (https://symbols.nuget.org/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"cachePath": {
Expand Down Expand Up @@ -2732,17 +2732,17 @@
"items": {
"type": "string"
},
"description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"description": "Array of symbol server URLs (example: http://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"default": []
},
"searchMicrosoftSymbolServer": {
"type": "boolean",
"description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"searchNuGetOrgSymbolServer": {
"type": "boolean",
"description": "If 'true' the NuGet.org symbol server (https\u200b://symbols.nuget.org\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the NuGet.org symbol server (https://symbols.nuget.org/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"cachePath": {
Expand Down Expand Up @@ -3446,17 +3446,17 @@
"items": {
"type": "string"
},
"description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"description": "Array of symbol server URLs (example: http://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"default": []
},
"searchMicrosoftSymbolServer": {
"type": "boolean",
"description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"searchNuGetOrgSymbolServer": {
"type": "boolean",
"description": "If 'true' the NuGet.org symbol server (https\u200b://symbols.nuget.org\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the NuGet.org symbol server (https://symbols.nuget.org/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"cachePath": {
Expand Down Expand Up @@ -3886,17 +3886,17 @@
"items": {
"type": "string"
},
"description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"description": "Array of symbol server URLs (example: http://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.",
"default": []
},
"searchMicrosoftSymbolServer": {
"type": "boolean",
"description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"searchNuGetOrgSymbolServer": {
"type": "boolean",
"description": "If 'true' the NuGet.org symbol server (https\u200b://symbols.nuget.org\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"description": "If 'true' the NuGet.org symbol server (https://symbols.nuget.org/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.",
"default": false
},
"cachePath": {
Expand Down Expand Up @@ -4888,4 +4888,4 @@
}
]
}
}
}
7 changes: 7 additions & 0 deletions src/csharpExtensionExports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { Advisor } from './features/diagnosticsProvider';
import { EventStream } from './eventStream';
import TestManager from './features/dotnetTest';
import { GlobalBrokeredServiceContainer } from '@microsoft/servicehub-framework';
import { RequestType } from 'vscode-languageclient/node';

export interface OmnisharpExtensionExports {
initializationFinished: () => Promise<void>;
Expand All @@ -20,4 +22,9 @@ export interface CSharpExtensionExports {
initializationFinished: () => Promise<void>;
logDirectory: string;
profferBrokeredServices: (container: GlobalBrokeredServiceContainer) => void;
sendRequest: <Params, Response, Error>(
type: RequestType<Params, Response, Error>,
params: Params,
token: vscode.CancellationToken
) => Promise<Response>;
}
4 changes: 3 additions & 1 deletion src/lsptoolshost/roslynLanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ export async function activateRoslynLanguageServer(
optionProvider: OptionProvider,
outputChannel: vscode.OutputChannel,
reporter: TelemetryReporter
) {
): Promise<RoslynLanguageServer> {
// Create a channel for outputting general logs from the language server.
_channel = outputChannel;
// Create a separate channel for outputting trace logs - these are incredibly verbose and make other logs very difficult to see.
Expand Down Expand Up @@ -624,6 +624,8 @@ export async function activateRoslynLanguageServer(

// Start the language server.
_languageServer.start();

return _languageServer;
}

function getServerPath(options: Options, platformInfo: PlatformInformation) {
Expand Down
33 changes: 33 additions & 0 deletions src/lsptoolshost/roslynLanguageServerExportChannel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { RequestType } from 'vscode-languageclient/node';
import { RoslynLanguageServer } from './roslynLanguageServer';

export class RoslynLanguageServerExport {
private _server: RoslynLanguageServer | undefined;

constructor(private serverPromise: Promise<RoslynLanguageServer>) {}

private async ensureServer(): Promise<RoslynLanguageServer> {
if (this._server === undefined) {
this._server = await this.serverPromise;
}

return this._server;
}

public async sendRequest<Params, Response, Error>(
type: RequestType<Params, Response, Error>,
params: Params,
token: vscode.CancellationToken
): Promise<Response> {
const server = await this.ensureServer();
// We need to recreate the type parameter to ensure that the prototypes line up. The `RequestType` we receive could have been
// from a different version.
const newType = new RequestType<Params, Response, Error>(type.method);
return await server.sendRequest(newType, params, token);
}
}
13 changes: 11 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ import { installRuntimeDependencies } from './installRuntimeDependencies';
import { isValidDownload } from './packageManager/isValidDownload';
import { BackgroundWorkStatusBarObserver } from './observers/backgroundWorkStatusBarObserver';
import { getDotnetPackApi } from './dotnetPack';
import { SolutionSnapshotProvider, activateRoslynLanguageServer } from './lsptoolshost/roslynLanguageServer';
import {
RoslynLanguageServer,
SolutionSnapshotProvider,
activateRoslynLanguageServer,
} from './lsptoolshost/roslynLanguageServer';
import { Options } from './shared/options';
import { MigrateOptions } from './shared/migrateOptions';
import { getBrokeredServiceContainer } from './lsptoolshost/services/brokeredServicesHosting';
Expand All @@ -51,6 +55,7 @@ import Descriptors from './lsptoolshost/services/descriptors';
import { GlobalBrokeredServiceContainer } from '@microsoft/servicehub-framework';
import { CSharpExtensionExports, OmnisharpExtensionExports } from './csharpExtensionExports';
import { csharpDevkitExtensionId, getCSharpDevKit } from './utils/getCSharpDevKit';
import { RoslynLanguageServerExport } from './lsptoolshost/roslynLanguageServerExportChannel';

export async function activate(
context: vscode.ExtensionContext
Expand Down Expand Up @@ -114,7 +119,7 @@ export async function activate(

let omnisharpLangServicePromise: Promise<OmniSharp.ActivationResult> | undefined = undefined;
let omnisharpRazorPromise: Promise<void> | undefined = undefined;
let roslynLanguageServerPromise: Promise<void> | undefined = undefined;
let roslynLanguageServerPromise: Promise<RoslynLanguageServer> | undefined = undefined;

if (!useOmnisharpServer) {
// Activate Razor. Needs to be activated before Roslyn so commands are registered in the correct order.
Expand Down Expand Up @@ -281,13 +286,17 @@ export async function activate(
if (!useOmnisharpServer) {
tryGetCSharpDevKitExtensionExports(csharpLogObserver);

const languageServerExport = new RoslynLanguageServerExport(
<Promise<RoslynLanguageServer>>roslynLanguageServerPromise
);
return {
initializationFinished: async () => {
await coreClrDebugPromise;
await roslynLanguageServerPromise;
},
profferBrokeredServices: (container) => profferBrokeredServices(context, container),
logDirectory: context.logUri.fsPath,
sendRequest: async (t, p, ct) => await languageServerExport.sendRequest(t, p, ct),
};
} else {
return {
Expand Down

0 comments on commit b357805

Please sign in to comment.