File: BraceMatching\IBraceMatchingServiceExtensions.cs
Web Access
Project: src\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.BraceMatching;
 
internal static class IBraceMatchingServiceExtensions
{
    public static async Task<TextSpan?> FindMatchingSpanAsync(
        this IBraceMatchingService service,
        Document document,
        int position,
        BraceMatchingOptions options,
        CancellationToken cancellationToken)
    {
        // These are the matching spans when checking the token to the right of the position.
        var braces1 = await service.GetMatchingBracesAsync(document, position, options, cancellationToken).ConfigureAwait(false);
 
        // These are the matching spans when checking the token to the left of the position.
        BraceMatchingResult? braces2 = null;
 
        // Ensure caret is valid at left of position.
        if (position > 0)
        {
            braces2 = await service.GetMatchingBracesAsync(document, position - 1, options, cancellationToken).ConfigureAwait(false);
        }
 
        // Favor matches where the position is on the outside boundary of the braces. i.e. if we
        // have:  {^()}  
        //
        // then this would return the  ()  not the  {}
        if (braces1.HasValue && position >= braces1.Value.LeftSpan.Start && position < braces1.Value.LeftSpan.End)
        {
            // ^{ } -- return right span
            return braces1.Value.RightSpan;
        }
        else if (braces2.HasValue && position > braces2.Value.RightSpan.Start && position <= braces2.Value.RightSpan.End)
        {
            // { }^ -- return left span
            return braces2.Value.LeftSpan;
        }
        else if (braces2.HasValue && position > braces2.Value.LeftSpan.Start && position <= braces2.Value.LeftSpan.End)
        {
            // {^ } -- return right span
            return braces2.Value.RightSpan;
        }
        else if (braces1.HasValue && position >= braces1.Value.RightSpan.Start && position < braces1.Value.RightSpan.End)
        {
            // { ^} - return left span
            return braces1.Value.LeftSpan;
        }
 
        return null;
    }
}