Repository navigation
Description
Version
Built from source, main @ 9b24332 (v0.10.8-181)
Platform / Install channel / Binary variant
Linux (x64) / Built from source / standard
What happened, and what did you expect?
A Scala class Foo and its companion object Foo share the source name, so both containers and their members get the same qualified name and overwrite each other in the graph. Whichever is extracted last wins; methods of the other one disappear, and CALLS edges to them are lost or bound to the wrong owner. Class-body val/var definitions are not qualified by their declaring owner either, so members of the class and the companion collide as well.
Expected: the companion object gets a distinct qualified name (the conventional Foo$, as used by scalac and most Scala tooling), everywhere a class QN is computed, and body-level val/var are qualified by their owner.
Reproduction
- Dummy snippet (
t/ValidateMandatoryInvoiceNumber.scala):
case class ValidateMandatoryInvoiceNumber private (invoice: Invoice) {
override lazy val isValid: Boolean = invoice.number.isDefined
def isMandatory: Boolean = true
}
case object ValidateMandatoryInvoiceNumber {
def createComponentTasks(invoice: Invoice) =
List(ValidateMandatoryInvoiceNumber(invoice))
}-
Command:
codebase-memory-mcp cli index_repository '{"repo_path":"/tmp/repro"}'then
codebase-memory-mcp cli search_graph '{"project":"repro","name_pattern":"ValidateMandatoryInvoiceNumber.*"}' -
Result: a single container
t.ValidateMandatoryInvoiceNumber.ValidateMandatoryInvoiceNumber; only one ofisValid/isMandatoryvscreateComponentTaskssurvives.
Expected:…ValidateMandatoryInvoiceNumber(class, withisValid,isMandatory) and…ValidateMandatoryInvoiceNumber$(object, withcreateComponentTasks).
Proposed fix
Use the Foo$ suffix for the companion in every QN computation and qualify class-body val/var by their declaring owner. One commit with extraction + pipeline tests. It is stacked on the Scala import/package work (#2153) because the tests share fixtures; branch:
https://github.com/htarnacki/codebase-memory-mcp/tree/feat/scala-receiver-resolution (second commit).
Confirmations
- I searched existing issues and this is not a duplicate.
- My reproduction uses shareable code (a dummy snippet), not proprietary code.
Activity
DeusData commentedon Sep 25, 2026
Hi @htarnacki, thank you so much for this report and for already writing the fix. The repro makes the collision obvious, and following scalac's
Foo$convention is a natural way to keep both the class and its companion findable.Since you've already done the work (commit 84c6ea7 on
feat/scala-receiver-resolution), we'd much rather merge your change, with your authorship, than re-implement it. Could you open it as a PR stacked on the #2153 one (see my note there)? Both would need a rebase onto currentmain, which has moved a lot since 09-09. Please keep the receiver-resolution commits for separate PRs so each stays small and easy to review.One question we'd like your view on: should a standalone
object Foowith no companion class also get the$suffix, or only a companion? The first changes the qualified name of every Scala object in existing graphs. Thanks again, your Scala work is a real gift to graph quality here!htarnacki commentedon Sep 26, 2026
Opened #2361, stacked on #2360.
On the standalone-object question: only companions get the
$suffix. A standaloneobject Foohas nothing to collide with, and suffixing it would rename every Scala object in existing graphs. With this rule the only QNs that change are the ones that were previously lost to a collision. Details and the finagle before/after are in the PR.fix(scala): keep companion objects distinct from their classes
fix(scala): suppress weak short-name matches for receiver calls
fix(scala): keep companion objects distinct from their classes
fix(scala): suppress weak short-name matches for receiver calls
fix(scala): suppress weak short-name matches for receiver calls
fix(scala): suppress weak short-name matches for receiver calls
DeusData commentedon Oct 19, 2026
Thank you for opening #2361 and clarifying that only colliding companion objects get the suffix. That answers the question raised above; there is no new verified review or landing status to add in this triage.
DeusData commentedon Oct 25, 2026
Thank you for #2361 and the companion-only suffix clarification. The next review is on our side; that question has already been answered. Sorry for the delay; I’ll follow up soon.