dotnet / dotnet/roslyn

Add experimental gladstone APIs for accessing Roslyn solutions

Open
#85,236 4 comments 0 reactions 0 assignees View on GitHub
api-ready-for-review Area-IDE Concept-API Feature Request
Dominant language
C#
Stars
20.7k
Forks
4.3k
PR merge metrics
PR metrics pending

Description

## Background and Motivation

Visual Studio Gladstone extensibility wants to add support for allowing extension authors to interact with the C# syntax / symbol model. Currently there is no public API to do this.

With this proposal, gladstone extensions can author 'handlers' that run inside the Roslyn DevHub context. The handlers are given access to a `Solution` / `Document` instance that they can read. Modifications are not supported through this API.

Gladstone extensibility will own the extension APIs required to dispatch messages to Roslyn. It will dispatch LSP messages to Roslyn, which Roslyn LSP will in turn re-direct to the specific handler in DevHub. This however is an implementation detail and not exposed to extension authors.

An initial prototype was developed and currently live in `Microsoft.CodeAnalysis.ExternalAccess.Extensions`. The Gladstone team want to make these available as experimental APIs. This proposal moves the contracts to `Microsoft.CodeAnalysis.Workspaces.dll`, which already owns the `Solution` and `Document` types used by the API. The LSP types and Roslyn-Gladstone bridge remain in EA.

Prototype: https://github.com/dotnet/roslyn/issues/85209

## Proposed API
Assembly: `Microsoft.CodeAnalysis.Workspaces.dll`

Diff
```
namespace Microsoft.CodeAnalysis.Extensions
{
+ [Experimental("RSEXPERIMENTAL008")]
+ public sealed class ExtensionMessageContext
+ {
+ public Solution Solution { get; }
+ }
+
+ [Experimental("RSEXPERIMENTAL008")]
+ public interface IExtensionWorkspaceMessageHandler
+ {
+ Task ExecuteAsync(
+ TMessage message,
+ ExtensionMessageContext context,
+ CancellationToken cancellationToken);
+ }
+
+ [Experimental("RSEXPERIMENTAL008")]
+ public interface IExtensionDocumentMessageHandler
+ {
+ Task ExecuteAsync(
+ TMessage message,
+ ExtensionMessageContext context,
+ Document document,
+ CancellationToken cancellationToken);
+ }
}

```

`ExtensionMessageContext` is created by Roslyn and has no public constructor. `TMessage` and `TResponse` are serialized using `System.Text.Json`.

## Usage Example

C#
```
#pragma warning disable RSEXPERIMENTAL008

public sealed record HasTypeRequest(string MetadataName);
public sealed record HasTypeResponse(bool Found);

public sealed class HasTypeHandler
: IExtensionWorkspaceMessageHandler
{
public async Task ExecuteAsync(
HasTypeRequest message,
ExtensionMessageContext context,
CancellationToken cancellationToken)
{
foreach (var project in context.Solution.Projects)
{
var compilation =
await project.GetCompilationAsync(cancellationToken);

if (compilation?.GetTypeByMetadataName(message.MetadataName) is not null)
return new(true);
}

return new(false);
}
}

```

Document handlers follow the same model but additionally receive the target `Document`.

## Alternative Designs

### Use standard LSP message handlers

Extensions could expose custom LSP methods and implement Roslyn LSP request handlers directly.

This was rejected because Roslyn’s normal LSP handler model is composed when the server starts and does not support dynamically loading and unloading extension assemblies. It would also expose LSP method names, JSON-RPC payloads, and transport lifecycle details as part of the extension-author contract.

Extension authors only need a typed request/response handler abstraction. The proposed API keeps LSP as a private transport detail while allowing Gladstone to activate and hot-load extension handlers at runtime.

## Risks

No one has ever implemented this API when it was in external access. We do not know if the API shape matches exactly what people would want, hence being experimental.

To my knowledge, the API support has been smoke tested, but not comprehensively tested since it was implemented.

Contributor guide

Open the contributing guide

Research direction

Start by comparing the prototype in Microsoft.CodeAnalysis.ExternalAccess.Extensions with the proposed contracts in issue #85209, then locate the Workspaces project that produces Microsoft.CodeAnalysis.Workspaces.dll. Verify the three experimental interfaces and context match the proposal, and check the existing smoke-test coverage before determining what additional validation is needed.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.