Skip to content

Enrich data for dynamic calling by adding external information and cleaning magic features - #51

Merged
hungpham10 merged 19 commits into
mainfrom
fix/enrich-data-for-dynamic-calls
Oct 25, 2026
Merged

hungpham10 merged 19 commits into
mainfrom
fix/enrich-data-for-dynamic-calls

Conversation

@hungpham10

Copy link
Copy Markdown
Owner

No description provided.

…oncurrency markers

- Method-set matching cho implicit interface: receiver_fn hook lưu receiver
  base type vào Symbol.type_name (`func (f *File) Write` → "File"); khai báo
  method trong interface body là node `method_elem` (không phải
  method_declaration) — giờ được extract với scope đúng vào interface symbol.
  build_go_method_sets tính structural typing: T implements I ⟺ method
  names(I) ⊆ method names(T); w.Write() fan-out chỉ tới các type thỏa thay vì
  naive CHA (fallback giữ nguyên khi method-set chưa đủ dữ liệu).
- Function value tracking: go_fn_ptr_assign bắt `handler := process` /
  `handler = process` → PointerAssign fan-out (dùng chung machinery C).
- Package/import: FileDeps { package, imports } mới trong ParseResult;
  go_file_deps đọc package_clause + import_spec (alias→path);
  alias_qualified_name resolve `orders.Get` qua import alias cho in-repo
  packages (match segment cuối path).
- Concurrency markers: MARKER_GO/MARKER_DEFER (Marker::Go/Defer) vào chain cho
  `go f()`/`defer f()`; select_statement wired vào switch machinery
  (communication_case); EffectType::Panic cho panic/log.Fatal/os.Exit.

Tests: 5 extractor (receiver type, interface method scope, fn value, file
deps, markers) + 2 e2e graph (method-set precision, import alias). Clippy
sạch, fmt xong.
- Symbol.sig_key: signature key chuẩn hóa `(param_types)(result_types)` (bỏ
  tên param) qua sig_key_fn hook; go_signature_key dùng chung cho
  method_declaration/method_elem/function_declaration. build_go_method_sets
  thỏa interface ⟺ (name, sig_key) khớp — `Wrong.Read(string) string` không
  còn bị coi là implement `Reader.Read([]byte) (int, error)`. Thiếu key nào →
  fallback name-only (lenient); interface 0 method → skip.
- LangSpec refactor: gom 3 nhóm base / hooks (HookSpec — các Option<fn>,
  HookSpec::none()) / markers (MarkerSpec — control-flow kinds + field names,
  MarkerSpec::dflt()); LangSpec::dflt() const + FRU hợp lệ trong static.
  14 language spec chỉ khai field KHÁC default — thêm hook mới không còn phải
  sửa 14 file.
…e impl linking, sig_key

- decls += field_declaration/parameter/let_declaration: struct field, tham số
  và local giờ là symbol có type_name (từ field `type`) — tie-break
  field_declared_type resolve `db.query()` theo type của `db`. Parameter lấy
  tên từ field `pattern` TRƯỚC name_type_fallback (tránh lấy nhầm tên kiểu).
- rust_file_deps: extract `use` (alias = `as` alias hoặc segment cuối);
  import_alias_candidates hỗ trợ `Type::method` — `use crate::storage::Database`
  + `Database::new()` resolve về method của class Database (Alias).
- link_impls_globally: impl linking chuyển lên global ingest — `impl Worker`
  khác file với `struct Worker` vẫn nối (type_ref → def, re-parent methods).
- rust_signature_key: `(params)(return)` cho method/fn (self → "self") —
  nguyên liệu trait matching theo signature.
Python (theo review gaps):
- param_container_kinds: `parameters` container → Parameter symbols (identifier
  / typed_parameter / default_parameter, type từ type hint) — field/param
  typing cho tie-break resolution.
- field_from_self_attr: `self.attr = Database()` → Field symbol scope vào
  class, type từ callee text — instance-attr typing.
- py_file_deps: import/import-as/from-import → FileDeps (alias→path), ăn vào
  import_alias_candidates sẵn có.
- py_superclasses: `class File(Writer)` → impl_trait "Writer" — inheritance
  fan-out qua machinery impl_index (giống C++ base class).

