diff --git a/graphify/extractors/engine.py b/graphify/extractors/engine.py index 723606e64..7a2470f21 100644 --- a/graphify/extractors/engine.py +++ b/graphify/extractors/engine.py @@ -969,7 +969,8 @@ def _scala_collect_type_refs(node, source: bytes, generic: bool, out: list[tuple _scala_collect_type_refs(arg, source, True, out) return if t in ("compound_type", "infix_type", "function_type", "tuple_type", - "annotated_type", "projected_type"): + "annotated_type", "projected_type", "match_type", + "type_case_clause"): for c in node.children: if c.is_named: _scala_collect_type_refs(c, source, generic, out) @@ -3074,8 +3075,11 @@ def _emit_java_parent_type(type_node, rel: str, at_line: int) -> None: type_table[prop_name] = prop_type return + # type_definition covers plain aliases (`type Alias = List[Int]`), + # `opaque type`, and match types — the right-hand side sits under the + # same `type` field a val/var annotation uses, so the walk is shared. if (config.ts_module == "tree_sitter_scala" - and t in ("val_definition", "var_definition") + and t in ("val_definition", "var_definition", "type_definition") and parent_class_nid): type_node = node.child_by_field_name("type") if type_node is not None: diff --git a/tests/fixtures/sample.scala b/tests/fixtures/sample.scala index 8a35888d8..4c1867e71 100644 --- a/tests/fixtures/sample.scala +++ b/tests/fixtures/sample.scala @@ -27,3 +27,12 @@ object HttpClientFactory { new HttpClient(Config(baseUrl, 30)) } } + +class TypeAliases { + type Routes = Map[String, HttpClient] + opaque type ClientId = Long + type Unwrap[X] = X match { + case Option[t] => t + case ListBuffer[t] => t + } +} diff --git a/tests/test_languages.py b/tests/test_languages.py index aff689d2a..85dd3eaaf 100644 --- a/tests/test_languages.py +++ b/tests/test_languages.py @@ -765,6 +765,24 @@ def test_scala_method_return_type_context(): assert ("create", "HttpClient") in _edge_labels(r, "references", "return_type") +def test_scala_type_alias_rhs_references(): + r = extract_scala(FIXTURES / "sample.scala") + assert ("TypeAliases", "Map") in _edge_labels(r, "references", "field") + assert ("TypeAliases", "HttpClient") in _edge_labels(r, "references", "generic_arg") + + +def test_scala_opaque_type_rhs_references(): + r = extract_scala(FIXTURES / "sample.scala") + assert ("TypeAliases", "Long") in _edge_labels(r, "references", "field") + + +def test_scala_match_type_case_references(): + r = extract_scala(FIXTURES / "sample.scala") + labels = _edge_labels(r, "references", "field") + assert ("TypeAliases", "Option") in labels + assert ("TypeAliases", "ListBuffer") in labels + + def test_scala_call_edges_have_call_context(): r = extract_scala(FIXTURES / "sample.scala") call_edges = _edges_with_relation(r, "calls")