Repository navigation
Conversation
…constructors (Graphify-Labs#4246) run.Sequence.Apply(), _configs[i].WriteIds() and any call inside a constructor body produced no calls edge when the callee lived in another file. Record the root's type plus the field for a one-level member chain and the element type for xs[i] on T[] / List<T> / IList<T> / IReadOnlyList<T>, and resolve them through the exported C# field tables. Walk constructor bodies too, attributing their calls to the declaring type. Any unknown or ambiguous step yields no edge. Co-Authored-By: Grok Bot <noreply@x.ai>
|
Thanks for the pull request, @Mpasha17. A maintainer will review it soon. Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions. A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic. |
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.
Graphify review — findings
Extends C# member-call resolution to chained receivers (x.F.M()) and indexed elements (xs[i].M()) by recording each field's, property's and local's declared type, plus an element type for T[], List<T>, IList<T> and IReadOnlyList<T>. _field_type_nid walks the base chain and gives up, leaving the call unresolved, on an unresolved base, an ambiguous declaration, or an indexed field accessed without an index. Constructor bodies are now walked for calls and attributed to the declaring type, so this./base. calls inside a constructor resolve against that type.
Worth a look
- C# generic property element types are not filtered —
graphify/extractors/engine.py:5769· Escalate · medium · 2 independent checks- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
- Nested C# collection elements are treated as concrete List receivers —
graphify/extractors/engine.py:2201· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 2902 functions depend on the 577 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 821 callers, 51 callees - new:
_rebuild_code()— 162 callers, 56 callees - new:
_extract_generic()— 19 callers, 34 callees - new:
extract_js()— 87 callers, 5 callees - new:
extract_xaml()— 19 callers, 17 callees - new:
main()— 102 callers, 3 callees - new:
extract_objc()— 27 callers, 10 callees - new:
dispatch_command()— 2 callers, 130 callees - …and 50 more — each is listed as a finding
Verification — 2902 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 2707 function(s) in the blast radius were not formally verified this run
Test selection
Test selection
160 of 356 test file(s) selected (45%) via static blast radius.
tests/test_astro_extraction.py— impacttests/test_astro_import_ids.py— impacttests/test_blade_extractor.py— impacttests/test_build.py— impacttests/test_builtin_global_type_refs.py— impacttests/test_cache.py— impacttests/test_case_sensitive_resolution.py— impacttests/test_cjs_module_extension.py— impacttests/test_cobol_extractor.py— impacttests/test_cpp_method_declarations.py— impacttests/test_cpp_nested_and_cli.py— impacttests/test_cpp_objc_cross_file_calls.py— impacttests/test_cross_extension_reexport_self_cycle.py— impacttests/test_cross_language_call_resolution.py— impacttests/test_cross_repo_external_call_guards.py— impacttests/test_cross_repo_member_calls.py— impacttests/test_csharp_call_site_generic_args.py— impacttests/test_csharp_enum_members.py— impacttests/test_csharp_field_generic_args.py— impacttests/test_csharp_generic_callsites.py— impacttests/test_csharp_interface_dispatch.py— impacttests/test_csharp_member_calls.py— impacttests/test_csharp_member_chain_calls.py— impact, changed-testtests/test_csharp_member_nodes.py— impacttests/test_csharp_object_creation.py— impacttests/test_csharp_partial_classes.py— impacttests/test_csharp_tuple_type_refs.py— impacttests/test_csharp_type_resolution.py— impacttests/test_definition_file_portability.py— impacttests/test_detect.py— impacttests/test_dotnet.py— impacttests/test_duplicate_annotation_edges.py— impacttests/test_elixir_import_resolution.py— impacttests/test_elixir_keyword_def_calls.py— impacttests/test_elixir_qualified_calls.py— impacttests/test_elixir_unqualified_call_scope.py— impacttests/test_erlang_extractor.py— impacttests/test_extract.py— impacttests/test_extract_cache_location.py— impacttests/test_extract_path_memo.py— impacttests/test_extract_php_closures.py— impacttests/test_file_label_disambiguation.py— impacttests/test_file_node_id_spec.py— impacttests/test_forwarding_review_findings.py— impacttests/test_go_builtin_call_targets.py— impacttests/test_go_import_repoint.py— impacttests/test_go_interface_methods.py— impacttests/test_go_qualified_resolution.py— impacttests/test_import_extension_resolution.py— impacttests/test_import_self_loops.py— impact- … and 110 more
Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.
Docs that may be stale (advisory)
CHANGELOG.md§ 0.4.10 (2026-04-13) (lines 2003-2022): references changed symbolsbind
· 58 more finding(s) on lines outside this diff (see the check run).
…access (Graphify-Labs#4246) Co-Authored-By: Grok Bot <noreply@x.ai>
|
Both findings were real, so I fixed them in 247ec07. I reproduced each one live first: |
…constructors (#4258, #4246) Resolve a.b.C(), xs[i].M(), and calls inside constructor bodies: a fail-closed chain/element-type resolver (one declared type per hop, collection element only for T[]/List<T>, bail on ambiguity) plus a ctor-body walk attributing calls to the type node. Reuses the existing C# scoping; avoids same-pair method/calls duplicates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes #4246
Three more C# call shapes got no
callsedge when the callee lived in another file: a call through a field of a typed receiver (run.Sequence.Apply()), a call on an array or list element (_configs[i].WriteIds()), and any call inside a constructor, since constructor bodies were never walked for calls at all.Now the C# extractor records
[type of run, "Sequence"]for a member chain and the element type forxs[i].M()(fromT[],List<T>,IList<T>orIReadOnlyList<T>fields, properties, parameters and locals, with the same scoping and shadowing rules as other receivers)._resolve_csharp_member_callsresolves the root type, looks up the field's declared type on that class or its bases through the field tables C# already exports, and then finds the method there like any other typed receiver. If any step is unknown or ambiguous there's no edge. Constructor bodies are walked now too, and since constructors have no node of their own, their calls come from the type node (the issue mentioned that as an option).this.M()andbase.M()inside a constructor resolve through that type. Chains and element access that already bound within the same file are left as they were.Limits: chains are only one field deep (
a.B.C.M()andthis.a.B.M()stay unresolved), and element access only works on a plain identifier (this._items[i]andrun.Items[i]don't resolve). A constructor's call to a method of its own class shares a node pair with the existingmethodedge, so the cross-file pass skips it. Walking constructor bodies also adds the usual call-sitereferencesedges (for example, generic args ofCreateMap<A, B>()inside an AutoMapperProfileconstructor). Constructor calls also go through v8's existing name lookup fornew X(), so the one wrong binding that already exists on v8 (new System.ArgumentNullExceptionlinking to AutoMapper's own internalArgumentNullException, 11 edges) picks up 2 more from constructors.Testing: new
tests/test_csharp_member_chain_calls.pywith 12 tests. The 6 positive ones fail on current v8, and the ambiguity, unknown-type, type-parameter, nested-list and #3797 control tests guard against wrong edges. The full suite on 3.10/3.12/3.13/3.14 has the same failures as v8. Ruff is clean and pyright shows no new findings. The three repros from the issue now give exactly the expected edges, andOther.WriteIdsgets nothing. On MediatR, Polly, Newtonsoft.Json and AutoMapper the C#callsedges went from 469 to 480, 5483 to 5546, 14252 to 14421 and 3479 to 3537, with none removed. I spot-checked a sample of the new edges against the source and they were right.AI-assisted (Grok Bot); each commit carries a Co-Authored-By line.