Persistence (fix: dynamic indexes chỉ ở RAM, MCP restart là mất):
- Storage trait + sqlite (sg_file_deps/sg_fn_ptr_assigns) + in_memory:
  persist ĐẦU VÀO thô FileDeps + FnPtrAssigns theo file path.
- rebuild() khi open: rebuild file_imports/fn_ptr_index từ blob +
  link_impls_globally/impl_index/go_impls từ sg_symbols — resolution quality
  giữ nguyên sau restart. E2e: dynamic_indexes_survive_reopen.
Review bằng fixture "thật" (trait + impl + macro + closure + async) phát hiện:
- function_signature_item (method KHAI BÁO trong trait) không được extract —
  không có symbol scope vào Interface nên fan-out Rust không bao giờ fire trên
  code thật (các test trước dùng synthetic symbols). Thêm vào decls → trigger
  Interface như Go method_elem.
- macro_invocation không phải call (println!/vec! mất hoàn toàn) — thêm
  CallRule với rust_macro_call_name (`println!`).
- E2E extraction thật: trait Repo{ping} + 2 impl → r.ping() fan-out cả hai
  (HierarchyFanOut) — chứng minh path thật chạy, không chỉ synthetic.
- Cập nhật chain expectation test cũ: cg_t!/cg_d! giờ là call thật.

Còn lại (defer): closure/callable tracking (cb()), generic instantiation,
associated type semantics, UFCS.
Trước đó chỉ sqlite + in_memory implement — lmdb/postgres/mysql/redis rơi về
no-op default = mất dynamic indexes khi reopen trên các backend đó.

- lmdb: 2 named DBI (sg_file_deps/sg_fn_ptr_assigns) + set/all (cursor iter)
  + clear_entities.
- postgres/mysql: bảng sg_file_deps/sg_fn_ptr_assigns (repo_id, path) PK,
  CREATE TABLE IF NOT EXISTS idempotent khi mở repo (không cần migration tay);
  mysql dùng ON DUPLICATE KEY UPDATE; clear_entities thêm 2 bảng.
- redis: 2 hash keys (filedeps/fnptpassigns) + DEL trong clear_entities.
- cached.rs: forward 4 methods xuống inner storage (trước đây rơi về default
  no-op → bypass backend thật!).
- Test roundtrip in_memory (set/all/clear); build + test --all-features.
…yn_callers index

Review qua MCP index thật (codegraph-rs tự index chính nó) phát hiện:
- `callers(set_file_deps)` trả rỗng dù ingest_with_progress gọi nó qua
  `dyn Storage` — call qua trait object bị resolve Single vì is_method_dispatch
  check `call_name.contains('.')` nhưng extractor đã rút call_name còn bare,
  trong khi receiver_text vẫn giữ receiver.
- Fix 1: is_method_dispatch = receiver_text.is_some() || call_name.contains('.')
  → fan-out fire cho dyn-trait call.
- Fix 2: dyn_callers (callee → callers) build từ call_meta khi ingest, scan
  call records khi rebuild; callers_resumable merge vào pending (dedup qua
  visited) → callers()/impact() thấy caller xuyên dyn-trait/interface/fn-ptr.
- E2E: callers() của từng impl method thấy dyn caller (trước đây rỗng).

Note vận hành: MCP server đang chạy bị MDB_BAD_RSLOT sau re-index in-process —
reader locktable stale, cần restart MCP server (issue riêng, chưa xử lý).
Review setup vs machinery Go/Rust/Python đã có — lấp các gap:

Java (typing đã tốt nhất: field/param/local + annotations + implements):
- java_supers: gộp extends (superclass) + implements vào impl_trait —
  inheritance fan-out qua machinery C++-base (superclass đứng trước).
- java_signature_key: (params)(return) — tên param bỏ.
- java_file_deps: import (bỏ static/wildcard) → FileDeps; strip keyword
  "extends" khỏi superclass text.

JavaScript/TypeScript:
- param_container_kinds formal_parameters: js identifier/rest_pattern, ts
  required/optional_parameter (name từ field pattern, type từ type_annotation
  — strip ':' + '?'). Trước đây params KHÔNG được extract.
