static MarkupContent GetContents(QuickInfoItem info, Document document, ClientCapabilities clientCapabilities) { var clientSupportsMarkdown = clientCapabilities?.TextDocument?.Hover?.ContentFormat.Contains(MarkupKind.Markdown) == true; // Insert line breaks in between sections to ensure we get double spacing between sections. var tags = info.Sections .SelectMany(section => section.TaggedParts.Add(new TaggedText(TextTags.LineBreak, Environment.NewLine))) .ToImmutableArray(); return(ProtocolConversions.GetDocumentationMarkupContent(tags, document, clientSupportsMarkdown)); }
public async Task <LSP.CompletionItem> HandleRequestAsync(LSP.CompletionItem completionItem, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; Contract.ThrowIfNull(document); var completionService = document.Project.LanguageServices.GetRequiredService <CompletionService>(); var cacheEntry = GetCompletionListCacheEntry(completionItem); if (cacheEntry == null) { // Don't have a cache associated with this completion item, cannot resolve. context.TraceInformation("No cache entry found for the provided completion item at resolve time."); return(completionItem); } var list = cacheEntry.CompletionList; // Find the matching completion item in the completion list var selectedItem = list.Items.FirstOrDefault(cachedCompletionItem => MatchesLSPCompletionItem(completionItem, cachedCompletionItem)); if (selectedItem == null) { return(completionItem); } var options = CompletionOptions.From(document.Project); var displayOptions = SymbolDescriptionOptions.From(document.Project); var description = await completionService.GetDescriptionAsync(document, selectedItem, options, displayOptions, cancellationToken).ConfigureAwait(false) !; if (description != null) { var supportsVSExtensions = context.ClientCapabilities.HasVisualStudioLspCapability(); if (supportsVSExtensions) { var vsCompletionItem = (LSP.VSInternalCompletionItem)completionItem; vsCompletionItem.Description = new ClassifiedTextElement(description.TaggedParts .Select(tp => new ClassifiedTextRun(tp.Tag.ToClassificationTypeName(), tp.Text))); } else { var clientSupportsMarkdown = context.ClientCapabilities.TextDocument?.Completion?.CompletionItem?.DocumentationFormat.Contains(LSP.MarkupKind.Markdown) == true; completionItem.Documentation = ProtocolConversions.GetDocumentationMarkupContent(description.TaggedParts, document, clientSupportsMarkdown); } } // We compute the TextEdit resolves for complex text edits (e.g. override and partial // method completions) here. Lazily resolving TextEdits is technically a violation of // the LSP spec, but is currently supported by the VS client anyway. Once the VS client // adheres to the spec, this logic will need to change and VS will need to provide // official support for TextEdit resolution in some form. if (selectedItem.IsComplexTextEdit) { Contract.ThrowIfTrue(completionItem.InsertText != null); Contract.ThrowIfTrue(completionItem.TextEdit != null); var snippetsSupported = context.ClientCapabilities.TextDocument?.Completion?.CompletionItem?.SnippetSupport ?? false; completionItem.TextEdit = await GenerateTextEditAsync( document, completionService, selectedItem, snippetsSupported, cancellationToken).ConfigureAwait(false); } return(completionItem); }