Ctrl K
ComunidadGuías…

tests/test_csharp_delegate_declarations.py

Rama v8 · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""A C# `delegate` is a named type and must be extracted as a sourced node.

`public delegate int BinOp(int a, int b);` was in neither `class_types` nor
`function_types`, so the declaration was dropped. But a field or parameter typed
as the delegate (`BinOp Op;`) still ran the name `BinOp` through
`ensure_named_node`, which minted a *sourceless* stub node and pointed the
`references` edge at it — even though `BinOp` is declared in the very same file.
That is a provenance violation (a real source-backed declaration losing to a
sourceless god node). Adding `delegate_declaration` to the C# `class_types` emits
a clean empty type node (it has a `name` field and no body) that the in-file
references bind to instead.
"""
from __future__ import annotations

from pathlib import Path

from graphify.extract import extract


def _extract(tmp_path, body: str):
    (tmp_path / "d.cs").write_text(body)
    return extract([tmp_path / "d.cs"], cache_root=tmp_path, parallel=False)


def _node(r, label):
    return next((n for n in r["nodes"] if n.get("label") == label), None)


def test_delegate_is_a_sourced_node_not_a_sourceless_stub(tmp_path):
    r = _extract(
        tmp_path,
        "public delegate int BinOp(int a, int b);\n"
        "public class Calc {\n"
        "    public BinOp Op;\n"
        "    public int Apply(BinOp f, int x) { return f(x, x); }\n"
        "}\n",
    )
    binop = _node(r, "BinOp")
    assert binop is not None, "delegate declaration was dropped"
    assert binop.get("source_file"), (
        f"delegate BinOp is a sourceless god node: {binop}"
    )
    # No sourceless node is left over for a type that is declared in-file.
    assert not any(
        (not n.get("source_file")) and n.get("label") == "BinOp"
        for n in r["nodes"]
    )
    # The field/parameter references now bind to the real sourced delegate node.
    refs_to_binop = {
        e["source"]
        for e in r["edges"]
        if e["relation"] == "references" and e["target"] == binop["id"]
    }
    assert refs_to_binop, "references to the delegate did not bind to it"


def test_namespaced_delegate_is_scoped_and_sourced(tmp_path):
    r = _extract(
        tmp_path,
        "namespace App {\n"
        "    public delegate void Handler(string msg);\n"
        "    public class Bus { public Handler OnMsg; }\n"
        "}\n",
    )
    handler = _node(r, "Handler")
    assert handler is not None and handler.get("source_file")
    assert any(
        e["relation"] == "references" and e["target"] == handler["id"]
        for e in r["edges"]
    )