fix(wasm): emit receiver edges for declaration-typed locals (cpp, cuda)#1497
fix(wasm): emit receiver edges for declaration-typed locals (cpp, cuda)#1497carlos-alm wants to merge 4 commits into
Conversation
The JS C++ and CUDA extractors had no handler for 'declaration' AST nodes,
so typeMap was never seeded for statically-typed locals (e.g. 'UserService svc;').
Without a typeMap entry for 'svc', resolveReceiverEdge had nothing to look up and
silently skipped the receiver edge.
Add handleCppDeclaration / handleCudaDeclaration to both extractors. They mirror
match_c_family_type_map ('declaration' branch) from the native Rust path: extract
the type node text and seed typeMap[varName] = { type, confidence: 0.9 } for each
identifier or init_declarator child. Primitive types (int, char, bool, …) are
skipped to avoid spurious edges.
parity-compare.mjs --langs cpp,cuda --hybrid: PARITY OK (wasm = native = hybrid)
All 3044 tests pass.
|
Claude finished @carlos-alm's task —— View job PR Review: fix(wasm): emit receiver edges for declaration-typed locals (cpp, cuda)
Root Cause AnalysisProblem Being Solved: WASM C++/CUDA extractors never handled Why This Approach: The fix mirrors the exact native Rust logic. The Risk Assessment: Low. The change is purely additive (adds new Phase 2: Configuration ChangesNone. No linter rules, tsconfig flags, or test thresholds were touched. Phase 3: Test IntegrityNo tests were modified or removed. The resolution-benchmark fixtures already contain the relevant Phase 4: Code QualityMinor — Both files now import Whether this counts as unused depends on the TypeScript/Biome configuration. If the linter runs with
Primitive filter divergence from native Rust: The WASM engines filter primitive types at extraction time (
Phase 5: Backlog Compliance
Critical ConcernsNone blocking. Non-blocking observation: The Final Recommendation
|
Greptile SummaryFixes missing
Confidence Score: 5/5The change is a well-scoped additive fix — it only seeds new typeMap entries where the map was previously empty, making it impossible to remove existing receiver edges. The primitive-type guard and the intentional skip of pointer/reference declarators are both consistent with the Rust implementation. Both new handlers are clean ports of the existing Rust logic with no behavioral divergence. The only concern is that the identical primitive-type sets are duplicated across the two files rather than shared, and there are no new parser-level unit tests — but neither issue affects correctness. The duplicated primitive-type set in Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[walkCppNode / walkCudaNode] -->|declaration node| B[handleCppDeclaration\nor handleCudaDeclaration]
B --> C{type field present?}
C -->|no| Z[return — no typeMap entry]
C -->|yes, typeName| D{isPrimitive?}
D -->|yes| Z
D -->|no| E[iterate child nodes]
E -->|init_declarator| F[nameNode = declarator child field]
E -->|identifier| G[nameNode = child directly]
E -->|pointer/ref declarator| H[skip — intentional parity with Rust]
F --> I[unwrapDeclaratorName]
G --> I
I --> J[typeMap.set varName to type at conf 0.9]
A -->|always after switch| K[recurse into all children]
K --> A
Reviews (4): Last reviewed commit: "fix(lint): expand inline toEqual objects..." | Re-trigger Greptile |
| if (kind === 'init_declarator') { | ||
| nameNode = child.childForFieldName('declarator') ?? null; | ||
| } else if (kind === 'identifier') { | ||
| nameNode = child; | ||
| } |
There was a problem hiding this comment.
Pointer/reference declarators silently skipped
The handler only seeds typeMap for direct identifier children and init_declarator children. For UserService *svc; or UserService &svc = ...;, the declarator field of the declaration node is a pointer_declarator / reference_declarator, not a bare identifier — so those variables never get a typeMap entry and svc->method() calls won't generate receiver edges. This may intentionally mirror the Rust match_c_family_type_map limitation; if so, a comment noting the gap would be helpful. The same applies in src/extractors/cuda.ts.
There was a problem hiding this comment.
Fixed — added a clarifying comment in both handleCppDeclaration and handleCudaDeclaration (commit d3d83ef) documenting that this is intentional: the native Rust match_c_family_type_map helper in crates/codegraph-core/src/extractors/helpers.rs also only iterates init_declarator and identifier children of a declaration node — pointer_declarator/reference_declarator children are skipped on both sides. Both engines have identical scope here, so this is not a parity gap.
Codegraph Impact Analysis6 functions changed → 6 callers affected across 2 files
|
…sets to one-per-line Biome flagged TypeMapEntry as an unused import in both cpp.ts and cuda.ts (ctx.typeMap.set is typed via ExtractorOutput, not via a direct TypeMapEntry annotation). Also reformatted CPP_PRIMITIVE_TYPES / CUDA_PRIMITIVE_TYPES to one element per line, which is what the Biome formatter requires.
…Declaration Add an inline comment in handleCppDeclaration and handleCudaDeclaration explaining that pointer_declarator / reference_declarator children are intentionally skipped. Native Rust match_c_family_type_map has the same scope: it only iterates 'init_declarator' and 'identifier' children, so both engines behave identically for pointer/reference-typed locals.
|
Addressed reviewer feedback:
|
WASM engine was missing `receiver` edges for declaration-typed locals in C++ and CUDA (e.g. `UserService svc; svc.method()` → receiver edge `caller → UserService`). Native correctly emitted these at conf=0.9.
Root cause
The JS C++ and CUDA extractors had no handler for `declaration` AST nodes, so `typeMap` was never seeded for statically-typed locals. Without a typeMap entry for `svc`, `resolveReceiverEdge` found nothing to look up and silently skipped the receiver edge.
The native Rust path runs a second `walk_tree` pass with `match_c_family_type_map`, which handles the `declaration` node kind: it reads the `type` field and each `identifier` / `init_declarator` child to call `push_type_map_entry(symbols, varName, typeName)` at confidence 0.9.
Fix
Added `handleCppDeclaration` to `src/extractors/cpp.ts` and `handleCudaDeclaration` to `src/extractors/cuda.ts`. Both mirror the `match_c_family_type_map` "declaration" branch exactly: extract the type node text and seed `typeMap[varName] = { type, confidence: 0.9 }` for each identifier or `init_declarator` child. Primitive types (`int`, `char`, `bool`, …) are skipped to avoid spurious edges.
Verification
```
node scripts/parity-compare.mjs --langs cpp,cuda --hybrid
PARITY OK — 2 fixture(s), all engines identical
```
3044 tests pass, 0 failures.
Closes #1466