From 355f429c856fbcfbe151e1586485f77297a47631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Magyar?= Date: Fri, 22 May 2026 09:22:53 +0100 Subject: [PATCH] fix(lang-kotlin): overload target-id selection by parameter types (#1761) (#1777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same-arity Kotlin class-method overloads collapsed onto whichever node was registered first. `lookup("alice")` resolved to `lookup(Int)` — not because the picker chose wrong, but because `resolveDefGraphId` fell through to the simple-name fallback after its parameter-typed key lookup missed. Root cause: `populateKotlinOwners` (which calls `populateClassOwnedMembers`) assigned `ownerId` and qualified names to class-owned function defs but left `def.type === 'Function'`. The graph parsing-processor, in contrast, emits a `Method` node label for class members. `resolveDefGraphId`'s parameter-typed key lookup is gated on `def.type === 'Method'` (graph-bridge/ids.ts:108-116), so it was skipped for every Kotlin class method. With the type-keyed lookup skipped, the resolver fell through to `simpleKey`, which is first-wins by registration order — and the Int overload always registered first in these fixtures. Fix: `populateKotlinOwners` now upgrades `def.type` from `Function` to `Method` after `populateClassOwnedMembers` assigns `ownerId`. This aligns the scope-resolution model with the graph's node labels so parameter-typed key registration and lookup operate in the same keyspace. Picker logic in `pickImplicitThisOverload` / `narrowOverloadCandidates` was already correct — verified by trace: it narrowed `lookup("alice")` to the `[String]` def. Only the graph-id lookup was broken. Verification (REGISTRY_PRIMARY_KOTLIN=1): - Forced-mode: 21 -> 18 failing of 175 (3 fewer; tests 1620, 1659, 1692 in `test/integration/resolvers/kotlin.test.ts` now green). - Default-mode Kotlin: 175/175 unchanged. - Full resolver suite: 2216/2216 unchanged. - Remaining 18 failures are tracked by sibling sub-issues (#1758, #1759, #1760, #1762, #1763). Does NOT add Kotlin to MIGRATED_LANGUAGES per parent #1746 flip criteria. Closes #1761. Refs #1746. Co-authored-by: Test --- .../core/ingestion/languages/kotlin/owners.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/gitnexus/src/core/ingestion/languages/kotlin/owners.ts b/gitnexus/src/core/ingestion/languages/kotlin/owners.ts index db6ddf6322..f034bafd78 100644 --- a/gitnexus/src/core/ingestion/languages/kotlin/owners.ts +++ b/gitnexus/src/core/ingestion/languages/kotlin/owners.ts @@ -4,6 +4,29 @@ import { isClassLike, populateClassOwnedMembers } from '../../scope-resolution/s export function populateKotlinOwners(parsed: ParsedFile): void { populateClassOwnedMembers(parsed); populateCompanionMembersOnEnclosingClass(parsed); + upgradeClassOwnedFunctionsToMethods(parsed); +} + +/** + * Align scope-resolution `def.type` with the graph's node-label + * conventions: a `Function` def that lives inside a class body becomes + * a `Method`. The Kotlin extractor labels every `function_declaration` + * as `Function`, but the graph parsing-processor emits a `Method` + * graph-node label for class members. Without this realignment, + * `resolveDefGraphId`'s parameter-typed key lookup (gated on + * `def.type === 'Method'`) falls through to the simple-name fallback + * for class methods, collapsing same-name same-arity overloads onto + * the first-registered node (#1761). + * + * Only Method-bearing types are touched. Methods have a class owner + * (set by `populateClassOwnedMembers`) and a class-qualified name. + */ +function upgradeClassOwnedFunctionsToMethods(parsed: ParsedFile): void { + for (const def of parsed.localDefs) { + if (def.type !== 'Function') continue; + if (def.ownerId === undefined) continue; + (def as { type: SymbolDefinition['type'] }).type = 'Method'; + } } function populateCompanionMembersOnEnclosingClass(parsed: ParsedFile): void {