📄 ui/tests/TestGraph.cs
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace Cfa.Ui.Tests;

internal static class TestGraph
{
    public static CallGraphAnalysis Create()
    {
        var tree = CSharpSyntaxTree.ParseText(
            """
            class Flow
            {
                void Request(int id) { }
                void Entry(int id) { }
                void Validate(int id) { }
                void Handle(int id) { }
                void Save(int id) { }
            }
            """,
            path: "/repo/Flow.cs"
        );
        var compilation = CSharpCompilation.Create(
            "Example",
            [tree],
            [MetadataReference.CreateFromFile(typeof(object).Assembly.Location)],
            new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
        );
        var members = compilation
            .GetTypeByMetadataName("Flow")!
            .GetMembers()
            .OfType<IMethodSymbol>()
            .ToDictionary(method => method.Name);
        var outgoing = ImmutableDictionary.CreateBuilder<ISymbol, IImmutableList<CallAnalysis>>(
            SymbolEqualityComparer.Default
        );
        var incoming = ImmutableDictionary.CreateBuilder<ISymbol, IImmutableList<CallAnalysis>>(
            SymbolEqualityComparer.Default
        );
        outgoing[members["Entry"]] =
        [
            new(members["Validate"], LinkKind.Direct, CallReach.SameType),
            new(members["Handle"], LinkKind.Event, CallReach.CrossAssembly),
        ];
        outgoing[members["Handle"]] = [new(members["Save"], LinkKind.Direct, CallReach.SameType)];
        outgoing[members["Save"]] = [new(members["Save"], LinkKind.Direct, CallReach.SameType)];
        incoming[members["Entry"]] = [new(members["Request"], LinkKind.Direct, CallReach.CrossAssembly)];
        var appearances = ImmutableDictionary.CreateBuilder<ISymbol, uint>(SymbolEqualityComparer.Default);
        foreach (var member in members.Values)
        {
            appearances[member] = 1;
        }
        return new(members["Entry"], outgoing.ToImmutable(), incoming.ToImmutable(), appearances.ToImmutable());
    }
}