fix(kotlin): keep annotated inferred properties in the graph

An annotation on a class property with no explicit type never assigned
`line`, so the annotation loop raised UnboundLocalError and _safe_extract
dropped the whole file. Set `line` before the type-node check so the file
and its attribute edge both survive.

Fixes #3884

Co-Authored-By: Grok 4.7 <noreply@x.ai>
This commit is contained in:
nothariharanandGrok 4.7 committed 2026-09-29 08:04:59 +05:30
1 parent d6eaa8aae8
commit 03ba8cc9a3
2 files changed
+54 -1

No files matched your search

+5 -1
View File
@@ -4855,9 +4855,13 @@ def _extract_generic(
# Field-type references stay class-gated: top-level properties keep
# their pre-#2565 (no-references) behavior unchanged.
if parent_class_nid:
# #3884: the annotation loop below also reads `line`. An annotated
# property with an inferred type has no type node, so assigning
# `line` only inside that branch raised UnboundLocalError and
# _safe_extract dropped the whole file.
line = node.start_point[0] + 1
type_node = _kotlin_property_type_node(node)
if type_node is not None:
line = node.start_point[0] + 1
refs: list[tuple[str, str]] = []
_kotlin_collect_type_refs(type_node, source, False, refs)
for ref_name, role in refs:
+49
View File
@@ -657,3 +657,52 @@ def test_kotlin_object_member_call_survives_incremental_rebuild(tmp_path):
assert _rebuild_code(corpus, changed_paths=[app], no_cluster=True,
acquire_lock=False) is True
assert _resolves(), "call stays resolved after an incremental rebuild"
def test_kotlin_annotated_inferred_property_keeps_the_file(tmp_path):
"""#3884: `@Volatile var counter = 0` has an annotation and no explicit type.
`line` used to be assigned only when a type node existed, so the annotation
loop raised UnboundLocalError and _safe_extract dropped every node in the file.
"""
r = _extract(tmp_path, {
"Repro.kt": (
"class Repro {\n"
" @Volatile\n"
" var counter = 0\n"
"\n"
" fun ping() { }\n"
"}\n"
),
})
assert r["failed_sources"] == [], "the file must not be skipped"
repro = _find(r, "Repro")
ping = _find(r, ".ping()")
volatile = _find(r, "Volatile")
attr = [e for e in r["edges"]
if e["relation"] == "references"
and e["source"] == repro
and e["target"] == volatile
and e.get("context") == "attribute"]
assert attr, "the annotation is a references edge on the class"
assert any(e["relation"] == "method" and e["source"] == repro and e["target"] == ping
for e in r["edges"]), "a sibling method in the same file must survive"
def test_kotlin_annotated_explicit_type_property_still_references(tmp_path):
"""Control for #3884: an annotation plus an explicit type already worked."""
r = _extract(tmp_path, {
"Typed.kt": (
"class Typed {\n"
" @Volatile\n"
" var counter: Int = 0\n"
"}\n"
),
})
typed = _find(r, "Typed")
volatile = _find(r, "Volatile")
assert any(e["relation"] == "references"
and e["source"] == typed
and e["target"] == volatile
and e.get("context") == "attribute"
for e in r["edges"])