// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.LanguageServer.CustomProtocol;
using Microsoft.VisualStudio.Text.Adornments;
using Newtonsoft.Json.Linq;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
///
/// Handle a completion resolve request to add description.
///
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentCompletionResolveName)]
internal class CompletionResolveHandler : IRequestHandler
{
public async Task HandleRequestAsync(Solution solution, LSP.CompletionItem completionItem,
LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken, bool keepThreadContext)
{
CompletionResolveData data;
if (completionItem.Data is CompletionResolveData)
{
data = (CompletionResolveData)completionItem.Data;
}
else
{
data = ((JToken)completionItem.Data).ToObject();
}
var request = data.CompletionParams;
var document = solution.GetDocumentFromURI(request.TextDocument.Uri);
if (document == null)
{
return completionItem;
}
var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(keepThreadContext);
var completionService = document.Project.LanguageServices.GetService();
var list = await completionService.GetCompletionsAsync(document, position, cancellationToken: cancellationToken).ConfigureAwait(keepThreadContext);
if (list == null)
{
return completionItem;
}
var selectedItem = list.Items.FirstOrDefault(i => i.DisplayText == data.DisplayText);
if (selectedItem == null)
{
return completionItem;
}
var description = await completionService.GetDescriptionAsync(document, selectedItem, cancellationToken).ConfigureAwait(keepThreadContext);
var lspVSClientCapability = clientCapabilities?.HasVisualStudioLspCapability() == true;
LSP.CompletionItem resolvedCompletionItem;
if (lspVSClientCapability)
{
resolvedCompletionItem = CloneVSCompletionItem(completionItem);
((LSP.VSCompletionItem)resolvedCompletionItem).Description = new ClassifiedTextElement(description.TaggedParts
.Select(tp => new ClassifiedTextRun(tp.Tag.ToClassificationTypeName(), tp.Text)));
}
else
{
resolvedCompletionItem = RoslynCompletionItem.From(completionItem);
((RoslynCompletionItem)resolvedCompletionItem).Description = description.TaggedParts.Select(
tp => new RoslynTaggedText { Tag = tp.Tag, Text = tp.Text }).ToArray();
}
resolvedCompletionItem.Detail = description.TaggedParts.GetFullText();
return resolvedCompletionItem;
}
private LSP.VSCompletionItem CloneVSCompletionItem(LSP.CompletionItem completionItem)
{
return new LSP.VSCompletionItem
{
AdditionalTextEdits = completionItem.AdditionalTextEdits,
Command = completionItem.Command,
CommitCharacters = completionItem.CommitCharacters,
Data = completionItem.Data,
Detail = completionItem.Detail,
Documentation = completionItem.Documentation,
FilterText = completionItem.FilterText,
InsertText = completionItem.InsertText,
InsertTextFormat = completionItem.InsertTextFormat,
Kind = completionItem.Kind,
Label = completionItem.Label,
SortText = completionItem.SortText,
TextEdit = completionItem.TextEdit
};
}
}
}