private static void AssertValidSignatureHelp(SignatureHelp?signatureHelp, Symbol symbol) { signatureHelp.Should().NotBeNull(); signatureHelp !.Signatures.Should().NotBeNull(); foreach (var signature in signatureHelp.Signatures) { signature.Label.Should().StartWith(symbol.Name.StartsWith("list") ? "list*(" : $"{symbol.Name}("); signature.Label.Should().EndWith(")"); signature.Parameters.Should().NotBeNull(); if (signature.Parameters !.Count() >= 2) { signature.Label.Should().Contain(", "); } // we use the top level active parameter index signature.ActiveParameter.Should().BeNull(); signature.Documentation.Should().NotBeNull(); signature.Documentation !.MarkupContent.Should().NotBeNull(); signature.Documentation.MarkupContent !.Kind.Should().Be(MarkupKind.Markdown); signature.Documentation.MarkupContent.Value.Should().NotBeEmpty(); } }
public async Task Handle_Resolve_TagHelperAttribute_ReturnsCompletionItemWithDocumentation() { // Arrange var lspDescriptionFactory = new Mock <LSPTagHelperTooltipFactory>(MockBehavior.Strict); var markdown = new MarkupContent { Kind = MarkupKind.Markdown, Value = "Some Markdown" }; lspDescriptionFactory.Setup(factory => factory.TryCreateTooltip(It.IsAny <AggregateBoundAttributeDescription>(), MarkupKind.Markdown, out markdown)) .Returns(true); var endpoint = new RazorCompletionResolveEndpoint(lspDescriptionFactory.Object, VSLSPTagHelperTooltipFactory, CompletionListCache, LoggerFactory); endpoint.GetRegistration(DefaultClientCapability); var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute); razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty <BoundAttributeDescriptionInfo>())); var completionList = CreateLSPCompletionList(new[] { razorCompletionItem }); var completionItem = completionList.Items.Single(); var parameters = ConvertToBridgedItem(completionItem); // Act var newCompletionItem = await endpoint.Handle(parameters, default); // Assert Assert.NotNull(newCompletionItem.Documentation); }
public async Task Handle_Resolve_TagHelperAttribute_ReturnsCompletionItemWithDocumentation() { // Arrange var lspDescriptionFactory = new Mock <LSPTagHelperTooltipFactory>(MockBehavior.Strict); var markdown = new MarkupContent { Kind = MarkupKind.Markdown, Value = "Some Markdown" }; lspDescriptionFactory.Setup(factory => factory.TryCreateTooltip(It.IsAny <AggregateBoundAttributeDescription>(), out markdown)) .Returns(true); var languageServer = new Mock <ClientNotifierServiceBase>(MockBehavior.Strict); languageServer.Setup(ls => ls.ClientSettings).Returns(new InitializeParams()); var completionEndpoint = new RazorCompletionEndpoint( Dispatcher, EmptyDocumentResolver, CompletionFactsService, lspDescriptionFactory.Object, VSLSPTagHelperTooltipFactory, languageServer.Object, LoggerFactory); var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute); razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty <BoundAttributeDescriptionInfo>())); var completionList = completionEndpoint.CreateLSPCompletionList(new[] { razorCompletionItem }); var completionItem = completionList.Items.Single(); // Act var newCompletionItem = await completionEndpoint.Handle(completionItem, default); // Assert Assert.NotNull(newCompletionItem.Documentation); }
private static MarkupContent CreateMarkupContent(ISymbolInformation symbol) { string type = symbol.Type?.ToString(); if (string.IsNullOrEmpty(type) || type == "?") { type = Resources.LoggingMessages.hover_unknown; } string declaration = symbol.IsDeclaration ? Resources.LoggingMessages.hover_isDeclaration : symbol.DeclarationOrigin.PositionToFormattedString(); string parameters = ""; if (symbol.Kind == Kind.Method || symbol.Kind == Kind.Function) { parameters += "("; if (symbol?.DeclarationOrigin?.Params != null) { parameters += string.Join(", ", symbol.DeclarationOrigin.Params.Select(parameter => parameter.Name + ": " + parameter.Type)); } parameters += ")"; } var formattedContent = new MarkupContent(); formattedContent.Kind = MarkupKind.Markdown; formattedContent.Value = $" **`{symbol.Name + parameters}`** *({symbol.PositionToFormattedString()})*\n" + $"* **{Resources.LoggingMessages.hover_type}:** {type}\n" + $"* **{Resources.LoggingMessages.hover_kind}:** {symbol.Kind}\n" + $"* **{Resources.LoggingMessages.hover_scope}:** `{symbol.Parent.Name}`\n" + $"* **{Resources.LoggingMessages.hover_declaration}:** {declaration}"; return(formattedContent); }
public async Task Handle_Resolve_TagHelperElementCompletion_ReturnsCompletionItemWithDocumentation() { // Arrange var descriptionFactory = new Mock <TagHelperTooltipFactory>(MockBehavior.Strict); var markdown = new MarkupContent { Kind = MarkupKind.Markdown, Value = "Some Markdown" }; descriptionFactory.Setup(factory => factory.TryCreateTooltip(It.IsAny <AggregateBoundElementDescription>(), out markdown)) .Returns(true); var completionEndpoint = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, descriptionFactory.Object, LoggerFactory); var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement); razorCompletionItem.SetTagHelperElementDescriptionInfo(new AggregateBoundElementDescription(Array.Empty <BoundElementDescriptionInfo>())); var completionList = completionEndpoint.CreateLSPCompletionList(new[] { razorCompletionItem }); var completionItem = completionList.Items.Single(); // Act var newCompletionItem = await completionEndpoint.Handle(completionItem, default); // Assert Assert.NotNull(newCompletionItem.Documentation); }
public async Task Handle_Resolve_NonTagHelperCompletion_Noops() { // Arrange var lspDescriptionFactory = new Mock <LSPTagHelperTooltipFactory>(MockBehavior.Strict); var markdown = new MarkupContent { Kind = MarkupKind.Markdown, Value = "Some Markdown" }; lspDescriptionFactory.Setup(factory => factory.TryCreateTooltip(It.IsAny <AggregateBoundElementDescription>(), out markdown)) .Returns(true); var languageServer = new Mock <ClientNotifierServiceBase>(MockBehavior.Strict); languageServer.Setup(ls => ls.ClientSettings).Returns(new InitializeParams()); var completionEndpoint = new RazorCompletionEndpoint( Dispatcher, EmptyDocumentResolver, CompletionFactsService, lspDescriptionFactory.Object, VSLSPTagHelperTooltipFactory, languageServer.Object, LoggerFactory); var completionItem = new CompletionItem(); // Act var newCompletionItem = await completionEndpoint.Handle(completionItem, default); // Assert Assert.Null(newCompletionItem.Documentation); }
public override bool TryCreateTooltip(AggregateBoundElementDescription elementDescriptionInfo, out MarkupContent tooltipContent) { if (elementDescriptionInfo is null) { throw new ArgumentNullException(nameof(elementDescriptionInfo)); } var associatedTagHelperInfos = elementDescriptionInfo.AssociatedTagHelperDescriptions; if (associatedTagHelperInfos.Count == 0) { tooltipContent = null; return(false); } // This generates a markdown description that looks like the following: // **SomeTagHelper** // // The Summary documentation text with `CrefTypeValues` in code. // // Additional description infos result in a triple `---` to separate the markdown entries. var descriptionBuilder = new StringBuilder(); for (var i = 0; i < associatedTagHelperInfos.Count; i++) { var descriptionInfo = associatedTagHelperInfos[i]; if (descriptionBuilder.Length > 0) { descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine("---"); } var tagHelperType = descriptionInfo.TagHelperTypeName; var reducedTypeName = ReduceTypeName(tagHelperType); StartOrEndBold(descriptionBuilder); descriptionBuilder.Append(reducedTypeName); StartOrEndBold(descriptionBuilder); var documentation = descriptionInfo.Documentation; if (!TryExtractSummary(documentation, out var summaryContent)) { continue; } descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine(); var finalSummaryContent = CleanSummaryContent(summaryContent); descriptionBuilder.Append(finalSummaryContent); } tooltipContent = new MarkupContent { Kind = GetMarkupKind() }; tooltipContent.Value = descriptionBuilder.ToString(); return(true); }
public override void Apply(MarkupContent content, MarkupRendererContext context) { var match = Expression.Match(content.Html); while (match != null && match.Success) { var tagname = "h" + (match.Groups[1].Value.Length + 1); content.Html = content.Html.Replace(match.Groups[0].Value, string.Format("<{0}>{1}</{0}>\r\n\r\n", tagname, match.Groups[2].Value)); match = Expression.Match(content.Html); } }
public override void Apply(MarkupContent content, MarkupRendererContext context) { content.Html = Expression.Replace(content.Html, delegate (Match match) { var childContent = context.LoadSiblingContent(match.Groups["path"].Value); if (childContent == null) return ""; content.SourceFiles.AddRange(childContent.SourceFiles); return childContent.Html; } ); }
private HoverModel AttributeInfoToHover(IEnumerable <BoundAttributeDescriptor> descriptors, RangeModel range, string attributeName, ClientCapabilities clientCapabilities) { var descriptionInfos = descriptors.Select(boundAttribute => { var indexer = TagHelperMatchingConventions.SatisfiesBoundAttributeIndexer(attributeName, boundAttribute); var descriptionInfo = BoundAttributeDescriptionInfo.From(boundAttribute, indexer); return(descriptionInfo); }).ToList().AsReadOnly(); var attrDescriptionInfo = new AggregateBoundAttributeDescription(descriptionInfos); var isVSClient = clientCapabilities is PlatformAgnosticClientCapabilities platformAgnosticClientCapabilities && platformAgnosticClientCapabilities.SupportsVisualStudioExtensions; if (isVSClient && _vsLspTagHelperTooltipFactory.TryCreateTooltip(attrDescriptionInfo, out ContainerElement classifiedTextElement)) { var vsHover = new OmniSharpVSHover { Contents = new MarkedStringsOrMarkupContent(), Range = range, RawContent = classifiedTextElement, }; return(vsHover); } else { var hoverContentFormat = GetHoverContentFormat(clientCapabilities); if (!_lspTagHelperTooltipFactory.TryCreateTooltip(attrDescriptionInfo, hoverContentFormat, out var vsMarkupContent)) { return(null); } Enum.TryParse(vsMarkupContent.Kind.Value, out MarkupKind markupKind); var markupContent = new MarkupContent() { Value = vsMarkupContent.Value, Kind = markupKind, }; var hover = new HoverModel { Contents = new MarkedStringsOrMarkupContent(markupContent), Range = range }; return(hover); } }
public override void Apply(MarkupContent content, MarkupRendererContext context) { content.Html = Expression.Replace(content.Html, delegate (Match match) { var image = context.ResolveContentAttachmentPath(match.Groups["image"].Value); var builder = new StringBuilder(); builder.AppendLine("<div class='image'>"); builder.AppendFormat("<img src='{0}' alt='Image {1}: {2}' />", image, match.Groups["index"].Value, match.Groups["caption"]).AppendLine(); builder.AppendFormat("<div>Image {0}: {1}</div>", match.Groups["index"].Value, match.Groups["caption"]); builder.AppendLine("</div>"); return builder.ToString(); } ); }
public async Task Handle_NonTagHelperCompletion_Noops() { // Arrange var descriptionFactory = new Mock<TagHelperDescriptionFactory>(); var markdown = new MarkupContent { Kind = MarkupKind.Markdown, Value = "Some Markdown" }; descriptionFactory.Setup(factory => factory.TryCreateDescription(It.IsAny<ElementDescriptionInfo>(), out markdown)) .Returns(true); var completionEndpoint = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, TagHelperCompletionService, descriptionFactory.Object, LoggerFactory); var completionItem = new CompletionItem(); // Act var newCompletionItem = await completionEndpoint.Handle(completionItem, default); // Assert Assert.Null(newCompletionItem.Documentation); }
public async Task Handle_DirectiveAttributeParameterCompletion_ReturnsCompletionItemWithDocumentation() { // Arrange var descriptionFactory = new Mock<TagHelperDescriptionFactory>(); var markdown = new MarkupContent { Kind = MarkupKind.Markdown, Value = "Some Markdown" }; descriptionFactory.Setup(factory => factory.TryCreateDescription(It.IsAny<AttributeCompletionDescription>(), out markdown)) .Returns(true); var completionEndpoint = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, TagHelperCompletionService, descriptionFactory.Object, LoggerFactory); var completionItem = new CompletionItem(); completionItem.SetDescriptionInfo(new AttributeCompletionDescription(Array.Empty<CodeAnalysis.Razor.Completion.AttributeDescriptionInfo>())); completionItem.SetRazorCompletionKind(RazorCompletionItemKind.DirectiveAttributeParameter); // Act var newCompletionItem = await completionEndpoint.Handle(completionItem, default); // Assert Assert.NotNull(newCompletionItem.Documentation); }
public Task <CompletionItem> Handle(CompletionItem completionItem, CancellationToken cancellationToken) { MarkupContent tagHelperDescription = null; if (completionItem.TryGetRazorCompletionKind(out var completionItemKind)) { switch (completionItemKind) { case RazorCompletionItemKind.DirectiveAttribute: case RazorCompletionItemKind.DirectiveAttributeParameter: var descriptionInfo = completionItem.GetAttributeDescriptionInfo(); _tagHelperDescriptionFactory.TryCreateDescription(descriptionInfo, out tagHelperDescription); break; } } else { if (completionItem.IsTagHelperElementCompletion()) { var descriptionInfo = completionItem.GetElementDescriptionInfo(); _tagHelperDescriptionFactory.TryCreateDescription(descriptionInfo, out tagHelperDescription); } if (completionItem.IsTagHelperAttributeCompletion()) { var descriptionInfo = completionItem.GetTagHelperAttributeDescriptionInfo(); _tagHelperDescriptionFactory.TryCreateDescription(descriptionInfo, out tagHelperDescription); } } if (tagHelperDescription != null) { var documentation = new StringOrMarkupContent(tagHelperDescription); completionItem.Documentation = documentation; } return(Task.FromResult(completionItem)); }
public Hover GetHoverInformation(Uri uri, int line, int col) { var symbol = _manager.GetSymbolByPosition(uri, line, col); if (symbol == null) { return(null); } MarkupContent formattedContent = CreateMarkupContent(symbol); Hover result = new Hover { Contents = new MarkedStringsOrMarkupContent(formattedContent), Range = new Range { Start = new Position(symbol.Line - 1, symbol.Column - 1), End = new Position(symbol.Line - 1, symbol.IdentifierEndColumn - 1) } }; return(result); }
public async Task <CompletionList> GetCompletionsAsync(IRIntellisenseContext context) { context.EditorBuffer.GetEditorDocument <IREditorDocument>().EditorTree.EnsureTreeReady(); var providers = _completionEngine.GetCompletionForLocation(context); if (providers == null || providers.Count == 0) { return(new CompletionList()); } // Do not generate thousands of items, VSCode cannot handle that. // Filter based on the text typed so far right away. var prefix = GetFilterPrefix(context); var completions = (await Task.WhenAll(providers.Select(p => p.GetEntriesAsync(context, prefix)))).SelectMany(t => t).ToList(); if (providers.All(p => p.AllowSorting)) { completions.Sort(new CompletionEntryComparer(StringComparison.OrdinalIgnoreCase)); completions.RemoveDuplicates(new CompletionEntryComparer(StringComparison.Ordinal)); } var sorted = new List <ICompletionEntry>(); sorted.AddRange(completions.Where(c => c.DisplayText.EndsWith("=", StringComparison.Ordinal))); sorted.AddRange(completions.Where(c => char.IsLetter(c.DisplayText[0]) && !c.DisplayText.EndsWith("=", StringComparison.Ordinal))); var items = sorted .Select(c => new CompletionItem { label = c.DisplayText, insertText = c.InsertionText, kind = (CompletionItemKind)c.ImageSource, documentation = new MarkupContent { value = c.Description }, data = c.Data is string @string ? JToken.FromObject(@string) : null }).ToList();
private static void AssertValidSignatureHelp(SignatureHelp?signatureHelp, Symbol symbol, bool expectDecorator) { signatureHelp.Should().NotBeNull(); signatureHelp !.Signatures.Should().NotBeNull(); foreach (var signature in signatureHelp.Signatures) { signature.Label.Should().StartWith(symbol.Name.StartsWith("list") ? "list*(" : $"{symbol.Name}("); if (expectDecorator) { // decorators should have no return type signature.Label.Should().EndWith(")"); } else { // normal function calls should include a return type signature.Label.Should().Contain("): "); } signature.Parameters.Should().NotBeNull(); if (signature.Parameters !.Count() >= 2) { signature.Label.Should().Contain(", "); } // we use the top level active parameter index signature.ActiveParameter.Should().BeNull(); signature.Documentation.Should().NotBeNull(); signature.Documentation !.MarkupContent.Should().NotBeNull(); signature.Documentation.MarkupContent !.Kind.Should().Be(MarkupKind.Markdown); signature.Documentation.MarkupContent.Value.Should().NotBeEmpty(); } }
public async Task Handle_Resolve_NonTagHelperCompletion_Noops() { // Arrange var lspDescriptionFactory = new Mock <LSPTagHelperTooltipFactory>(MockBehavior.Strict); var markdown = new MarkupContent { Kind = MarkupKind.Markdown, Value = "Some Markdown" }; lspDescriptionFactory.Setup(factory => factory.TryCreateTooltip(It.IsAny <AggregateBoundElementDescription>(), MarkupKind.Markdown, out markdown)) .Returns(true); var endpoint = new RazorCompletionResolveEndpoint(LSPTagHelperTooltipFactory, VSLSPTagHelperTooltipFactory, CompletionListCache, LoggerFactory); endpoint.GetRegistration(DefaultClientCapability); var completionItem = new CompletionItem(); var parameters = ConvertToBridgedItem(completionItem); // Act var newCompletionItem = await endpoint.Handle(parameters, default); // Assert Assert.Null(newCompletionItem.Documentation); }
public override void Apply(MarkupContent content, MarkupRendererContext context) { content.Html = Expression.Replace(content.Html, "$1<strong>$2</strong>"); }
public Hover(MarkupContent contents) { Contents = contents; }
public override void Apply(MarkupContent content, MarkupRendererContext context) { content.Html = Expression.Replace(content.Html, "<blockquote><p>${Quote}</p><p><span class='author'>${Author}</span></p></blockquote>"); }
public MarkupContentImpl(MarkupContent content) { content_ = content; }
public abstract bool TryCreateDescription(AttributeCompletionDescription descriptionInfos, out MarkupContent markupContent);
public Task <CompletionItem> Handle(CompletionItem completionItem, CancellationToken cancellationToken) { MarkupContent tagHelperTooltip = null; if (!completionItem.TryGetCompletionListResultId(out var resultId)) { // Couldn't resolve. return(Task.FromResult(completionItem)); } if (!_completionListCache.TryGet(resultId, out var cachedCompletionItems)) { return(Task.FromResult(completionItem)); } var labelQuery = completionItem.Label; var associatedRazorCompletion = cachedCompletionItems.FirstOrDefault(completion => string.Equals(labelQuery, completion.DisplayText, StringComparison.Ordinal)); if (associatedRazorCompletion == null) { Debug.Fail("Could not find an associated razor completion item. This should never happen since we were able to look up the cached completion list."); return(Task.FromResult(completionItem)); } switch (associatedRazorCompletion.Kind) { case RazorCompletionItemKind.Directive: { var descriptionInfo = associatedRazorCompletion.GetDirectiveCompletionDescription(); completionItem.Documentation = descriptionInfo.Description; break; } case RazorCompletionItemKind.MarkupTransition: { var descriptionInfo = associatedRazorCompletion.GetMarkupTransitionCompletionDescription(); completionItem.Documentation = descriptionInfo.Description; break; } case RazorCompletionItemKind.DirectiveAttribute: case RazorCompletionItemKind.DirectiveAttributeParameter: case RazorCompletionItemKind.TagHelperAttribute: { var descriptionInfo = associatedRazorCompletion.GetAttributeCompletionDescription(); _tagHelperTooltipFactory.TryCreateTooltip(descriptionInfo, out tagHelperTooltip); break; } case RazorCompletionItemKind.TagHelperElement: { var descriptionInfo = associatedRazorCompletion.GetTagHelperElementDescriptionInfo(); _tagHelperTooltipFactory.TryCreateTooltip(descriptionInfo, out tagHelperTooltip); break; } } if (tagHelperTooltip != null) { var documentation = new StringOrMarkupContent(tagHelperTooltip); completionItem.Documentation = documentation; } return(Task.FromResult(completionItem)); }
public override bool TryCreateDescription(AttributeDescriptionInfo attributeDescriptionInfo, out MarkupContent tagHelperDescription) { var convertedDescriptionInfos = new List <RazorAttributeDescriptionInfo>(); foreach (var descriptionInfo in attributeDescriptionInfo.AssociatedAttributeDescriptions) { var tagHelperTypeName = ResolveTagHelperTypeName(descriptionInfo); var converted = new RazorAttributeDescriptionInfo( descriptionInfo.ReturnTypeName, tagHelperTypeName, descriptionInfo.PropertyName, descriptionInfo.Documentation); convertedDescriptionInfos.Add(converted); } var convertedDescriptionInfo = new AttributeCompletionDescription(convertedDescriptionInfos); return(TryCreateDescription(convertedDescriptionInfo, out tagHelperDescription)); }
public abstract bool TryCreateDescription(ElementDescriptionInfo descriptionInfos, out MarkupContent markupContent);
public override bool TryCreateDescription(AttributeCompletionDescription descriptionInfos, out MarkupContent tagHelperDescription) { var associatedAttributeInfos = descriptionInfos.DescriptionInfos; if (associatedAttributeInfos.Count == 0) { tagHelperDescription = null; return(false); } // This generates a markdown description that looks like the following: // **ReturnTypeName** SomeTypeName.**SomeProperty** // // The Summary documentation text with `CrefTypeValues` in code. // // Additional description infos result in a triple `---` to separate the markdown entries. var descriptionBuilder = new StringBuilder(); for (var i = 0; i < associatedAttributeInfos.Count; i++) { var descriptionInfo = associatedAttributeInfos[i]; if (descriptionBuilder.Length > 0) { descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine("---"); } StartOrEndBold(descriptionBuilder); var returnTypeName = GetSimpleName(descriptionInfo.ReturnTypeName); var reducedReturnTypeName = ReduceTypeName(returnTypeName); descriptionBuilder.Append(reducedReturnTypeName); StartOrEndBold(descriptionBuilder); descriptionBuilder.Append(" "); var tagHelperTypeName = descriptionInfo.TypeName; var reducedTagHelperTypeName = ReduceTypeName(tagHelperTypeName); descriptionBuilder.Append(reducedTagHelperTypeName); descriptionBuilder.Append("."); StartOrEndBold(descriptionBuilder); descriptionBuilder.Append(descriptionInfo.PropertyName); StartOrEndBold(descriptionBuilder); var documentation = descriptionInfo.Documentation; if (!TryExtractSummary(documentation, out var summaryContent)) { continue; } descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine(); var finalSummaryContent = CleanSummaryContent(summaryContent); descriptionBuilder.Append(finalSummaryContent); } tagHelperDescription = new MarkupContent { Kind = GetMarkupKind() }; tagHelperDescription.Value = descriptionBuilder.ToString(); return(true); }
public override void Apply(MarkupContent content, MarkupRendererContext context) { content.Html = Expression.Replace(content.Html, Matcher); }
public abstract bool TryCreateTooltip(AggregateBoundElementDescription elementDescriptionInfo, out MarkupContent tooltipContent);
public abstract bool TryCreateTooltip(AggregateBoundAttributeDescription attributeDescriptionInfo, out MarkupContent tooltipContent);
public override bool TryCreateTooltip( AggregateBoundAttributeDescription attributeDescriptionInfo, MarkupKind markupKind, [NotNullWhen(true)] out MarkupContent?tooltipContent) { if (attributeDescriptionInfo is null) { throw new ArgumentNullException(nameof(attributeDescriptionInfo)); } var associatedAttributeInfos = attributeDescriptionInfo.DescriptionInfos; if (associatedAttributeInfos.Count == 0) { tooltipContent = null; return(false); } // This generates a markdown description that looks like the following: // **ReturnTypeName** SomeTypeName.**SomeProperty** // // The Summary documentation text with `CrefTypeValues` in code. // // Additional description infos result in a triple `---` to separate the markdown entries. var descriptionBuilder = new StringBuilder(); for (var i = 0; i < associatedAttributeInfos.Count; i++) { var descriptionInfo = associatedAttributeInfos[i]; if (descriptionBuilder.Length > 0) { descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine("---"); } StartOrEndBold(descriptionBuilder, markupKind); if (!TypeNameStringResolver.TryGetSimpleName(descriptionInfo.ReturnTypeName, out var returnTypeName)) { returnTypeName = descriptionInfo.ReturnTypeName; } var reducedReturnTypeName = ReduceTypeName(returnTypeName); descriptionBuilder.Append(reducedReturnTypeName); StartOrEndBold(descriptionBuilder, markupKind); descriptionBuilder.Append(" "); var tagHelperTypeName = descriptionInfo.TypeName; var reducedTagHelperTypeName = ReduceTypeName(tagHelperTypeName); descriptionBuilder.Append(reducedTagHelperTypeName); descriptionBuilder.Append("."); StartOrEndBold(descriptionBuilder, markupKind); descriptionBuilder.Append(descriptionInfo.PropertyName); StartOrEndBold(descriptionBuilder, markupKind); var documentation = descriptionInfo.Documentation; if (!TryExtractSummary(documentation, out var summaryContent)) { continue; } descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine(); var finalSummaryContent = CleanSummaryContent(summaryContent); descriptionBuilder.Append(finalSummaryContent); } tooltipContent = new MarkupContent { Kind = markupKind, Value = descriptionBuilder.ToString(), }; return(true); }