- js_file_deps (share TS): import default/named-as/namespace → FileDeps.
  Bug kèm theo: class_type_name cũ không bao giờ match JS thuần (class_heritage
  không có extends_clause — chỉ TS có); js_extends xử lý cả 2 grammar.
- js_extends → impl_trait: inheritance fan-out cho class extends.
- js_fn_value_assign: `handler = process` / `const h = process` (identifier
  thuần) → PointerAssign machinery.

Tests: 3 fixture mới (java supers/sig/imports; js params/imports/extends/
fn-value; ts typed params + interface method scope). 20/21 suite (Redis env).
… ngữ

PHP (typing đã tốt: params/property/variable):
- php_supers: base_clause (extends) + class_interface_clause (implements) —
  LÀ NODE KIND không phải field name (child_by_field_name trả None!) —
  inheritance fan-out.
- php_signature_key + php_use_deps (namespace_use_declaration, bỏ
  function/const/wildcard).

Ruby (mỏng nhất — params chưa từng extract):
- param_container_kinds method_parameters: identifier/optional_parameter/
  keyword_parameter/splat_parameter.
- ruby_superclass → impl_trait (bỏ dynamic superclass `< Struct.new(..)`).
- ruby_require_deps: require/require_relative → FileDeps.

Lua:
- param_container_kinds "parameters" (kind thật, không phải parameter_list).
- lua_require_deps: `local mod = require('mod')` ghép variable_list với
  expression_list theo vị trí.
- lua_fn_value_assign: `handler = process` → PointerAssign.

Scala:
- scala_supers: field "extend" (extends_clause là node kind, field tên
  "extend") — extends B with T → "B,T".
- scala_signature_key + scala_file_deps (import_declaration, selector
  `.{a, b => c}`); token keyword "import" có cùng kind — guard child_count.

Bài học chung: field name vs node kind khác nhau từng grammar — luôn dump AST
trước khi wire hook.
Swift (trước đây gần trống — không hooks):
- decls += protocol_function_declaration: method KHAI BÁO trong protocol
  scope vào Interface → fan-out (đúng bug Rust từng mắc).
- swift_supers: inheritance_specifier (`class FileRepo: BaseRepo, Repo`) →
  impl_trait — protocol conformance đi cùng cơ chế fan-out.
- swift_signature_key: Swift dùng TRÙNG tên field "name" cho tên param VÀ
  type (lấy field "name" cuối); match cả protocol_function_declaration;
  return = user_type sau token "->".
- swift_import_deps: import_declaration → FileDeps.

C# (typing/annotations sẵn tốt):
- csharp_bases: base_list (node kind, unnamed child) → impl_trait
  (base class + interfaces, strip generic).
- csharp_signature_key: return field là "returns" (không phải "type").
- csharp_using_deps: `using App.Repos` + alias form `using Db = App.Data`.

Tests: 2 fixture mới (swift protocol/supers/sig/imports; csharp bases/sig/
using). 25/25 dynamic_dispatch, 20/21 workspace (Redis env-only).
A. FunctionValue cho 4 ngôn ngữ còn thiếu:
- Python: `handler = process` (identifier=identifier) + `self.handler = process`
  (member, var = "self.handler").
- Ruby: CHỈ `handler = method(:process)` — plain `x = process` là LỜI GỌI
  trong Ruby, không track.
- Java: `Runnable r = this::run` — method_reference, target = identifier cuối
  (không phụ thuộc field name grammar).
- C#: `Action handler = Process` — value là identifier UNNAMED (không có
  field "value") — lấy identifier con cuối khác name.

B. Member fn assignment `obj.handler = fn`:
- Mở guard fn_ptr_index (bỏ `!contains('.')`) — lookup theo call_name bare
  lẫn dotted.
- js/ts: member_expression left → key full dotted text (`Foo.prototype.run`).
- lua: text chứa '.' → full text; bracket `handlers["read"]` skip.
- python: self.attr.

C. MARKER_AWAIT (Marker::Await = 27): MarkerSpec.await_kinds — python "await",
js/ts/csharp/swift "await_expression" (dump AST xác nhận); walk_chain push
AWAIT trước call như GO/DEFER → edge mang ngữ cảnh async boundary.

