fix(cpp): extract union specifiers as class-like type nodes - #4052
rajatnagda45 wants to merge 1 commit into
Conversation
|
Thanks for the pull request, @rajatnagda45. 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.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify review — findings
Adds union_specifier to the C++ class_types, so a named union { ... } now becomes a type node with its data members (file contains the union, the union defines each field) instead of vanishing entirely. Anonymous unions such as typedef union { ... } Anon have no type name and are still skipped, matching anonymous enums.
No blocking issues surfaced.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 2349 functions depend on the 289 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 753 callers, 50 callees - new:
_rebuild_code()— 149 callers, 56 callees - new:
extract_js()— 87 callers, 4 callees - new:
extract_xaml()— 19 callers, 17 callees - new:
main()— 99 callers, 3 callees - new:
dispatch_command()— 2 callers, 127 callees - new:
_get_extractor()— 27 callers, 6 callees - new:
collect_files()— 19 callers, 6 callees - …and 35 more — each is listed as a finding
Verification — 2349 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: 2164 function(s) in the blast radius were not formally verified this run
Test selection
Test selection
142 of 326 test file(s) selected (44%) 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_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— impact, changed-testtests/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_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_unqualified_call_scope.py— impacttests/test_erlang_extractor.py— impacttests/test_extract.py— impacttests/test_extract_cache_location.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— impacttests/test_imported_export_forwarding.py— impacttests/test_incremental.py— impacttests/test_indirect_call_arrow_single_param_shadow.py— impacttests/test_indirect_call_block_scoped_shadow.py— impacttests/test_indirect_call_catch_binding_shadow.py— impact- … and 92 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.
· 43 more finding(s) on lines outside this diff (see the check run).
|
Shipped in v0.9.76 (live on PyPI as Closing as shipped. |
Closes #4051
Problem
A named C++
unionis dropped from the graph entirely — the type and all its members vanish:Pointand its members are in the graph;Value/i/fare not.Cause
union_specifierwas missing from_CPP_CONFIG.class_types.class_specifier,struct_specifier, andenum_specifierare all there, so a union was the only class-like container that fell through and was dropped.Fix
Add
union_specifiertoclass_types. It shares struct_specifier's name/body fields (type_identifier+field_declaration_list), so the existing generic container handling gives it a type node, acontainsedge from its file, and a data member per field — exactly like a struct. An anonymous union has notype_identifierand is skipped by the existing name guard, like an anonymous enum.Tests
Added
test_cpp_union_specifier_is_extracted: a named union becomes a type node withdefinesedges to its members, and atypedef union { ... } Anonmints no nameless node. Fails on currentv8, passes with the fix. Full suite: 6345 passed, 15 skipped.ruffclean;pyrighton extract.py unchanged (119 errors before and after, 0 added).