diff --git a/src/LanguageServer/Protocol/Extensions/ProtocolConversions.cs b/src/LanguageServer/Protocol/Extensions/ProtocolConversions.cs index e8608ec2e28a7..eac849642c1fe 100644 --- a/src/LanguageServer/Protocol/Extensions/ProtocolConversions.cs +++ b/src/LanguageServer/Protocol/Extensions/ProtocolConversions.cs @@ -936,29 +936,22 @@ public static LSP.MarkupContent GetDocumentationMarkupContent(ImmutableArray` in doc comments. It can be a block or it can be inline. + case TextTags.Text when taggedText.Style == (TaggedTextStyle.Code | TaggedTextStyle.PreserveWhitespace): + // This represents a block of code (``) in doc comments. // Since code elements optionally support a `lang` attribute and we do not have access to the // language which was specified at this point, we tell the client to render it as plain text. - if (markdownBuilder.IsLineEmpty()) - { - // If the current line is empty, we can append a code block. - markdownBuilder.AppendLine($"{BlockCodeFence}text"); - markdownBuilder.AppendLine(taggedText.Text); - markdownBuilder.AppendLine(BlockCodeFence); - } - else - { - // There is text on the line already - we should append an in-line code block. - markdownBuilder.Append($"`{taggedText.Text}`"); - } + if (!markdownBuilder.IsLineEmpty()) + AppendLineBreak(markdownBuilder); + + // The current line is empty, we can append a code block. + markdownBuilder.AppendLine($"{BlockCodeFence}text"); + markdownBuilder.AppendLine(taggedText.Text); + markdownBuilder.AppendLine(BlockCodeFence); + break; case TextTags.LineBreak: - // A line ending with double space and a new line indicates to markdown - // to render a single-spaced line break. - markdownBuilder.Append(" "); - markdownBuilder.AppendLine(); + AppendLineBreak(markdownBuilder); break; default: var styledText = GetStyledText(taggedText, codeFence != null); @@ -975,6 +968,14 @@ public static LSP.MarkupContent GetDocumentationMarkupContent(ImmutableArray + /// + /// if (true) { + /// Console.WriteLine(""hello""); + /// } + /// + /// + void {|caret:AMethod|}(int i) + { + } +}"; + var clientCapabilities = new LSP.ClientCapabilities + { + TextDocument = new LSP.TextDocumentClientCapabilities { Hover = new LSP.HoverSetting { ContentFormat = [LSP.MarkupKind.Markdown] } } + }; + await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, clientCapabilities); + var expectedLocation = testLspServer.GetLocations("caret").Single(); + + var expectedMarkdown = @"```csharp +void A.AMethod(int i) +``` + + +```text +if (true) { + Console.WriteLine(""hello""); +} +``` +"; + + var results = await RunGetHoverAsync( + testLspServer, + expectedLocation).ConfigureAwait(false); + Assert.Equal(expectedMarkdown, results.Contents.Fourth.Value); + } + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/vscode-csharp/issues/6577")] public async Task TestGetHoverAsync_UsesInlineCodeFencesInAwaitReturn(bool mutatingLspWorkspace) {