fix(callgraph): register object-literal arrow fns as nodes (closes #222)#225
Merged
Merged
Conversation
Arrow functions assigned to object-literal properties (e.g.
`const svc = { list: (ctx) => { ... } }`) were invisible as function
nodes — `_parse_variable_declarator` only handles value berupa
arrow_function/function_expression/defineStore call, bukan object node.
Sebelum fix: calls di dalam arrow body sudah ter-extract oleh module-level
pass (PR #219, issue #210) dan di-attribute ke synthetic <module> node,
jadi ref_count callee sudah benar. Tapi arrow function-nya sendiri TIDAK
terdaftar sebagai node, sehingga trace/impact/search --mode symbol tidak
bisa resolve method by name.
Fix:
- TS parser: tambah _find_object_literal_method_decls yang walk AST,
cari variable_declarator dengan object value, register setiap pair
dengan arrow/function value sebagai node <varName>.<key>.
- JS parser: tambah _collect_object_literal_method_calls yang serupa
tapi collect calls inline (konsisten dengan single-pass design JS parser).
- Update _find_module_level_calls di kedua parser untuk skip pair nodes
dengan arrow/function value — hindari double-counting antara per-function
pass (yang sekarang register method tsb) dan module-level pass.
Hasil:
- Arrow function terdaftar sebagai node <varName>.<key> (e.g.
assignmentService.list, assignmentService.create, assignmentService.remove)
- Calls di dalam arrow body di-attribute ke method node id, bukan <module>
- ref_count callee tetap sama (tidak double-counted)
- trace/impact/search sekarang bisa resolve method by name
Tests: 16 regression tests (8 TS + 8 JS) — registration, call attribution,
multi-method, ref_count end-to-end, non-arrow pair handling, no double-count,
object literal in function body.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Closed
3 tasks
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Closes #222
Patch Peta (delta struktural)
Files:
Endpoints: none
Schema: node baru: object_method nodes (fn=
<varName>.<key>, node_type=object_method) untuk arrow functions di object-literal pairs. Format konsisten dengan node lain (<file>:<line>id, field sama seperti pinia_store type).Konvensi:
rc/ref_countuntuk callee tidak berubah (calls tetap ter-extract, hanya caller-nya berubah dari<module>ke<varName>.<key>). trace/impact/search sekarang bisa resolve method by name. Tidak ada breaking change — downstream code yang baca rc tidak perlu ubah.Klaim + Bukti
Verifikasi state main post-#219 (sebelum fix)
Issue body mengatakan: "Cek dulu behavior sekarang di main (post-#219) sebelum mulai — jangan asumsikan kode dari PR #221 yang di-reference di sini masih relevan tanpa verifikasi ulang terhadap state main terbaru."
Verifikasi via reproduksi script (
/home/z/my-project/scripts/verify_issue222.py):Konfirmasi: PR #219 (
_find_module_level_calls) SUDAH meng-cover calls di dalam object-literal arrow functions secara TIDAK LANGSUNG. Karenavariable_declaratordenganobjectvalue tidak di-skip oleh module-level pass, walk masuk ke object literal dan extract calls dari arrow body, attribute ke<module>.Jadi
rc=3SUDAH benar sebelum fix ini. Tapi issue #222 EKSPLISIT meminta untuk register arrow function sebagai node<varName>.<key>(bukan hanya collect calls-nya). Tujuan eksplisit: supayatrace/impact/search --mode symbolbisa resolve method by name.Root cause detail
_parse_variable_declaratordi kedua parser hanya handle value berupa:arrow_function(e.g.const fn = () => {})function_expression(e.g.const fn = function() {})call_expressiondengan functiondefineStore(Pinia store pattern)Kalau value adalah
objectnode (object literal), return None — arrow functions di dalam pair-nya tidak pernah diregister sebagai node.Bukti fix (sesudah fix)
Sesuai Definition of Done:
search --mode symboluntuk fungsi yang dipanggil hanya lewat pattern ini menunjukkanrcyang benar (rc=3, bukan 0)Test suite — 0 regresi baru
Parser tests (existing + baru):
Full suite (exclude pre-existing broken test files per CONTEXT.md):
Baseline (main sebelum fix): 17 failed, 2260 passed → 2276 passed setelah fix (naik 16 = test baru). Jumlah failure sama (17) — semua pre-existing (doctor/formatters/codelensignore/node_types — env-specific, bukan dari fix ini).
Checklist Laporan Worker
Catatan Pendekatan
Issue body mengatakan: "Supaya calls di dalam body-nya ter-collect dengan benar." Investigasi menemukan bahwa calls SUDAH ter-collect dengan benar (rc=3) berkat PR #219, TAPI arrow function-nya sendiri tidak terdaftar sebagai node. Fix ini fokus pada node registration (sesuai tujuan eksplisit issue body: "register sebagai node dengan nama
<varName>.<key>"), bukan pada call extraction.Approach: tambah pass terpisah untuk find object-literal method decls, lalu update
_find_module_level_callsuntuk skip pair dengan arrow/function value (hindari double-counting antara per-function pass yang baru dan module-level pass yang sudah ada dari #219).Untuk JS parser, approach sedikit berbeda karena JS parser pakai single-pass iterative walk dengan keep_alive (bukan two-pass seperti TS parser). Method baru
_collect_object_literal_method_callscollect calls inline (register node + collect body calls dalam satu operasi), konsisten dengan_parse_and_collect_callspattern yang sudah ada.Breaking / Found-not-fixed
return { list: () => {} }di dalam function body, atau{ handler: () => {} }sebagai call argument) TIDAK terdaftar sebagai node — tidak ada stable var name. Calls di dalamnya tetap ter-extract via per-function pass (untuk yang di function body) atau module-level pass (untuk yang di module scope). Ini acceptable: trace/impact tidak bisa resolve by name, tapi rc tetap benar. Follow-up optional kalau ada use case spesifik.const svc = { api: { list: () => {} } }) — hanya outermost var name yang dipakai →svc.list(bukansvc.api.list). Ini keeps naming simple dan matches Pinia store convention. Kalau perlu nested naming, issue terpisah.node_typefield baru (object_method) ditambahkan ke node dict. Downstream commands yang filter berdasarkan node_type mungkin perlu update kalau tidak expect value baru ini. Cek grep:node_typesudah dipakai di parser lain (e.g.pinia_store,class), jadi field-nya sudah dikenal — value baru saja yang ditambah.