private static QuickInfoItem?BuildQuickInfoDirectives(SyntaxToken token, CancellationToken cancellationToken) { if (token.Parent is DirectiveTriviaSyntax directiveTrivia) { if (directiveTrivia is EndRegionDirectiveTriviaSyntax) { var regionStart = directiveTrivia.GetMatchingDirective(cancellationToken); if (regionStart is not null) { return(QuickInfoItem.Create(token.Span, relatedSpans: ImmutableArray.Create(regionStart.Span))); } } else if (directiveTrivia is ElifDirectiveTriviaSyntax or ElseDirectiveTriviaSyntax or EndIfDirectiveTriviaSyntax) { var matchingDirectives = directiveTrivia.GetMatchingConditionalDirectives(cancellationToken); var matchesBefore = matchingDirectives .TakeWhile(d => d.SpanStart < directiveTrivia.SpanStart) .Select(d => d.Span) .ToImmutableArray(); if (matchesBefore.Length > 0) { return(QuickInfoItem.Create(token.Span, relatedSpans: matchesBefore)); } } } return(null); }
protected override async Task <QuickInfoItem?> BuildQuickInfoAsync( Document document, SyntaxToken token, CancellationToken cancellationToken ) { if (token.Kind() != SyntaxKind.CloseBraceToken) { return(null); } // Don't show for interpolations if ( token.Parent.IsKind( SyntaxKind.Interpolation, out InterpolationSyntax? interpolation ) && interpolation.CloseBraceToken == token ) { return(null); } // Now check if we can find an open brace. var parent = token.Parent !; var openBrace = parent .ChildNodesAndTokens() .FirstOrDefault(n => n.Kind() == SyntaxKind.OpenBraceToken) .AsToken(); if (openBrace.Kind() != SyntaxKind.OpenBraceToken) { return(null); } var spanStart = parent.SpanStart; var spanEnd = openBrace.Span.End; // If the parent is a scope block, check and include nearby comments around the open brace // LeadingTrivia is preferred if (IsScopeBlock(parent)) { MarkInterestedSpanNearbyScopeBlock(parent, openBrace, ref spanStart, ref spanEnd); } // If the parent is a child of a property/method declaration, object/array creation, or control flow node, // then walk up one higher so we can show more useful context else if (parent.GetFirstToken() == openBrace) { // parent.Parent must be non-null, because for GetFirstToken() to have returned something it would have had to walk up to its parent spanStart = parent.Parent !.SpanStart; } // encode document spans that correspond to the text to show var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var spans = ImmutableArray.Create(TextSpan.FromBounds(spanStart, spanEnd)); return(QuickInfoItem.Create(token.Span, relatedSpans: spans)); }
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() )); }