Skip to content

Commit e143515

Browse files
Saulius Menkeviciusrazzmatazz
authored andcommitted
LSP: update OmniSharpCodeHandler so we support codeAction/resolve
This feature was introduced in LSP 3.16.0 https://microsoft.github.io/language-server-protocol/specification#codeAction_resolve and allows us to drop the hack where we were introducing a special "omnisharp/executeCodeAction" command to delay the resolution of code action changesets until user actually selets that code action: see OmniSharp#1814. Related to: - OmniSharp#2068 - OmniSharp#1814
1 parent d52c76d commit e143515

4 files changed

Lines changed: 108 additions & 56 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using OmniSharp.Extensions.LanguageServer.Protocol;
2+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
3+
4+
namespace OmniSharp.LanguageServerProtocol.Handlers
5+
{
6+
internal class CodeActionCommandData
7+
{
8+
public DocumentUri Uri { get; set; }
9+
public string Identifier { get; set; }
10+
public string Name { get; set; }
11+
public Range Range { get; set; }
12+
}
13+
}

src/OmniSharp.LanguageServerProtocol/Handlers/OmniSharpCodeActionHandler.cs

Lines changed: 18 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,51 @@
11
using System.Linq;
22
using System.Collections.Generic;
3-
using System.Diagnostics;
43
using System.Threading;
54
using System.Threading.Tasks;
6-
using MediatR;
7-
using Microsoft.CodeAnalysis;
85
using Newtonsoft.Json.Linq;
96
using OmniSharp.Extensions.JsonRpc;
10-
using OmniSharp.Extensions.LanguageServer.Protocol;
117
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
128
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
139
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
1410
using OmniSharp.Models.V2.CodeActions;
1511
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
16-
using OmniSharp.Extensions.LanguageServer.Protocol.Workspace;
17-
using OmniSharp.Models;
1812
using Diagnostic = OmniSharp.Extensions.LanguageServer.Protocol.Models.Diagnostic;
1913

2014
namespace OmniSharp.LanguageServerProtocol.Handlers
2115
{
22-
internal sealed class OmniSharpCodeActionHandler : CodeActionHandlerBase, IExecuteCommandHandler
16+
internal sealed class OmniSharpCodeActionHandler : CodeActionHandlerBase
2317
{
2418
public static IEnumerable<IJsonRpcHandler> Enumerate(
2519
RequestHandlers handlers,
26-
ISerializer serializer,
2720
ILanguageServer mediator,
2821
DocumentVersions versions)
2922
{
3023
foreach (var (selector, getActionsHandler, runActionHandler) in handlers
3124
.OfType<Mef.IRequestHandler<GetCodeActionsRequest, GetCodeActionsResponse>,
3225
Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse>>())
3326
{
34-
yield return new OmniSharpCodeActionHandler(getActionsHandler, runActionHandler, selector, serializer, mediator, versions);
27+
yield return new OmniSharpCodeActionHandler(getActionsHandler, runActionHandler, selector, mediator, versions);
3528
}
3629
}
3730

3831
private readonly Mef.IRequestHandler<GetCodeActionsRequest, GetCodeActionsResponse> _getActionsHandler;
39-
private readonly ExecuteCommandRegistrationOptions _executeCommandRegistrationOptions;
40-
private ExecuteCommandCapability _executeCommandCapability;
41-
private Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse> _runActionHandler;
32+
private readonly Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse> _runActionHandler;
4233
private readonly DocumentSelector _documentSelector;
43-
private readonly ISerializer _serializer;
4434
private readonly ILanguageServer _server;
4535
private readonly DocumentVersions _documentVersions;
4636

4737
public OmniSharpCodeActionHandler(
4838
Mef.IRequestHandler<GetCodeActionsRequest, GetCodeActionsResponse> getActionsHandler,
4939
Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse> runActionHandler,
5040
DocumentSelector documentSelector,
51-
ISerializer serializer,
5241
ILanguageServer server,
5342
DocumentVersions documentVersions)
5443
{
5544
_getActionsHandler = getActionsHandler;
5645
_runActionHandler = runActionHandler;
5746
_documentSelector = documentSelector;
58-
_serializer = serializer;
5947
_server = server;
6048
_documentVersions = documentVersions;
61-
_executeCommandRegistrationOptions = new ExecuteCommandRegistrationOptions()
62-
{
63-
Commands = new Container<string>("omnisharp/executeCodeAction"),
64-
};
6549
}
6650

6751
public override async Task<CommandOrCodeActionContainer> Handle(CodeActionParams request, CancellationToken cancellationToken)
@@ -93,34 +77,28 @@ public override async Task<CommandOrCodeActionContainer> Handle(CodeActionParams
9377
Title = ca.Name,
9478
Kind = kind,
9579
Diagnostics = new Container<Diagnostic>(),
96-
Edit = new WorkspaceEdit(),
97-
Command = Command.Create("omnisharp/executeCodeAction")
98-
.WithArguments(new CommandData()
80+
Edit = null,
81+
Data = JObject.FromObject(
82+
new CodeActionCommandData()
9983
{
10084
Uri = request.TextDocument.Uri,
10185
Identifier = ca.Identifier,
10286
Name = ca.Name,
10387
Range = request.Range,
10488
})
105-
with { Title = ca.Name }
10689
});
10790
}
10891

10992
return new CommandOrCodeActionContainer(
11093
codeActions.Select(ca => new CommandOrCodeAction(ca)));
11194
}
11295

