📄 SyntaxNodeStatementReachability.cs
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Reacher;

internal static class SyntaxNodeStatementReachability
{
    public static bool IsReachable(this SemanticModel semanticModel, SyntaxNode syntaxNode)
    {
        var statement = syntaxNode
            .AncestorsAndSelf()
            .TakeWhile(AscendWithinMember)
            .OfType<StatementSyntax>()
            .FirstOrDefault();
        if (statement is null)
        {
            return syntaxNode
                .AncestorsAndSelf()
                .TakeWhile(AscendWithinMember)
                .Any(n => n.IsKind(SyntaxKind.ArrowExpressionClause));
        }

        var controlFlowAnalysis = semanticModel.AnalyzeControlFlow(statement);
        return controlFlowAnalysis?.StartPointIsReachable is true;
    }

    private static bool AscendWithinMember(SyntaxNode syntax) =>
        !(
            syntax.IsKind(SyntaxKind.LocalFunctionStatement)
            || syntax.IsKind(SyntaxKind.MethodDeclaration)
            || syntax.IsKind(SyntaxKind.PropertyDeclaration)
            || syntax.IsKind(SyntaxKind.IndexerDeclaration)
            || syntax.IsKind(SyntaxKind.ConstructorDeclaration)
        );
}