E2E: member_fn_assignment_resolves_dotted_call — `obj.handler = process` +
`obj.handler()` → PointerAssign (trước đây guard chặn). 25/25 dynamic_dispatch
(2 test mới), 20/21 workspace (Redis env-only).
…irtual precision

1. c_include_deps: #include "foo.h" / <openssl/ssl.h> → FileDeps (path nguyên
   văn, alias = tên file không extension) — include graph qua machinery
   file_imports; C + C++ share.
2. c_fn_ptr_assign mở rộng: LHS field_expression (`obj.handler` — dotted key,
   ăn guard fn_ptr_index mới) + pointer_expression (`*handler` → "handler");
   RHS `&f` address-of + `&ns::cb` qualified.
3. cpp_signature_key: params từ function_declarator (function_definition 1
   tầng declarator; method inline field_declaration cũng 1 tầng — dump mới
   thấy, không phải 2); return field "type".
4. Virtual precision trong collect_fanout (C++ path): nếu CÓ candidate mang
   keyword virtual/override (signature chứa — extractor lưu dòng khai báo)
   → chỉ giữ virtual candidates + base decl; không keyword nào → giữ hết
   (soundness fallback). Loại non-virtual cùng tên trong hierarchy.

E2E: cpp_virtual_filter_prefers_override_candidates (D2 non-virtual bị loại).
Tests: 26/26 dynamic_dispatch (2 mới), 121/121 graph lib, 20/21 workspace
(Redis env-only).
…h pagination + annotation

Explore UI (SvelteKit + GraphQL) lộ đầy đủ query surface mới:

- Flow tab: mỗi call hiện badge resolvedVia ([dyn]/[fn-ptr]/[unresolved]/…)
  + candidate chips click-to-navigate (searchExact). GraphQL enum là
  SCREAMING_SNAKE_CASE — smoke query bắt được bug casing lowercase ban đầu.
- Tab Call sites (references): tìm callers theo call name — thấy cả
  unresolved/library + dynamic calls; prefill theo symbol name.
- Tab Pattern (searchFlow): tìm hàm theo chain pattern (markers/tên/id).
- Tab Trace (traceFullFlow — targetId arg): debug-style paths caller → target,
  indent theo stackDepth, icon theo action (CALL/RETURN/THROW/BRANCH/LOOP),
  màu theo PathEnding; chọn caller depth.
- SymbolSearch: Load more (offset pagination), "continue" khi timed_out
  (resumable cursor), source by name | by annotation
  (graphcodeSearchByAnnotation).

Smoke qua server thật: flow(ingest_with_progress) có 11 HIERARCHY_FAN_OUT
calls với 7 candidates (dyn Storage backends), trace 3 paths,
annotation "derive" 196 kết quả, references set_file_deps 2 callers.
svelte-check 0 errors, build-web assets embed, workspace tests 20/21
(Redis env-only).
…fied call

#6 link_cpp_decl_def (global, chạy cả ingest lẫn rebuild):
- `void Service::run() {}` trong .cpp (definition, có chain) nối với method
  khai báo trong .hpp (declaration, không chain): cùng tên + cùng sig_key
  (khi cả hai có) + khác file → def re-parent về scope của decl (class/
  namespace) + reclassify theo kind của decl; decl.type_ref → def.
- Hiệu ứng: fan-out/hierarchy thấy definition (có body/flow), class_info
  theo type_ref tới nơi có chain.

#8 qualified call `orders::run()`:
- Short-name fallback split cả '::' (rsplit ['.', ':'] bỏ segment rỗng) —
  trước đây "::" không split → qualified call unresolved hoàn toàn.
- Namespace preference: prefix trước '::' lọc candidate theo tổ tiên Module
  (namespace) cùng tên hoặc file chứa prefix — `foo::run` không còn nhầm
  `bar::run`; không subset khớp → giữ tất cả (soundness).

