Skip to content

fix(registry): restrict same-module suffix resolution to self/namespace receivers#893

Open
sahil-mangla wants to merge 4 commits into
DeusData:mainfrom
sahil-mangla:main
Open

fix(registry): restrict same-module suffix resolution to self/namespace receivers#893
sahil-mangla wants to merge 4 commits into
DeusData:mainfrom
sahil-mangla:main

Conversation

@sahil-mangla

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR fixes #876 false-positive recursion flags (unguarded_recursion, self_recursive, recursive) occurring on store wrappers, singleton delegations, and other method calls targeting unrelated objects that happen to share a name with a top-level function in the current module (e.g. _get_store().get(...) inside get(...) or _default.check(...) inside check(...)).

Root Cause

During call graph resolution in Strategy 2 (resolve_same_module in src/pipeline/registry.c), dotted/colon-separated callee names (like _default.check) were split into prefix (_default) and suffix (check). The resolver fell back to checking if the suffix exists as a top-level function in the caller's module (module_qn.check). If a local check function was defined, it matched and mistakenly resolved the call to it, generating a self-loop CALLS edge which flagged the function as recursive.

Solution

  • Introduced is_same_module_receiver to validate the receiver prefix. Suffix fallback checks in resolve_same_module are now restricted to:
    • Valid self-receivers: "self", "this", "cls", "@self".
    • Prefix matching the module/namespace name itself (or ending with .<prefix>).
  • Restricting this prevents unrelated receiver calls (like axios.get, _get_store().get, _default.check) from matching same-module top-level functions, eliminating spurious CALLS self-loops.
  • Added a regression test suite in tests/test_registry.c (resolve_same_module_only_on_self_receiver) to cover delegation, self, and namespace/module receiver pattern cases.

Checklist

  • Every commit is signed off (git commit -s) — required, CI rejects unsigned commits (DCO, see CONTRIBUTING.md)
  • Tests pass locally (make -f Makefile.cbm test)
  • Lint passes (make -f Makefile.cbm lint-ci)
  • New behavior is covered by a test (reproduce-first for bug fixes)

@sahil-mangla sahil-mangla requested a review from DeusData as a code owner July 5, 2026 18:44
@DeusData DeusData added bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges priority/normal Standard review queue; useful PR with ordinary maintainer urgency. labels Jul 7, 2026
@DeusData

DeusData commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Thanks for the focused #876 fix. Triage: parsing/quality bug, normal priority.

Review should verify the receiver restriction removes store/delegation false positives without regressing legitimate same-module self or namespace receiver calls. The small registry-focused diff is a good shape for this bug.

… receivers

Limit same-module suffix fallback in resolve_same_module to only fire if the receiver is a self-receiver or matches the module/namespace. Also reject matching dotted/colon-qualified callees targeting a Function to a different prefix in name lookup. This prevents false-positive recursion flags on store/delegation calls.

Signed-off-by: sahil-mangla <manglasahil2017@gmail.com>
Signed-off-by: sahil-mangla <manglasahil2017@gmail.com>
Java enums with methods (e.g. isWeekend/label in cp_enum_method_java)
have their method declarations inside enum_body_declarations, which is a
child of enum_body — not a direct child of enum_body itself.

find_class_body was returning the raw enum_body node (16 children:
enum_constant×7, commas, and the nested enum_body_declarations). As a
result, extract_class_methods iterated enum_constant/comma nodes and
never visited any method_declaration, so no Method nodes were created
and no CALLS edges resolved.

Fixes:
- find_class_body: if a body resolved via field-name lookup is enum_body,
  look for enum_body_declarations inside it and return that instead.
- find_class_body fallback loop: same unwrapping for the type-scan path.
- push_class_body_children: add enum_body and enum_body_declarations to
  the recognised body-container kinds so the walk_defs stack correctly
  scopes enum method children under the enum QN.

Tests: convergence_probe 47/47 passed (was 46/47, cp_enum_method_java
was the failing case).

Signed-off-by: sahil-mangla <manglasahil2017@gmail.com>
@sahil-mangla sahil-mangla force-pushed the main branch 2 times, most recently from 626802b to 4479649 Compare July 8, 2026 12:51
@DeusData DeusData added this to the 0.9.1-rc milestone Jul 8, 2026
Wrap two if-conditions that exceeded the 100-column limit:

- Line 3506: break &&-condition before the parenthesised ObjC/Java
  language check so the line stays within 100 cols.
- Lines 5860-5861: split the combined enum_body / enum_body_declarations
  comparison onto separate continuation lines to satisfy the limit.

No logic change; formatting only.

Signed-off-by: sahil-mangla <manglasahil2017@gmail.com>
@sahil-mangla

Copy link
Copy Markdown
Contributor Author

@DeusData Everything is ready for you to review it took me oddly big time to fix 6ab8a84 and the some of the automated test cases but everything should be ready for you check!

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

Labels

bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges priority/normal Standard review queue; useful PR with ordinary maintainer urgency.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Recursion flags still false-positive on store/delegation calls after #599 (soil.get, _default.check)

2 participants