fix(extract): emit Java enum and annotation declarations as type nodes (#1512)

Java `enum` and `@interface` (annotation) declarations weren't in _JAVA_CONFIG's
class_types, so they were never emitted as type nodes — a field typed as an enum or
a class annotated with a project annotation referenced a node that didn't exist
(dangling). enum_declaration and annotation_type_declaration are now extracted as
first-class (sourced) type nodes, so those references resolve onto them.

Ported from PR #1513 by @oleksii-tumanov.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
oleksii-tumanov
2026-06-28 10:31:22 +01:00
committed by safishamsi
co-authored by Claude Opus 4.8
parent 1b994965bb
commit 940cb53f4d
2 changed files with 35 additions and 1 deletions
+5 -1
View File
@@ -2065,7 +2065,11 @@ _JAVA_CONFIG = LanguageConfig(
ts_module="tree_sitter_java",
# record_declaration shares class_declaration's name/body/interfaces fields,
# so it becomes a first-class type node instead of an isolated file (#1373).
class_types=frozenset({"class_declaration", "interface_declaration", "record_declaration"}),
# Enums and annotation declarations use the same name/body contract.
class_types=frozenset({
"class_declaration", "interface_declaration", "record_declaration",
"enum_declaration", "annotation_type_declaration",
}),
function_types=frozenset({"method_declaration", "constructor_declaration"}),
import_types=frozenset({"import_declaration"}),
# object_creation_expression (`new Foo(...)`) is handled by a dedicated Java
+30
View File
@@ -399,6 +399,36 @@ def test_java_type_annotations_have_attribute_context(tmp_path):
assert ("CheckoutService", "Entity") in refs
def test_java_enum_and_annotation_declarations_are_type_nodes(tmp_path):
source = tmp_path / "TypeDeclarations.java"
source.write_text(
"enum PaymentStatus { PENDING, PAID }\n"
"@interface Audited {}\n"
"class Order { PaymentStatus status; }\n"
"@Audited class CheckoutService {}\n"
)
result = extract_java(source)
assert ("TypeDeclarations.java", "PaymentStatus") in _edge_labels(
result, "contains"
)
assert ("TypeDeclarations.java", "Audited") in _edge_labels(result, "contains")
assert ("Order", "PaymentStatus") in _edge_labels(
result, "references", "field"
)
assert ("CheckoutService", "Audited") in _edge_labels(
result, "references", "attribute"
)
definitions = {
node["label"]: node
for node in result["nodes"]
if node.get("label") in {"PaymentStatus", "Audited"}
}
assert definitions["PaymentStatus"].get("source_file") == str(source)
assert definitions["Audited"].get("source_file") == str(source)
def test_csharp_field_type_references_have_field_context():
r = extract_csharp(FIXTURES / "sample.cs")
refs = _references(r)