E2E: cpp_decl_def_linked_across_files (link đúng, pick_best ưu tiên def
has-chain); cpp_qualified_call_prefers_namespace (orders::run chọn đúng
namespace, không chọn bar). 123/123 graph lib, 20/21 workspace (Redis env).
…lite), typedef signature (#4-lite)

#5 C++ lambda thành Function symbol:
- decls/func_kinds += lambda_expression → chain riêng cho calls trong lambda
  body (attribution chính xác, không gộp vào enclosing fn).
- anonymous_name_fn cpp_lambda_name: `auto f = [](){}` mượn tên biến —
  LƯU Ý init_declarator đặt tên ở field `declarator`, không phải `name`
  như JS variable_declarator (grammar khác nhau).

#9-lite macro THEO THIẾT KẾ GHI-NHẬN (không resolve):
- preproc_function_def + preproc_def → Constant symbol, signature = định
  nghĩa nguyên văn (`CALL(x) x()`, `MAX 10`) — macro KHÔNG phải function,
  invocation giữ raw call → usage tra qua call-name index (references).
- Hành vi semantic do config khai báo ("LLM tự định nghĩa"): `[[effect_rules]]`
  trong .codegraph/config.toml (matcher + EffectType, xét trước bảng default)
  — test chứng minh rule Contains "CALL" → Panic (exception-like).
- Không làm (đúng defer): macro expansion, conditional compilation.

#4-lite typedef signature:
- HookSpec thêm typedef_sig_fn; c_typedef_sig (C + C++ share): typedef +
  macro → signature = text định nghĩa (strip typedef/#define + ;). Hook
  ƯU TIÊN extract_signature (nó trả full text trước khiến hook không chạy).
- fn-ptr typedef giờ giữ underlying type: `int (*handler_t)(int)` thay vì
  chỉ `int` từ field type.

Tests: cpp_lambda_macro_typedef_batch (lambda symbol + chain + calls, macro
Constant + signature + raw invocation + effect-rule config, typedef sig).
20/21 workspace (Redis env-only), clippy sạch.
…acro semantics)

Trước đây `[[effect_rules]]` chỉ đọc được từ .codegraph/config.toml — LLM phải
sửa file ngoài band rồi re-index. Giờ có tool chính tắc:

- config.rs CRUD API: list_effect_rules (raw — kể cả rule lỗi) /
  add_effect_rule (validate matcher + EffectType, toml_edit preserve mọi
  section khác) / remove_effect_rule (theo index). Sau ghi: install_current
  cho thread hiện tại; orchestrator reload config mỗi index nên rule áp dụng
  từ lần re-index kế tiếp (re-classify call records).
- MCP tool `codegraph_config_effects`: op list|add|remove; mô tả tool kèm
  ví dụ macro exception-like (contains CHECK → panic) + ghi chú áp dụng.
- GraphQL mutation `configEffects(op, matcher, text, effect, index)` mirror
  cho web UI.

Test: effect_rule_crud_roundtrip — add 2 rules → list đúng, classifier load
từ file classify CHECK_OK → Panic / db.Query → SqlQuery, effect sai bị chặn
(file không đổi), remove theo index, section khác (storage) nguyên vẹn.
Fix bug bắt được bởi test: or_insert tạo ArrayOfTables với table rỗng dummy
→ rule rỗng đầu danh sách.
@coderabbitai

coderabbitai Bot commented Oct 25, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 71888e1d-1e99-48cf-8719-ab3c38f5c86b
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hungpham10
hungpham10 merged commit 598f47f into main Oct 25, 2026
21 of 22 checks passed
@hungpham10
hungpham10 deleted the fix/enrich-data-for-dynamic-calls branch October 25, 2026 23:58
@codspeed

codspeed Bot commented Oct 26, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 17.78%

2 warnings

⚠️ 22 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

❌ 11 regressed benchmarks
✅ 27 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ walk+parse 528.6 ms 701.2 ms -24.62%
❌ walk+parse 93.7 ms 118.9 ms -21.21%
❌ sample 105.2 ms 133.6 ms -21.2%
❌ sample 105.1 ms 133.1 ms -21.03%
❌ walk+parse 508.3 ms 634.4 ms -19.88%
❌ walk+parse 714.5 ms 856.6 ms -16.59%
❌ open+ingest 1.1 s 1.3 s -15.69%
❌ open+ingest 2.4 s 2.8 s -15.35%
❌ ingest 898.4 ms 1,049.9 ms -14.43%
❌ open+ingest 898.7 ms 1,049.8 ms -14.4%
❌ open+ingest 1.3 s 1.5 s -10.16%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix/enrich-data-for-dynamic-calls (7c1f618) with main (cb034c2)

Open in CodSpeed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant