File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\CSharp\Formatting\Rules\BaseFormattingRule.cs
Web Access
Project: src\src\CodeStyle\CSharp\Analyzers\Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj (Microsoft.CodeAnalysis.CSharp.CodeStyle)
// 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.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.Formatting;
 
internal abstract class BaseFormattingRule : AbstractFormattingRule
{
    protected static void AddUnindentBlockOperation(
        List<IndentBlockOperation> list,
        SyntaxToken startToken,
        SyntaxToken endToken,
        TextSpan textSpan,
        IndentBlockOption option = IndentBlockOption.RelativePosition)
    {
        if (startToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None)
        {
            return;
        }
 
        list.Add(FormattingOperations.CreateIndentBlockOperation(startToken, endToken, textSpan, indentationDelta: -1, option: option));
    }
 
    protected static void AddUnindentBlockOperation(
        List<IndentBlockOperation> list,
        SyntaxToken startToken,
        SyntaxToken endToken,
        bool includeTriviaAtEnd = false,
        IndentBlockOption option = IndentBlockOption.RelativePosition)
    {
        if (startToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None)
        {
            return;
        }
 
        if (includeTriviaAtEnd)
        {
            list.Add(FormattingOperations.CreateIndentBlockOperation(startToken, endToken, indentationDelta: -1, option: option));
        }
        else
        {
            var startPosition = CommonFormattingHelpers.GetStartPositionOfSpan(startToken);
            var endPosition = endToken.Span.End;
 
            list.Add(FormattingOperations.CreateIndentBlockOperation(startToken, endToken, TextSpan.FromBounds(startPosition, endPosition), indentationDelta: -1, option: option));
        }
    }
 
    protected static void AddAbsoluteZeroIndentBlockOperation(
        List<IndentBlockOperation> list,
        SyntaxToken startToken,
        SyntaxToken endToken,
        IndentBlockOption option = IndentBlockOption.AbsolutePosition)
    {
        if (startToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None)
        {
            return;
        }
 
        list.Add(FormattingOperations.CreateIndentBlockOperation(startToken, endToken, indentationDelta: 0, option: option));
    }
 
    protected static void AddIndentBlockOperation(
        List<IndentBlockOperation> list,
        SyntaxToken startToken,
        SyntaxToken endToken,
        IndentBlockOption option = IndentBlockOption.RelativePosition)
    {
        if (startToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None)
        {
            return;
        }
 
        list.Add(FormattingOperations.CreateIndentBlockOperation(startToken, endToken, indentationDelta: 1, option: option));
    }
 
    protected static void AddIndentBlockOperation(
        List<IndentBlockOperation> list,
        SyntaxToken startToken,
        SyntaxToken endToken,
        TextSpan textSpan,
        IndentBlockOption option = IndentBlockOption.RelativePosition)
    {
        if (startToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None)
        {
            return;
        }
 
        list.Add(FormattingOperations.CreateIndentBlockOperation(startToken, endToken, textSpan, indentationDelta: 1, option: option));
    }
 
    protected static void AddIndentBlockOperation(
        List<IndentBlockOperation> list,
        SyntaxToken baseToken,
        SyntaxToken startToken,
        SyntaxToken endToken,
        IndentBlockOption option = IndentBlockOption.RelativePosition)
    {
        list.Add(FormattingOperations.CreateRelativeIndentBlockOperation(baseToken, startToken, endToken, indentationDelta: 1, option: option));
    }
 
    protected static void SetAlignmentBlockOperation(
        List<IndentBlockOperation> list,
        SyntaxToken baseToken,
        SyntaxToken startToken,
        SyntaxToken endToken,
        IndentBlockOption option = IndentBlockOption.RelativePosition)
    {
        list.Add(FormattingOperations.CreateRelativeIndentBlockOperation(baseToken, startToken, endToken, indentationDelta: 0, option: option));
    }
 
    protected static void AddSuppressWrappingIfOnSingleLineOperation(ArrayBuilder<SuppressOperation> list, SyntaxToken startToken, SyntaxToken endToken, SuppressOption extraOption = SuppressOption.None)
        => AddSuppressOperation(list, startToken, endToken, SuppressOption.NoWrappingIfOnSingleLine | extraOption);
 
    protected static void AddSuppressAllOperationIfOnMultipleLine(ArrayBuilder<SuppressOperation> list, SyntaxToken startToken, SyntaxToken endToken, SuppressOption extraOption = SuppressOption.None)
        => AddSuppressOperation(list, startToken, endToken, SuppressOption.NoSpacingIfOnMultipleLine | SuppressOption.NoWrapping | extraOption);
 
    protected static void AddSuppressOperation(ArrayBuilder<SuppressOperation> list, SyntaxToken startToken, SyntaxToken endToken, SuppressOption option)
    {
        if (startToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None)
        {
            return;
        }
 
        list.Add(FormattingOperations.CreateSuppressOperation(startToken, endToken, option));
    }
 
    protected static void AddAnchorIndentationOperation(List<AnchorIndentationOperation> list, SyntaxToken anchorToken, SyntaxToken endToken)
    {
        if (anchorToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None)
        {
            return;
        }
 
        list.Add(FormattingOperations.CreateAnchorIndentationOperation(anchorToken, endToken));
    }
 
    protected static void AddAlignIndentationOfTokensToBaseTokenOperation(List<AlignTokensOperation> list, SyntaxNode containingNode, SyntaxToken baseNode, IEnumerable<SyntaxToken> tokens, AlignTokensOption option = AlignTokensOption.AlignIndentationOfTokensToBaseToken)
    {
        if (containingNode == null || tokens == null)
        {
            return;
        }
 
        list.Add(FormattingOperations.CreateAlignTokensOperation(baseNode, tokens, option));
    }
 
    protected static AdjustNewLinesOperation CreateAdjustNewLinesOperation(int line, AdjustNewLinesOption option)
        => FormattingOperations.CreateAdjustNewLinesOperation(line, option);
 
    protected static AdjustSpacesOperation CreateAdjustSpacesOperation(int space, AdjustSpacesOption option)
        => FormattingOperations.CreateAdjustSpacesOperation(space, option);
 
    protected static void AddBraceSuppressOperations(ArrayBuilder<SuppressOperation> list, SyntaxNode node)
    {
        var bracePair = node.GetBracePair();
        if (!bracePair.IsValidBracketOrBracePair())
        {
            return;
        }
 
        var firstTokenOfNode = node.GetFirstToken(includeZeroWidth: true);
 
        if (node is MemberDeclarationSyntax memberDeclNode)
        {
            (firstTokenOfNode, _) = memberDeclNode.GetFirstAndLastMemberDeclarationTokensAfterAttributes();
        }
 
        if (node.IsLambdaBodyBlock())
        {
            RoslynDebug.AssertNotNull(node.Parent);
 
            // include lambda itself.
            firstTokenOfNode = node.Parent.GetFirstToken(includeZeroWidth: true);
        }
        else if (node.IsKind(SyntaxKind.PropertyPatternClause))
        {
            // include the pattern recursive pattern syntax and/or subpattern
            firstTokenOfNode = firstTokenOfNode.GetPreviousToken();
        }
 
        // suppress wrapping on whole construct that owns braces and also brace pair itself if 
        // it is on same line
        AddSuppressWrappingIfOnSingleLineOperation(list, firstTokenOfNode, bracePair.closeBrace);
        AddSuppressWrappingIfOnSingleLineOperation(list, bracePair.openBrace, bracePair.closeBrace);
    }
}