diff --git a/graphify/extract.py b/graphify/extract.py index 0fdba70..f0a4927 100644 --- a/graphify/extract.py +++ b/graphify/extract.py @@ -3513,7 +3513,7 @@ def _extract_generic( context="generic_arg", metadata=metadata) # Java-specific: extends (superclass) / implements (interfaces) / interface-extends - if config.ts_module == "tree_sitter_java": + if config.ts_module in ("tree_sitter_java", "tree_sitter_groovy"): def _emit_java_parent(base_name: str, rel: str, at_line: int) -> None: if not base_name: return diff --git a/tests/fixtures/sample.groovy b/tests/fixtures/sample.groovy index 9a080ec..2e8bddc 100644 --- a/tests/fixtures/sample.groovy +++ b/tests/fixtures/sample.groovy @@ -19,3 +19,17 @@ class SampleService { processor.reset() } } + +interface Resettable { + void reset() +} + +class ExtendedService extends SampleService implements Resettable { + ExtendedService(Processor processor) { + super(processor) + } + + void reset() { + // no-op + } +} diff --git a/tests/test_languages.py b/tests/test_languages.py index 82fd1d6..b41c105 100644 --- a/tests/test_languages.py +++ b/tests/test_languages.py @@ -2195,6 +2195,35 @@ def test_groovy_no_dangling_edges(): assert e["source"] in node_ids +def test_groovy_extends_edge(): + """`class X extends Base` must emit an inherits edge. + + tree-sitter-groovy exposes inheritance via the same `superclass` field as + tree-sitter-java, but the inheritance handler was gated to Java only, so + Groovy extends/implements were silently dropped. + """ + r = extract_groovy(FIXTURES / "sample.groovy") + node_by_id = {n["id"]: n["label"] for n in r["nodes"]} + found = any( + "ExtendedService" in node_by_id.get(e["source"], "") + and "SampleService" in node_by_id.get(e["target"], "") + for e in r["edges"] if e["relation"] == "inherits" + ) + assert found, "ExtendedService should have inherits edge to SampleService" + + +def test_groovy_implements_edge(): + """`class X implements Iface` must emit an implements edge.""" + r = extract_groovy(FIXTURES / "sample.groovy") + node_by_id = {n["id"]: n["label"] for n in r["nodes"]} + found = any( + "ExtendedService" in node_by_id.get(e["source"], "") + and "Resettable" in node_by_id.get(e["target"], "") + for e in r["edges"] if e["relation"] == "implements" + ) + assert found, "ExtendedService should have implements edge to Resettable" + + def test_groovy_spock_finds_class(): r = extract_groovy(FIXTURES / "sample_spock.groovy") assert any("SampleSpec" in l for l in _labels(r))