private static QuickInfoItem CreateQuickInfo( TextSpan location, DiagnosticDescriptor descriptor, params TextSpan[] relatedSpans ) { var description = descriptor.Title.ToStringOrNull() ?? descriptor.Description.ToStringOrNull() ?? descriptor.MessageFormat.ToStringOrNull() ?? descriptor.Id; var idTag = !string.IsNullOrWhiteSpace(descriptor.HelpLinkUri) ? new TaggedText( TextTags.Text, descriptor.Id, TaggedTextStyle.None, descriptor.HelpLinkUri, descriptor.HelpLinkUri ) : new TaggedText(TextTags.Text, descriptor.Id); return(QuickInfoItem.Create( location, sections: new[] { QuickInfoSection.Create( QuickInfoSectionKinds.Description, new[] { idTag, new TaggedText(TextTags.Punctuation, ":"), new TaggedText(TextTags.Space, " "), new TaggedText(TextTags.Text, description) }.ToImmutableArray() ) }.ToImmutableArray(), relatedSpans: relatedSpans.ToImmutableArray() )); }
static void appendSectionAsCsharp(QuickInfoSection section, StringBuilder builder, FormattingOptions formattingOptions, int startingIndex = 0, bool includeSpaceAtStart = true) { if (includeSpaceAtStart) { builder.Append(formattingOptions.NewLine); } builder.Append("```csharp"); builder.Append(formattingOptions.NewLine); for (int i = startingIndex; i < section.TaggedParts.Length; i++) { TaggedText part = section.TaggedParts[i]; if (part.Tag == TextTags.LineBreak && i + 1 != section.TaggedParts.Length) { builder.Append(formattingOptions.NewLine); } else { builder.Append(part.Text); } } builder.Append(formattingOptions.NewLine); builder.Append("```"); }
static void buildSectionAsMarkdown(QuickInfoSection section, StringBuilder stringBuilder, FormattingOptions formattingOptions, out int lastIndex, bool untilLineBreak = false) { bool isInCodeBlock = false; lastIndex = 0; for (int i = 0; i < section.TaggedParts.Length; i++) { var current = section.TaggedParts[i]; lastIndex = i; switch (current.Tag) { case TextTags.Text when !isInCodeBlock: stringBuilder.Append(current.Text); break; case TextTags.Text: endBlock(); stringBuilder.Append(current.Text); break; case TextTags.Space when isInCodeBlock: if (nextIsTag(i, TextTags.Text)) { endBlock(); } stringBuilder.Append(current.Text); break; case TextTags.Space: case TextTags.Punctuation: stringBuilder.Append(current.Text); break; case ContainerStart: addNewline(); stringBuilder.Append(current.Text); break; case ContainerEnd: addNewline(); break; case TextTags.LineBreak when untilLineBreak && stringBuilder.Length != 0: // The section will end and another newline will be appended, no need to add yet another newline. return; case TextTags.LineBreak: if (stringBuilder.Length != 0 && !nextIsTag(i, ContainerStart, ContainerEnd) && i + 1 != section.TaggedParts.Length) { addNewline(); } break; default: if (!isInCodeBlock) { isInCodeBlock = true; stringBuilder.Append('`'); } stringBuilder.Append(current.Text); break; } } if (isInCodeBlock) { endBlock(); } return; void addNewline() { if (isInCodeBlock) { endBlock(); } // Markdown needs 2 linebreaks to make a new paragraph stringBuilder.Append(formattingOptions.NewLine); stringBuilder.Append(formattingOptions.NewLine); } void endBlock() { stringBuilder.Append('`'); isInCodeBlock = false; } bool nextIsTag(int i, params string[] tags) { int nextI = i + 1; return(nextI < section.TaggedParts.Length && tags.Contains(section.TaggedParts[nextI].Tag)); } }
internal static IEnumerable <object> BuildClassifiedTextElements(QuickInfoSection section) { // This method produces a sequence of zero or more paragraphs var paragraphs = new List <object>(); // Each paragraph is constructed from one or more lines var currentParagraph = new List <ClassifiedTextElement>(); // Each line is constructed from one or more inline elements var currentRuns = new List <ClassifiedTextRun>(); foreach (var part in section.TaggedParts) { if (part.Tag == TextTags.LineBreak) { if (currentRuns.Count > 0) { // This line break means the end of a line within a paragraph. currentParagraph.Add(new ClassifiedTextElement(currentRuns)); currentRuns.Clear(); } else { // This line break means the end of a paragraph. Empty paragraphs are ignored, but could appear // in the input to this method: // // * Empty <para> elements // * Explicit line breaks at the start of a comment // * Multiple line breaks between paragraphs if (currentParagraph.Count > 0) { // The current paragraph is not empty, so add it to the result collection paragraphs.Add(CreateParagraphFromLines(currentParagraph)); currentParagraph.Clear(); } else { // The current paragraph is empty, so we simply ignore it. } } } else { // This is tagged text getting added to the current line we are building. currentRuns.Add(new ClassifiedTextRun(part.Tag.ToClassificationTypeName(), part.Text)); } } if (currentRuns.Count > 0) { // Add the final line to the final paragraph. currentParagraph.Add(new ClassifiedTextElement(currentRuns)); } if (currentParagraph.Count > 0) { // Add the final paragraph to the result. paragraphs.Add(CreateParagraphFromLines(currentParagraph)); } return(paragraphs); }
private static ClassifiedTextElement BuildClassifiedTextElement(QuickInfoSection section) { return(new ClassifiedTextElement(section.TaggedParts.Select( part => new ClassifiedTextRun(part.Tag.ToClassificationTypeName(), part.Text)))); }