You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
trace_path and call-graph queries return empty results across several unrelated reports, and I believe they share one root cause: when the LSP does not populate the enclosing-function qualified name for a call site, calls_find_source falls back to attaching the CALLS edge to the File/Module node instead of the enclosing function. Downstream traversal is by function node, so the edge is invisible to function-scoped queries.
Filing this as a consolidated root-cause issue rather than a sixth per-language symptom report.
/* Find source node for a call: enclosing function or file node. */staticconstcbm_gbuf_node_t*calls_find_source(cbm_pipeline_ctx_t*ctx, constchar*rel,
constchar*enclosing_qn) {
constcbm_gbuf_node_t*src=NULL;
if (enclosing_qn) {
src=cbm_gbuf_find_by_qn(ctx->gbuf, enclosing_qn); // 1. enclosing function
}
if (!src) {
char*fqn=cbm_pipeline_fqn_compute(ctx->project_name, rel, "__file__");
src=cbm_gbuf_find_by_qn(ctx->gbuf, fqn); // 2. FALLBACK -> File nodefree(fqn);
}
returnsrc;
}
resolve_single_call (line 424) calls this for the edge source. When call->enclosing_func_qn is unset or unresolvable, step 1 misses and step 2 attaches the CALLS edge to the file's __file__ node. The edge exists and is traversable via query_graph on the file node, but trace_path / search_graph scoped to a function see zero outbound CALLS — hence "returns empty despite traversable CALLS edges".
Why this hits specific languages hardest
LSP enclosing-function resolution is most likely to come back empty for:
Two honest options, I'd like a steer on which you prefer before opening a PR:
Stop falling back to File when enclosing_qn is set-but-unresolved — drop (or defer) the edge rather than misattribute. trace_path correctness improves for resolvable sites, but total CALLS edge count drops where the enclosing function genuinely can't be resolved.
Keep the File fallback but tag it — add a source_kind: "file_fallback" (or similar) prop on edges emitted from the fallback path, so function-scoped traversal can skip/flag them while the file-level graph stays intact. Additive, lower risk.
I lean toward (2) for a first PR since it doesn't reduce edge coverage, but (1) is cleaner if you'd rather not carry misattributed edges at all. Happy to implement either with a reproduce-first test.
Reproduce
A test that indexes a C/C++ or cross-repo call site where enclosing_func_qn is empty, then asserts trace_path on the enclosing function returns a non-empty path — RED on current main, GREEN after the fix. (I'll write this in the PR.)
Summary
trace_pathand call-graph queries return empty results across several unrelated reports, and I believe they share one root cause: when the LSP does not populate the enclosing-function qualified name for a call site,calls_find_sourcefalls back to attaching the CALLS edge to the File/Module node instead of the enclosing function. Downstream traversal is by function node, so the edge is invisible to function-scoped queries.Filing this as a consolidated root-cause issue rather than a sixth per-language symptom report.
Root cause (source-level)
src/pipeline/pass_calls.c:404-417—calls_find_source():resolve_single_call(line 424) calls this for the edge source. Whencall->enclosing_func_qnis unset or unresolvable, step 1 misses and step 2 attaches the CALLS edge to the file's__file__node. The edge exists and is traversable viaquery_graphon the file node, buttrace_path/search_graphscoped to a function see zero outbound CALLS — hence "returns empty despite traversable CALLS edges".Why this hits specific languages hardest
LSP enclosing-function resolution is most likely to come back empty for:
tests/test_c_lsp.c:593carries the comment "Issue C++ CALLS edges attributed to Module node instead of Function/Method nodes #220: C++ CALLS edges were attributed to the Module (file) node", so this is a known historical recurrence.enclosing_func_qnis empty for cross-repo call sites and every such edge lands on the File node.Six reports, one mechanism.
What I checked before filing
enclosing_func_qn/ file-fallback framing — no duplicate root-cause issue.pass_calls.ccommit history onmain: recent fixes (cross-repo-intelligence returns 0 edges for a byte-identical call/route #523 sequential external, fix(pipeline): persist call-site line on CALLS edges #508 call-site line, Java/Go module-QN de-double) touch surrounding paths but not theenclosing -> __file__fallback itself.Fix direction (asking before coding)
Two honest options, I'd like a steer on which you prefer before opening a PR:
enclosing_qnis set-but-unresolved — drop (or defer) the edge rather than misattribute.trace_pathcorrectness improves for resolvable sites, but total CALLS edge count drops where the enclosing function genuinely can't be resolved.source_kind: "file_fallback"(or similar) prop on edges emitted from the fallback path, so function-scoped traversal can skip/flag them while the file-level graph stays intact. Additive, lower risk.I lean toward (2) for a first PR since it doesn't reduce edge coverage, but (1) is cleaner if you'd rather not carry misattributed edges at all. Happy to implement either with a reproduce-first test.
Reproduce
A test that indexes a C/C++ or cross-repo call site where
enclosing_func_qnis empty, then assertstrace_pathon the enclosing function returns a non-empty path — RED on currentmain, GREEN after the fix. (I'll write this in the PR.)