File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\CSharp\Formatting\Rules\AnchorIndentationFormattingRule.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;
 
namespace Microsoft.CodeAnalysis.CSharp.Formatting;
 
internal class AnchorIndentationFormattingRule : BaseFormattingRule
{
    internal const string Name = "CSharp Anchor Indentation Formatting Rule";
 
    public override void AddAnchorIndentationOperations(List<AnchorIndentationOperation> list, SyntaxNode node, in NextAnchorIndentationOperationAction nextOperation)
    {
        nextOperation.Invoke();
 
        if (node.Kind() is SyntaxKind.SimpleLambdaExpression or SyntaxKind.ParenthesizedLambdaExpression)
        {
            AddAnchorIndentationOperation(list, node);
            return;
        }
 
        if (node.IsKind(SyntaxKind.AnonymousMethodExpression))
        {
            AddAnchorIndentationOperation(list, node);
            return;
        }
 
        if (node is BlockSyntax block)
        {
            // if it is not nested block, then its anchor will be first token that this block is
            // associated with. otherwise, "{" of block is the anchor token its children would follow
            if (block.Parent is null or BlockSyntax)
            {
                AddAnchorIndentationOperation(list, block);
                return;
            }
            else
            {
                AddAnchorIndentationOperation(list,
                    block.Parent.GetFirstToken(includeZeroWidth: true),
                    block.GetLastToken(includeZeroWidth: true));
                return;
            }
        }
 
        switch (node)
        {
            case StatementSyntax statement:
                AddAnchorIndentationOperation(list, statement);
                return;
            case UsingDirectiveSyntax usingNode:
                AddAnchorIndentationOperation(list, usingNode);
                return;
            case NamespaceDeclarationSyntax namespaceNode:
                AddAnchorIndentationOperation(list, namespaceNode);
                return;
            case TypeDeclarationSyntax typeNode:
                AddAnchorIndentationOperation(list, typeNode);
                return;
            case MemberDeclarationSyntax memberDeclNode:
                AddAnchorIndentationOperation(list, memberDeclNode);
                return;
            case AccessorDeclarationSyntax accessorDeclNode:
                AddAnchorIndentationOperation(list, accessorDeclNode);
                return;
            case SwitchExpressionArmSyntax switchExpressionArm:
                // The expression in a switch expression arm should be anchored to the beginning of the arm
                // ```
                // e switch
                // {
                // pattern:
                //         expression,
                // ```
                // We will keep the relative position of `expression` relative to `pattern:`. It will format to:
                // ```
                // e switch
                // {
                //     pattern:
                //             expression,
                // ```
                AddAnchorIndentationOperation(list, switchExpressionArm);
                return;
        }
    }
 
    private static void AddAnchorIndentationOperation(List<AnchorIndentationOperation> list, SyntaxNode node)
        => AddAnchorIndentationOperation(list, node.GetFirstToken(includeZeroWidth: true), node.GetLastToken(includeZeroWidth: true));
}