113-
public override Task<CodeAction> Handle(CodeAction request, CancellationToken cancellationToken)
114-
{
115-
return Task.FromResult(request);
116-
}
117-
118-
public async Task<Unit> Handle(ExecuteCommandParams request, CancellationToken cancellationToken)
96+
public override async Task<CodeAction> Handle(CodeAction request, CancellationToken cancellationToken)
11997
{
120-
Debug.Assert(request.Command == "omnisharp/executeCodeAction");
121-
var data = request.ExtractArguments<CommandData>(_serializer);
98+
var data = request.Data.ToObject<CodeActionCommandData>();
12299

123-
var omnisharpCaRequest = new RunCodeActionRequest {
100+
var omnisharpCaRequest = new RunCodeActionRequest
101+
{
124102
Identifier = data.Identifier,
125103
FileName = data.Uri.GetFileSystemPath(),
126104
Column = data.Range.Start.Character,
@@ -139,33 +117,16 @@ public async Task<Unit> Handle(ExecuteCommandParams request, CancellationToken c
139117
_server.ClientSettings.Capabilities.Workspace!.WorkspaceEdit.Value,
140118
_documentVersions
141119
);
142-
;
143120

144-
await _server.Workspace.ApplyWorkspaceEdit(new ApplyWorkspaceEditParams()
121+
return new CodeAction
145122
{
146-
Label = data.Name,
147-
Edit = edit
148-
}, cancellationToken);
149-
150-
// Do something with response?
151-
//if (response.Applied)
123+
Edit = edit,
124+
};
125+
}
126+
else
127+
{
128+
return new CodeAction();
152129
}
153-
154-
return Unit.Value;
155-
}
156-
157-
class CommandData
158-
{
159-
public DocumentUri Uri { get; set;}
160-
public string Identifier { get; set;}
161-
public string Name { get; set;}
162-
public Range Range { get; set;}
163-
}
164-
165-
ExecuteCommandRegistrationOptions IRegistration<ExecuteCommandRegistrationOptions, ExecuteCommandCapability>.GetRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities)
166-
{
167-
_executeCommandCapability = capability;
168-
return _executeCommandRegistrationOptions;
169130
}
170131

