Repository navigation
Description
Version
0.8.1
Platform
macOS (Apple Silicon)
Install channel
GitHub release archive / install.sh / install.ps1
Binary variant
standard
What happened, and what did you expect?
For C++ out-of-line method definitions (void Foo::Bar() { ... } in a .cpp file), CALLS edges emitted from call sites inside the method body have source = Module (file-level node) instead of source = the enclosing Method node. This causes trace_path(direction=inbound) to return file paths rather than specific caller method names, and prevents multi-hop method-to-method BFS traversal.
Expected: CALLS edges should have source = Method("Foo::Bar"), matching how in-class definitions are handled.
Actual: CALLS edges have source = Module("path/to/file.cpp"). The calls_find_source() fallback to __file__ fires because call->enclosing_func_qn does not match the graph node's qualified name after PR #428 promoted out-of-line definitions from Function to Method (changing their QN).
Reproduction
Reproduction:
- Create a minimal C++ project:
// include/factory.h
#pragma once
class TileDataFactory {
public:
void CreateTileData(int level);
};
// src/factory.cpp
#include "factory.h"
void TileDataFactory::CreateTileData(int level) {} // out-of-line
// src/consumer.cpp
#include "factory.h"
class DataProvider {
public:
void ConvertBlob(); // in-class declaration
};
void DataProvider::ConvertBlob() { // out-of-line definition
TileDataFactory f;
f.CreateTileData(1); // <-- this call site
}- Index and query:
codebase-memory-mcp cli index_repository '{"repo_path": "/tmp/repro"}'
codebase-memory-mcp cli query_graph '{"query": "MATCH (src)-[:CALLS]->(dst {name: \"CreateTileData\"}) RETURN src.name, src.label, dst.name, dst.label", "project": "..."}'- Actual output:
src.name = "src/consumer.cpp",src.label = "Module" - Expected output:
src.name = "ConvertBlob",src.label = "Method"(withparent_class = DataProvider)
Root cause (from source inspection):
In src/pipeline/pass_calls.c L320–333, calls_find_source() first tries enclosing_func_qn:
static const cbm_gbuf_node_t *calls_find_source(ctx, rel, enclosing_qn) {
if (enclosing_qn) {
src = cbm_gbuf_find_by_qn(ctx->gbuf, enclosing_qn);
}
if (!src) {
// fallback to file-level Module
file_qn = cbm_pipeline_fqn_compute(ctx->project_name, rel, "__file__");
src = cbm_gbuf_find_by_qn(ctx->gbuf, file_qn);
}
}After PR #428 (commit a50b086), out-of-line method definitions are correctly promoted from Function to Method with a class-qualified QN. However, call->enclosing_func_qn (set during extraction in pass_definitions.c) still carries the old pre-promotion QN (free-function style), so gbuf_find_by_qn fails → fallback fires.
This is visible in production: a 2500-file C++ engine module shows 99.6% of CALLS edges have source.label = Module (5779 Module→Method vs 43 Function/Method→Function/Method).
Logs
Project scale (if relevant)
2543 files, 36,219 nodes, 79,170 edges
Confirmations
- I searched existing issues and this is not a duplicate.
- My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.
Activity
DeusData commentedon Jun 22, 2026
Hey, thx for reporting, will check ASAP
DeusData commentedon Jun 23, 2026
Related to the general bug #438 (cross-file CALLS edges resolving to the Module node instead of the caller function). Your case is the C++ out-of-line-definition path — the
calls_find_source()fallback to__file__firing becauseenclosing_func_qnno longer matches the node QN after #428 promoted out-of-line defs toMethod. PR #463 targets exactly this by attributing C/C++ CALLS edges to the enclosing function. Linking the two.DeusData commentedon Jun 28, 2026
Reproduced as a first-class failing test in the cumulative bug-reproduction suite and fixed at the root cause in #667.
Root cause: for an out-of-line method definition (
Class::methodin a .cpp), the LSP-resolved caller QN omitted the module prefix, so it never matched the textual call's enclosing-function QN and the resolution was discarded — the CALLS edge fell back to the Module node. The caller QN is now module-qualified so the LSP rescue joins. The reproduction stays as a permanent regression guard.(Lands when #667 merges.)
test(repro): scaffold cumulative bug-reproduction suite + cross-platf…
fix: 17 reproduce-first issue + new-bug fixes (per-case verified)
DeusData commentedon Sep 26, 2026
Thank you, @spwlyzx, for the minimal reproduction and for tracing it straight to
calls_find_source()!The root cause was that the LSP-resolved caller QN for an out-of-line
Class::methodwas missing the module prefix. The resolution was discarded, and the edge fell back to the Module node. Since #667 the caller QN is module-qualified. I re-ran your exact three-file repro on current main and gotConvertBlob (Method) -CALLS-> CreateTileData (Method), with no Module source.Closing as fixed (v0.9.0+). Please reopen if your engine module still shows Module-sourced CALLS on v0.11.0.