From 0774ecde2ac1fb9f2eebf3612d9cb6a55fc2ccff Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Sun, 1 Nov 2026 20:36:07 +0100 Subject: [PATCH] fix(doc-links): an unnamed Kotlin companion reads its own definition An unnamed companion now has a node, but the scope looked a definition up only by a name token, which it does not have. [Type.Companion] stayed a graph gap with the node right there. RED: doc_mentions_jvm_kotlin_scope_blob, doc_mentions_jvm_kotlin_companion_inherits. Signed-off-by: Martin Vogel --- internal/cbm/doclink_jvm.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/internal/cbm/doclink_jvm.c b/internal/cbm/doclink_jvm.c index b33d37f75..b55f3d107 100644 --- a/internal/cbm/doclink_jvm.c +++ b/internal/cbm/doclink_jvm.c @@ -56,10 +56,10 @@ * when that definition is the one the graph keeps for the qualified name * inside this file. Both are read off the extractor's own definitions (same * start line, name and kind), so this file models neither the qualified-name - * scheme nor its collisions: Kotlin flattens nested types and puts class - * properties at module level, Java names a field after its whole declarator - * (`MAX = 10`), overloads share one name, and whatever the scheme does next is - * followed without a change here. + * scheme nor its collisions: a Kotlin nested type and a member function of one + * name share one, Java names a field after its whole declarator (`MAX = 10`), + * overloads share one name, and whatever the scheme does next is followed + * without a change here. * pnames (the parameter names of a callable, the primary-constructor * parameters of a Kotlin class) and all line numbers serve the file's own * references only: the persisted form drops them. @@ -2697,15 +2697,22 @@ static char jv_kotlin_type_kind(const jv_scan_t *s, TSNode decl, TSNode body) { return 'c'; } +#define JV_KOTLIN_COMPANION "Companion" + static void jv_kotlin_type(jv_scan_t *s, TSNode decl, const jv_frame_t *outer, int depth) { TSNode body = jv_kotlin_body(decl); char kind = jv_kotlin_type_kind(s, decl, body); TSNode name_node = jv_child(decl, "type_identifier"); const char *raw = NULL; size_t raw_len = 0; - const char *name = (kind == 'C' && ts_node_is_null(name_node)) - ? "Companion" - : jv_name_of(s, name_node, &raw, &raw_len); + const char *name = NULL; + if (kind == 'C' && ts_node_is_null(name_node)) { + /* no name token, but the extractor names its definition the same way */ + name = raw = JV_KOTLIN_COMPANION; + raw_len = sizeof(JV_KOTLIN_COMPANION) - SKIP_ONE; + } else { + name = jv_name_of(s, name_node, &raw, &raw_len); + } if (!name) { return; }