File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\CSharp\Services\SyntaxFacts\CSharpBlockFacts.cs
Web Access
Project: src\src\Workspaces\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Workspaces.csproj (Microsoft.CodeAnalysis.CSharp.Workspaces)
// 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 System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.LanguageService;
 
internal class CSharpBlockFacts : AbstractBlockFacts<StatementSyntax>
{
    public static readonly CSharpBlockFacts Instance = new();
 
    public override bool IsScopeBlock([NotNullWhen(true)] SyntaxNode? node)
        => node.IsKind(SyntaxKind.Block);
 
    public override bool IsExecutableBlock([NotNullWhen(true)] SyntaxNode? node)
        => node is (kind: SyntaxKind.Block or SyntaxKind.SwitchSection or SyntaxKind.CompilationUnit);
 
    public override SyntaxNode? GetImmediateParentExecutableBlockForStatement(StatementSyntax statement)
        => statement.Parent switch
        {
            BlockSyntax block => block,
            SwitchSectionSyntax switchSection => switchSection,
            GlobalStatementSyntax globalStatement => globalStatement.Parent,
            _ => null,
        };
 
    public override IReadOnlyList<StatementSyntax> GetExecutableBlockStatements(SyntaxNode? node)
    {
        return node switch
        {
            BlockSyntax block => block.Statements,
            SwitchSectionSyntax switchSection => switchSection.Statements,
            CompilationUnitSyntax compilationUnit => compilationUnit.Members.OfType<GlobalStatementSyntax>().SelectAsArray(globalStatement => globalStatement.Statement),
            _ => throw ExceptionUtilities.UnexpectedValue(node),
        };
    }
 
    public override SyntaxNode? FindInnermostCommonExecutableBlock(IEnumerable<SyntaxNode> nodes)
        => nodes.FindInnermostCommonNode(IsExecutableBlock);
 
    public override bool IsStatementContainer([NotNullWhen(true)] SyntaxNode? node)
        => IsExecutableBlock(node) || node.IsEmbeddedStatementOwner();
 
    public override IReadOnlyList<StatementSyntax> GetStatementContainerStatements(SyntaxNode? node)
    {
        if (IsExecutableBlock(node))
            return GetExecutableBlockStatements(node);
        else if (node.GetEmbeddedStatement() is { } embeddedStatement)
            return [embeddedStatement];
        else
            return [];
    }
}