CompletionResolveHandler.cs 4.7 KB
Newer Older
J
Jonathon Marolf 已提交
1 2 3
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
4

5 6
#nullable enable

7
using System;
8 9 10 11 12
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
13
using Microsoft.CodeAnalysis.Host.Mef;
14 15 16 17 18 19 20 21 22 23 24 25
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
{
    /// <summary>
    /// Handle a completion resolve request to add description.
    /// </summary>
    [Shared]
    [ExportLspMethod(LSP.Methods.TextDocumentCompletionResolveName)]
D
David Barbet 已提交
26
    internal class CompletionResolveHandler : AbstractRequestHandler<LSP.CompletionItem, LSP.CompletionItem>
27
    {
28
        [ImportingConstructor]
29
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
30
        public CompletionResolveHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
31 32 33
        {
        }

34 35
        public override async Task<LSP.CompletionItem> HandleRequestAsync(LSP.CompletionItem completionItem, LSP.ClientCapabilities clientCapabilities,
            string? clientName, CancellationToken cancellationToken)
36 37 38 39 40 41 42 43 44 45 46 47 48
        {
            CompletionResolveData data;
            if (completionItem.Data is CompletionResolveData)
            {
                data = (CompletionResolveData)completionItem.Data;
            }
            else
            {
                data = ((JToken)completionItem.Data).ToObject<CompletionResolveData>();
            }

            var request = data.CompletionParams;

D
David Barbet 已提交
49
            var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
50 51 52 53 54
            if (document == null)
            {
                return completionItem;
            }

55
            var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);
56

57
            var completionService = document.Project.LanguageServices.GetRequiredService<CompletionService>();
58
            var list = await completionService.GetCompletionsAsync(document, position, cancellationToken: cancellationToken).ConfigureAwait(false);
59 60 61 62 63 64 65 66 67 68 69
            if (list == null)
            {
                return completionItem;
            }

            var selectedItem = list.Items.FirstOrDefault(i => i.DisplayText == data.DisplayText);
            if (selectedItem == null)
            {
                return completionItem;
            }

70
            var description = await completionService.GetDescriptionAsync(document, selectedItem, cancellationToken).ConfigureAwait(false);
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

            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;
        }

91
        private static LSP.VSCompletionItem CloneVSCompletionItem(LSP.CompletionItem completionItem)
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
        {
            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
            };
        }
    }
}