Skip to content

Commit

Permalink
Merge pull request #1795 from razzmatazz/lsp-code-actions
Browse files Browse the repository at this point in the history
LSP: wire up handler for codeAction
  • Loading branch information
filipw authored May 21, 2020
2 parents ffafffb + 66c3cb1 commit a8d639f
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
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

0 comments on commit a8d639f

Please sign in to comment.