diff --git a/src/Features/CSharp/Portable/BraceMatching/BlockCommentBraceMatcher.cs b/src/Features/CSharp/Portable/BraceMatching/BlockCommentBraceMatcher.cs index fc03a7203d271..d86d976e03576 100644 --- a/src/Features/CSharp/Portable/BraceMatching/BlockCommentBraceMatcher.cs +++ b/src/Features/CSharp/Portable/BraceMatching/BlockCommentBraceMatcher.cs @@ -14,33 +14,52 @@ namespace Microsoft.CodeAnalysis.CSharp.BraceMatching; [ExportBraceMatcher(LanguageNames.CSharp), Shared] -internal class BlockCommentBraceMatcher : IBraceMatcher +[method: ImportingConstructor] +[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] +internal sealed class BlockCommentBraceMatcher() : IBraceMatcher { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public BlockCommentBraceMatcher() - { - } - public async Task FindBracesAsync(Document document, int position, BraceMatchingOptions options, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var token = root.FindToken(position, findInsideTrivia: false); + if (token == default) + return null; + + var span = token.Span; + if (span.Contains(position)) + return null; + var text = await document.GetValueTextAsync(cancellationToken).ConfigureAwait(false); - var trivia = root.FindTrivia(position); - if (trivia.Kind() is SyntaxKind.MultiLineCommentTrivia && - trivia.ToString() is ['/', '*', .., '*', '/']) - { - return new BraceMatchingResult(new TextSpan(trivia.SpanStart, "/*".Length), TextSpan.FromBounds(trivia.Span.End - "*/".Length, trivia.Span.End)); - } - else if (trivia.Kind() is SyntaxKind.MultiLineDocumentationCommentTrivia) - { - var startBrace = new TextSpan(trivia.FullSpan.Start, "/**".Length); - var endBrace = TextSpan.FromBounds(trivia.FullSpan.End - "*/".Length, trivia.FullSpan.End); - if (text.ToString(startBrace) == "/**" && text.ToString(endBrace) == "*/") - return new BraceMatchingResult(startBrace, endBrace); - } + if (position < token.SpanStart) + return FindBraces(token.LeadingTrivia); + else if (position >= token.Span.End) + return FindBraces(token.TrailingTrivia); return null; + + BraceMatchingResult? FindBraces(SyntaxTriviaList triviaList) + { + foreach (var trivia in triviaList) + { + if (trivia.FullSpan.Contains(position)) + { + if (trivia.Kind() is SyntaxKind.MultiLineCommentTrivia && + trivia.ToString() is ['/', '*', .., '*', '/']) + { + return new BraceMatchingResult(new TextSpan(trivia.SpanStart, "/*".Length), TextSpan.FromBounds(trivia.Span.End - "*/".Length, trivia.Span.End)); + } + else if (trivia.Kind() is SyntaxKind.MultiLineDocumentationCommentTrivia) + { + var startBrace = new TextSpan(trivia.FullSpan.Start, "/**".Length); + var endBrace = TextSpan.FromBounds(trivia.FullSpan.End - "*/".Length, trivia.FullSpan.End); + if (text.ToString(startBrace) == "/**" && text.ToString(endBrace) == "*/") + return new BraceMatchingResult(startBrace, endBrace); + } + } + } + + return null; + } } }