Bug
In C++ codebases, all CALLS edges originate from the Module (file) node rather than from individual Function/Method nodes. This makes trace_path unable to traverse C++ call chains at function-level granularity.
Version: 0.6.0 (macOS arm64)
Evidence
Querying CALLS edge source labels across languages in the same repository:
-- C++ (hbmx/marcopolo/src/): 100% of CALLS from Module
SELECT n1.label AS source_label, count(*) AS call_count
FROM edges e JOIN nodes n1 ON e.source_id = n1.id
WHERE e.type = 'CALLS' AND n1.file_path LIKE 'hbmx/marcopolo/src/%'
GROUP BY n1.label ORDER BY call_count DESC;
-- Result: Module|1706 (no Method or Function entries)
-- Swift (ios/MarcoPolo/): 82% from Method/Function
SELECT n1.label AS source_label, count(*) AS call_count
FROM edges e JOIN nodes n1 ON e.source_id = n1.id
WHERE e.type = 'CALLS' AND n1.file_path LIKE 'ios/MarcoPolo/%'
GROUP BY n1.label ORDER BY call_count DESC;
-- Result: Method|20160, Module|4417, File|611, Function|261
Concrete example — AutoplayController.cpp has 29 Method nodes but zero outbound CALLS edges. All 23 CALLS are attributed to the .hpp Module node:
-- Zero CALLS from .cpp
SELECT count(*) FROM edges e JOIN nodes n1 ON e.source_id = n1.id
WHERE e.type = 'CALLS'
AND n1.file_path = 'hbmx/marcopolo/src/conversation/AutoplayController.cpp';
-- Result: 0
-- 23 CALLS from .hpp Module node
SELECT count(*) FROM edges e JOIN nodes n1 ON e.source_id = n1.id
WHERE e.type = 'CALLS'
AND n1.file_path = 'hbmx/marcopolo/src/conversation/AutoplayController.hpp';
-- Result: 23
-- All from the Module node specifically
SELECT DISTINCT n1.id, n1.name, n1.label FROM edges e
JOIN nodes n1 ON e.source_id = n1.id
WHERE e.type = 'CALLS'
AND n1.file_path = 'hbmx/marcopolo/src/conversation/AutoplayController.hpp';
-- Result: 23296|hbmx/marcopolo/src/conversation/AutoplayController.hpp|Module
Impact
trace_path(function_name="configureAutoplay", direction="inbound") returns only 1 caller (the Module node) instead of the actual function-level callers. Effectively, trace_path is unusable for C++ code.
Root Cause Analysis
Traced through the source code:
1. func_kinds_cpp is too narrow (helpers.c:361):
static const char *func_kinds_cpp[] = {"function_definition", NULL};
Compare with the generic/Swift fallback which works correctly:
static const char *func_kinds_generic[] = {
"function_declaration", "function_definition",
"method_declaration", "method_definition", NULL
};
C++ tree-sitter uses function_definition for .cpp implementations, but .hpp inline methods and other constructs may use different node types. The narrow list means cbm_find_enclosing_func often fails to find the enclosing function in C++.
2. Module QN collision between .hpp and .cpp — When cbm_find_enclosing_func returns null, cbm_enclosing_func_qn falls back to module_qn (helpers.c:480):
TSNode func_node = cbm_find_enclosing_func(node, lang);
if (ts_node_is_null(func_node)) {
return module_qn; // fallback to file-level
}
Since AutoplayController.hpp and AutoplayController.cpp produce the same base Module qualified name (...AutoplayController), calls extracted from the .cpp are attributed to the .hpp Module node (which was created first). The .cpp ends up with zero CALLS edges.
Suggested Fix
- Expand
func_kinds_cpp to include "declaration" or the specific tree-sitter node types used for C++ method declarations in class bodies
- Ensure
.hpp and .cpp files get distinct Module qualified names (e.g., include the extension) so calls aren't cross-attributed
Reproduction
Any C++ codebase with the standard .hpp/.cpp split pattern will exhibit this. Index the repository, then compare CALLS edge source labels for C++ files vs Swift/Kotlin files — C++ will show 100% Module-attributed CALLS.
Environment
- codebase-memory-mcp 0.6.0
- macOS arm64 (Apple Silicon)
- Repository: ~14K files, mixed Swift/Kotlin/C++/TypeScript
- Clean index (deleted project + removed .db file before reindexing)
Bug
In C++ codebases, all CALLS edges originate from the Module (file) node rather than from individual Function/Method nodes. This makes
trace_pathunable to traverse C++ call chains at function-level granularity.Version: 0.6.0 (macOS arm64)
Evidence
Querying CALLS edge source labels across languages in the same repository:
Concrete example —
AutoplayController.cpphas 29 Method nodes but zero outbound CALLS edges. All 23 CALLS are attributed to the.hppModule node:Impact
trace_path(function_name="configureAutoplay", direction="inbound")returns only 1 caller (the Module node) instead of the actual function-level callers. Effectively,trace_pathis unusable for C++ code.Root Cause Analysis
Traced through the source code:
1.
func_kinds_cppis too narrow (helpers.c:361):Compare with the generic/Swift fallback which works correctly:
C++ tree-sitter uses
function_definitionfor.cppimplementations, but.hppinline methods and other constructs may use different node types. The narrow list meanscbm_find_enclosing_funcoften fails to find the enclosing function in C++.2. Module QN collision between
.hppand.cpp— Whencbm_find_enclosing_funcreturns null,cbm_enclosing_func_qnfalls back tomodule_qn(helpers.c:480):Since
AutoplayController.hppandAutoplayController.cppproduce the same base Module qualified name (...AutoplayController), calls extracted from the.cppare attributed to the.hppModule node (which was created first). The.cppends up with zero CALLS edges.Suggested Fix
func_kinds_cppto include"declaration"or the specific tree-sitter node types used for C++ method declarations in class bodies.hppand.cppfiles get distinct Module qualified names (e.g., include the extension) so calls aren't cross-attributedReproduction
Any C++ codebase with the standard
.hpp/.cppsplit pattern will exhibit this. Index the repository, then compare CALLS edge source labels for C++ files vs Swift/Kotlin files — C++ will show 100% Module-attributed CALLS.Environment