-
Notifications
You must be signed in to change notification settings - Fork 417
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #977 from mholo65/lsp-completionhandler
Adds CompletionHandler.
- Loading branch information
Showing
2 changed files
with
145 additions
and
0 deletions.
There are no files selected for viewing
144 changes: 144 additions & 0 deletions
144
src/OmniSharp.LanguageServerProtocol/Handlers/CompletionHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Composition; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using OmniSharp.Extensions.JsonRpc; | ||
using OmniSharp.Extensions.LanguageServer.Capabilities.Client; | ||
using OmniSharp.Extensions.LanguageServer.Models; | ||
using OmniSharp.Extensions.LanguageServer.Protocol; | ||
using OmniSharp.Mef; | ||
using OmniSharp.Models.AutoComplete; | ||
using OmniSharp.Models.TypeLookup; | ||
|
||
namespace OmniSharp.LanguageServerProtocol.Handlers | ||
{ | ||
[Shared, Export(typeof(CompletionHandler))] | ||
class CompletionHandler : ICompletionHandler | ||
{ | ||
public static IEnumerable<IJsonRpcHandler> Enumerate(RequestHandlers handlers) | ||
{ | ||
foreach (var (selector, handler) in handlers | ||
.OfType<Mef.IRequestHandler<AutoCompleteRequest, IEnumerable<AutoCompleteResponse>>>()) | ||
if (handler != null) | ||
yield return new CompletionHandler(handler, selector); | ||
} | ||
|
||
private CompletionCapability _capability; | ||
private readonly Mef.IRequestHandler<AutoCompleteRequest, IEnumerable<AutoCompleteResponse>> _autoCompleteHandler; | ||
private readonly DocumentSelector _documentSelector; | ||
|
||
private static readonly IDictionary<string, CompletionItemKind> _kind = new Dictionary<string, CompletionItemKind>{ | ||
// types | ||
{ "Class", CompletionItemKind.Class }, | ||
{ "Delegate", CompletionItemKind.Class }, // need a better option for this. | ||
{ "Enum", CompletionItemKind.Enum }, | ||
{ "Interface", CompletionItemKind.Interface }, | ||
{ "Struct", CompletionItemKind.Class }, // TODO: Is struct missing from enum? | ||
|
||
// variables | ||
{ "Local", CompletionItemKind.Variable }, | ||
{ "Parameter", CompletionItemKind.Variable }, | ||
{ "RangeVariable", CompletionItemKind.Variable }, | ||
|
||
// members | ||
{ "Const", CompletionItemKind.Value }, // TODO: Is const missing from enum? | ||
{ "EnumMember", CompletionItemKind.Enum }, | ||
{ "Event", CompletionItemKind.Function }, // TODO: Is event missing from enum? | ||
{ "Field", CompletionItemKind.Field }, | ||
{ "Method", CompletionItemKind.Method }, | ||
{ "Property", CompletionItemKind.Property }, | ||
|
||
// other stuff | ||
{ "Label", CompletionItemKind.Unit }, // need a better option for this. | ||
{ "Keyword", CompletionItemKind.Keyword }, | ||
{ "Namespace", CompletionItemKind.Module } | ||
}; | ||
|
||
private static CompletionItemKind GetCompletionItemKind(string key) | ||
{ | ||
if (string.IsNullOrEmpty(key)) | ||
{ | ||
return CompletionItemKind.Property; | ||
} | ||
if(_kind.TryGetValue(key, out var completionItemKind)) | ||
{ | ||
return completionItemKind; | ||
} | ||
return CompletionItemKind.Property; | ||
} | ||
|
||
[ImportingConstructor] | ||
public CompletionHandler(Mef.IRequestHandler<AutoCompleteRequest, IEnumerable<AutoCompleteResponse>> autoCompleteHandler, DocumentSelector documentSelector) | ||
{ | ||
_autoCompleteHandler = autoCompleteHandler; | ||
_documentSelector = documentSelector; | ||
} | ||
|
||
public async Task<CompletionList> Handle(TextDocumentPositionParams request, CancellationToken token) | ||
{ | ||
var omnisharpRequest = new AutoCompleteRequest() | ||
{ | ||
FileName = Helpers.FromUri(request.TextDocument.Uri), | ||
Column = Convert.ToInt32(request.Position.Character), | ||
Line = Convert.ToInt32(request.Position.Line), | ||
WantKind = true, | ||
WantDocumentationForEveryCompletionResult = true, | ||
WantReturnType = true | ||
}; | ||
|
||
var omnisharpResponse = await _autoCompleteHandler.Handle(omnisharpRequest); | ||
|
||
var completions = new Dictionary<string, List<CompletionItem>>(); | ||
foreach (var response in omnisharpResponse) | ||
{ | ||
var completionItem = new CompletionItem { | ||
Label = response.CompletionText, | ||
Detail = !string.IsNullOrEmpty(response.ReturnType) ? | ||
response.DisplayText : | ||
$"{response.ReturnType} {response.DisplayText}", | ||
Documentation = response.Description, | ||
Kind = GetCompletionItemKind(response.Kind), | ||
InsertText = response.CompletionText, | ||
}; | ||
|
||
if(!completions.ContainsKey(completionItem.Label)) | ||
{ | ||
completions[completionItem.Label] = new List<CompletionItem>(); | ||
} | ||
completions[completionItem.Label].Add(completionItem); | ||
} | ||
|
||
var result = new List<CompletionItem>(); | ||
foreach (var key in completions.Keys) | ||
{ | ||
var suggestion = completions[key][0]; | ||
var overloadCount = completions[key].Count - 1; | ||
|
||
if (overloadCount > 0) | ||
{ | ||
// indicate that there is more | ||
suggestion.Detail = $"{suggestion.Detail} (+ {overloadCount} overload(s))"; | ||
} | ||
|
||
result.Add(suggestion); | ||
} | ||
|
||
return new CompletionList(result); | ||
} | ||
|
||
public CompletionRegistrationOptions GetRegistrationOptions() | ||
{ | ||
return new CompletionRegistrationOptions() | ||
{ | ||
DocumentSelector = _documentSelector | ||
}; | ||
} | ||
|
||
public void SetCapability(CompletionCapability capability) | ||
{ | ||
_capability = capability; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters