Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LSP: wire up handler for codeAction #1795

Merged
merged 4 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Changelog
All changes to the project will be documented in this file.

## [1.35.3] - Not yet released
## [1.35.3] - not yet released
* Added LSP handler for `textDocument/codeAction` request. (PR: [#1795](https://github.com/OmniSharp/omnisharp-roslyn/pull/1795))

## [1.35.2] - 2020-05-20
* Added support for `WarningsAsErrors` in csproj files (PR: [#1779](https://github.com/OmniSharp/omnisharp-roslyn/pull/1779))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
using OmniSharp.Models;
using OmniSharp.Models.V2.CodeActions;

namespace OmniSharp.LanguageServerProtocol.Handlers
{
internal sealed class OmniSharpCodeActionHandler: CodeActionHandler
{
public static IEnumerable<IJsonRpcHandler> Enumerate(RequestHandlers handlers)
{
foreach (var (selector, getActionsHandler, runActionHandler) in handlers
.OfType<Mef.IRequestHandler<GetCodeActionsRequest, GetCodeActionsResponse>,
Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse>>())
{
yield return new OmniSharpCodeActionHandler(getActionsHandler, runActionHandler, selector);
}
}

private readonly Mef.IRequestHandler<GetCodeActionsRequest, GetCodeActionsResponse> _getActionsHandler;
private readonly Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse> _runActionHandler;

public OmniSharpCodeActionHandler(
Mef.IRequestHandler<GetCodeActionsRequest, GetCodeActionsResponse> getActionsHandler,
Mef.IRequestHandler<RunCodeActionRequest, RunCodeActionResponse> runActionHandler,
DocumentSelector documentSelector)
: base(new CodeActionRegistrationOptions()
{
DocumentSelector = documentSelector,
CodeActionKinds = new Container<CodeActionKind>(
CodeActionKind.SourceOrganizeImports,
CodeActionKind.Refactor,
CodeActionKind.RefactorExtract),
})
{
_getActionsHandler = getActionsHandler;
_runActionHandler = runActionHandler;
}

public async override Task<CommandOrCodeActionContainer> Handle(CodeActionParams request, CancellationToken cancellationToken)
{
var omnisharpRequest = new GetCodeActionsRequest {
FileName = Helpers.FromUri(request.TextDocument.Uri),
Column = (int)request.Range.Start.Character,
Line = (int)request.Range.Start.Line,
Selection = Helpers.FromRange(request.Range),
};

var omnisharpResponse = await _getActionsHandler.Handle(omnisharpRequest);

var codeActions = new List<CodeAction>();

foreach (var ca in omnisharpResponse.CodeActions)
{
var omnisharpCaRequest = new RunCodeActionRequest {
Identifier = ca.Identifier,
FileName = Helpers.FromUri(request.TextDocument.Uri),
Column = Convert.ToInt32(request.Range.Start.Character),
Line = Convert.ToInt32(request.Range.Start.Line),
Selection = Helpers.FromRange(request.Range),
ApplyTextChanges = false,
WantsTextChanges = true,
};

var omnisharpCaResponse = await _runActionHandler.Handle(omnisharpCaRequest);

var changes = omnisharpCaResponse.Changes.ToDictionary(
x => Helpers.ToUri(x.FileName),
x => ((ModifiedFileResponse)x).Changes.Select(edit => new TextEdit
{
NewText = edit.NewText,
Range = Helpers.ToRange((edit.StartColumn, edit.StartLine), (edit.EndColumn, edit.EndLine))
}));

CodeActionKind kind;
if (ca.Identifier.StartsWith("using ")) { kind = CodeActionKind.SourceOrganizeImports; }
else if (ca.Identifier.StartsWith("Inline ")) { kind = CodeActionKind.RefactorInline; }
else if (ca.Identifier.StartsWith("Extract ")) { kind = CodeActionKind.RefactorExtract; }
else if (ca.Identifier.StartsWith("Change ")) { kind = CodeActionKind.QuickFix; }
else { kind = CodeActionKind.Refactor; }

codeActions.Add(
new CodeAction {
Title = ca.Name,
Kind = kind,
Diagnostics = new Container<Diagnostic>(),
Edit = new WorkspaceEdit { Changes = changes, }
});
}

return new CommandOrCodeActionContainer(
codeActions.Select(ca => new CommandOrCodeAction(ca)));
}
}
}
17 changes: 17 additions & 0 deletions src/OmniSharp.LanguageServerProtocol/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ public static Range ToRange(this QuickFix location)
};
}

public static OmniSharp.Models.V2.Range FromRange(Range range)
{
return new OmniSharp.Models.V2.Range
{
Start = new OmniSharp.Models.V2.Point
{
Column = Convert.ToInt32(range.Start.Character),
Line = Convert.ToInt32(range.Start.Line),
},
End = new OmniSharp.Models.V2.Point
{
Column = Convert.ToInt32(range.End.Character),
Line = Convert.ToInt32(range.End.Line),
},
};
}

public static DiagnosticSeverity ToDiagnosticSeverity(string logLevel)
{
// We stringify this value and pass to clients
Expand Down
1 change: 1 addition & 0 deletions src/OmniSharp.LanguageServerProtocol/LanguageServerHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ private Task Initialize(Extensions.LanguageServer.Server.ILanguageServer server,
.Concat(OmniSharpDocumentSymbolHandler.Enumerate(_handlers))
.Concat(OmniSharpReferencesHandler.Enumerate(_handlers))
.Concat(OmniSharpCodeLensHandler.Enumerate(_handlers))
.Concat(OmniSharpCodeActionHandler.Enumerate(_handlers))
.Concat(OmniSharpDocumentFormattingHandler.Enumerate(_handlers))
.Concat(OmniSharpDocumentFormatRangeHandler.Enumerate(_handlers))
.Concat(OmniSharpDocumentOnTypeFormatHandler.Enumerate(_handlers)))
Expand Down