171132
protected override CodeActionRegistrationOptions CreateRegistrationOptions(CodeActionCapability capability, ClientCapabilities clientCapabilities)
@@ -177,6 +138,7 @@ protected override CodeActionRegistrationOptions CreateRegistrationOptions(CodeA
177138
CodeActionKind.SourceOrganizeImports,
178139
CodeActionKind.Refactor,
179140
CodeActionKind.RefactorExtract),
141+
ResolveProvider = true,
180142
};
181143
}
182144
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using OmniSharp.Extensions.JsonRpc;
5+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
6+
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
7+
using OmniSharp.Models.V2.CodeActions;
8+
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
9+
10+
namespace OmniSharp.LanguageServerProtocol.Handlers
11+
{
12+
internal sealed class OmniSharpCodeActionResolveHandler : CodeActionResolveHandlerBase
13+
{
14+
public static IEnumerable<IJsonRpcHandler> Enumerate(
15+
RequestHandlers handlers,
16+
ILanguageServer mediator,
17+
DocumentVersions versions)
18+
{
19+
foreach (var (_, runActionHandler) in handlers
20+
.OfType<Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse>>())
21+
{
22+
yield return new OmniSharpCodeActionResolveHandler(runActionHandler, mediator, versions);
23+
}
24+
}
25+
26+
private readonly Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse> _runActionHandler;
27+
private readonly ILanguageServer _server;
28+
private readonly DocumentVersions _documentVersions;
29+
30+
public OmniSharpCodeActionResolveHandler(
31+
Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse> runActionHandler,
32+
ILanguageServer server,
33+
DocumentVersions documentVersions)
34+
{
35+
_runActionHandler = runActionHandler;
36+
_server = server;
37+
_documentVersions = documentVersions;
38+
}
39+
40+
public override async Task<CodeAction> Handle(CodeAction request, CancellationToken cancellationToken)
41+
{
42+
var data = request.Data.ToObject<CodeActionCommandData>();
43+
44+
var omnisharpCaRequest = new RunCodeActionRequest
45+
{
46+
Identifier = data.Identifier,
47+
FileName = data.Uri.GetFileSystemPath(),
48+
Column = data.Range.Start.Character,
49+
Line = data.Range.Start.Line,
50+
Selection = Helpers.FromRange(data.Range),
51+
ApplyTextChanges = false,
52+
WantsTextChanges = true,
53+
WantsAllCodeActionOperations = true
54+
};
55+
56+
var omnisharpCaResponse = await _runActionHandler.Handle(omnisharpCaRequest);
57+
if (omnisharpCaResponse.Changes != null)
58+
{
59+
var edit = Helpers.ToWorkspaceEdit(
60+
omnisharpCaResponse.Changes,
61+
_server.ClientSettings.Capabilities.Workspace!.WorkspaceEdit.Value,
62+
_documentVersions
63+
);
64+
65+
return new CodeAction
66+
{
67+
Edit = edit,
68+
};
69+
}
70+
else
71+
{
72+
return new CodeAction();
73+
}
74+
}
75+
}
76+
}

src/OmniSharp.LanguageServerProtocol/LanguageServerHost.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ internal static void RegisterHandlers(ILanguageServer server, CompositionHost co
382382
.Concat(OmniSharpImplementationHandler.Enumerate(handlers))
383383
.Concat(OmniSharpCodeLensHandler.Enumerate(handlers))
384384
.Concat(OmniSharpCodeActionHandler.Enumerate(handlers, serializer, server, documentVersions))
385+
.Concat(OmniSharpCodeActionResolveHandler.Enumerate(handlers, serializer, server, documentVersions))
385386
.Concat(OmniSharpDocumentFormattingHandler.Enumerate(handlers))
386387
.Concat(OmniSharpDocumentFormatRangeHandler.Enumerate(handlers))
387388
.Concat(OmniSharpDocumentOnTypeFormattingHandler.Enumerate(handlers)))

0 commit comments

Comments
 (0)