提交 fa4d1afe 编写于 作者: D David Barbet

Add back roslyn completion item until liveshare supports VSCompletion item in the client.

上级 5d4cd939
// 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.Runtime.Serialization;
using Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.CustomProtocol
{
// TODO - This should be deleted when liveshare moves to VSCompletionItem.
// https://github.com/dotnet/roslyn/projects/45#card-21249665
[DataContract]
internal class RoslynCompletionItem : CompletionItem
{
/// <summary>
/// A set of custom tags on a completion item. Roslyn has information here to get icons.
/// </summary>
[DataMember(Name = "tags")]
public string[] Tags { get; set; }
/// <summary>
/// The description for a completion item.
/// </summary>
[DataMember(Name = "description")]
public RoslynTaggedText[] Description { get; set; }
public static RoslynCompletionItem From(CompletionItem completionItem)
{
return new RoslynCompletionItem
{
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
};
}
}
}
// 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 Microsoft.CodeAnalysis;
namespace Microsoft.CodeAnalysis.LanguageServer.CustomProtocol
{
// TODO - This should be deleted when liveshare moves to VSCompletionItem.
// https://github.com/dotnet/roslyn/projects/45#card-21249665
internal class RoslynTaggedText
{
public string Tag { get; set; }
public string Text { get; set; }
public TaggedText ToTaggedText() => new TaggedText(Tag, Text);
}
}
......@@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.LanguageServer.CustomProtocol;
using Microsoft.VisualStudio.Text.Adornments;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;
......@@ -37,21 +38,35 @@ public async Task<object> HandleRequestAsync(Solution solution, LSP.CompletionPa
return Array.Empty<LSP.CompletionItem>();
}
var lspClientCapability = clientCapabilities.HasVisualStudioLspCapability();
return list.Items.Select(item => CreateCompletionItem(request, item)).ToArray();
var lspVSClientCapability = clientCapabilities?.HasVisualStudioLspCapability() == true;
return list.Items.Select(item => CreateLSPCompletionItem(request, item, lspVSClientCapability)).ToArray();
// local functions
static LSP.VSCompletionItem CreateCompletionItem(LSP.CompletionParams request, CompletionItem item)
=> new LSP.VSCompletionItem
static LSP.CompletionItem CreateLSPCompletionItem(LSP.CompletionParams request, CompletionItem item, bool useVSCompletionItem)
{
if (useVSCompletionItem)
{
var vsCompletionItem = CreateCompletionItem<LSP.VSCompletionItem>(request, item);
vsCompletionItem.Icon = new ImageElement(item.Tags.GetFirstGlyph().GetImageId());
return vsCompletionItem;
}
else
{
var roslynCompletionItem = CreateCompletionItem<RoslynCompletionItem>(request, item);
roslynCompletionItem.Tags = item.Tags.ToArray();
return roslynCompletionItem;
}
}
static TCompletionItem CreateCompletionItem<TCompletionItem>(LSP.CompletionParams request, CompletionItem item) where TCompletionItem : LSP.CompletionItem, new()
=> new TCompletionItem
{
Label = item.DisplayText,
InsertText = item.Properties.ContainsKey("InsertionText") ? item.Properties["InsertionText"] : item.DisplayText,
SortText = item.SortText,
FilterText = item.FilterText,
Kind = GetCompletionKind(item.Tags),
Data = new CompletionResolveData { CompletionParams = request, DisplayText = item.DisplayText },
Icon = new ImageElement(item.Tags.GetFirstGlyph().GetImageId())
Data = new CompletionResolveData { CompletionParams = request, DisplayText = item.DisplayText }
};
}
......
......@@ -57,10 +57,22 @@ internal class CompletionResolveHandler : IRequestHandler<LSP.CompletionItem, LS
var description = await completionService.GetDescriptionAsync(document, selectedItem, cancellationToken).ConfigureAwait(false);
var resolvedCompletionItem = CloneVSCompletionItem(completionItem);
resolvedCompletionItem.Description = new ClassifiedTextElement(description.TaggedParts.Select(tp => new ClassifiedTextRun(tp.Tag.ToClassificationTypeName(), tp.Text)));
resolvedCompletionItem.Detail = description.TaggedParts.GetFullText();
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;
}
......
......@@ -27,15 +27,16 @@ void M()
var completionParams = CreateCompletionParams(locations["caret"].First());
var completionItem = CreateCompletionItem("A", LSP.CompletionItemKind.Class, tags, completionParams);
var description = new ClassifiedTextElement(CreateClassifiedTextRunForClass("A"));
var clientCapabilities = new LSP.VSClientCapabilities { SupportsVisualStudioExtensions = true };
var expected = CreateResolvedCompletionItem("A", LSP.CompletionItemKind.Class, null, completionParams, description, "class A", null);
var results = (LSP.VSCompletionItem)await RunResolveCompletionItemAsync(solution, completionItem);
var results = (LSP.VSCompletionItem)await RunResolveCompletionItemAsync(solution, completionItem, clientCapabilities);
AssertCompletionItemsEqual(expected, results, true);
}
private static async Task<object> RunResolveCompletionItemAsync(Solution solution, LSP.CompletionItem completionItem)
=> await GetLanguageServer(solution).ResolveCompletionItemAsync(solution, completionItem, new LSP.ClientCapabilities(), CancellationToken.None);
private static async Task<object> RunResolveCompletionItemAsync(Solution solution, LSP.CompletionItem completionItem, LSP.ClientCapabilities clientCapabilities = null)
=> await GetLanguageServer(solution).ResolveCompletionItemAsync(solution, completionItem, clientCapabilities, CancellationToken.None);
private static LSP.VSCompletionItem CreateResolvedCompletionItem(string text, LSP.CompletionItemKind kind, string[] tags, LSP.CompletionParams requestParameters,
ClassifiedTextElement description, string detail, string documentation)
......
......@@ -23,12 +23,13 @@ void M()
}";
var (solution, locations) = CreateTestSolution(markup);
var expected = CreateCompletionItem("A", LSP.CompletionItemKind.Class, new string[] { "Class", "Internal" }, CreateCompletionParams(locations["caret"].First()));
var clientCapabilities = new LSP.VSClientCapabilities { SupportsVisualStudioExtensions = true };
var results = (LSP.VSCompletionItem[])await RunGetCompletionsAsync(solution, locations["caret"].First());
AssertCompletionItemsEqual(expected, results.First(), false);
var results = (LSP.CompletionItem[])await RunGetCompletionsAsync(solution, locations["caret"].First(), clientCapabilities);
AssertCompletionItemsEqual(expected, (LSP.VSCompletionItem)results.First(), false);
}
private static async Task<object> RunGetCompletionsAsync(Solution solution, LSP.Location caret)
=> await GetLanguageServer(solution).GetCompletionsAsync(solution, CreateCompletionParams(caret), new LSP.ClientCapabilities(), CancellationToken.None);
private static async Task<object> RunGetCompletionsAsync(Solution solution, LSP.Location caret, LSP.ClientCapabilities clientCapabilities = null)
=> await GetLanguageServer(solution).GetCompletionsAsync(solution, CreateCompletionParams(caret), clientCapabilities, CancellationToken.None);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册