Skip to content

fix(csharp): resolve fluent-chain receivers, generic member names, and type twins for call recall - #787

Merged
vitali87 merged 9 commits into
mainfrom
fix/csharp-recall-tail
Jul 18, 2026
Merged

fix(csharp): resolve fluent-chain receivers, generic member names, and type twins for call recall#787
vitali87 merged 9 commits into
mainfrom
fix/csharp-recall-tail

Conversation

@vitali87

Copy link
Copy Markdown
Owner

What

Round 1 of the C# calls-recall campaign (follows the dead-code dogfood, #782/#784/#785/#786): three resolution gaps behind Polly's fluent-API surface. The retrieval eval gains 280 true call edges with zero new false positives: tp 3113 -> 3393, recall 0.7828 -> 0.8532, f1 0.8781 -> 0.9208, precision stays 1.0000. The dead-code report is unchanged at its single verified true positive.

Root causes and fixes

  1. Generic member names never matched (+242 edges). Policy.Handle<InvalidOperationException>() keeps its type arguments through both call-name extraction and the member resolver, while methods register generic-free, so Polly's whole fluent entry point emitted nothing. Both paths now strip the type-argument list.
  2. Object-creation and invocation receivers were untypable. new Builder().Add() and Policy.Handle<T>().Wrap(...) hand the resolver receiver nodes it had no branch for. An object-creation receiver IS its type; an invocation receiver types the next hop through the resolved inner call's recorded return type (new csharp_method_return_types, recorded at both the member-ingest and #if-recovery paths from the returns field, which is the C# grammar's return-type field; there is no type field on methods). Mirrors the existing C++ chained-factory typing.
  3. Generic/non-generic type twins killed the chain and extension binding. ResiliencePipelineBuilder and ResiliencePipelineBuilder<TResult> share a simple name, so the receiver-type sweep returned None (ambiguity) and the extension matcher's unqualified-ambiguity guard refused to bind. Class declarations now record their type-parameter count (csharp_class_generic_arity); the type sweep filters candidates by the reference's written arity, and the extension guard treats same-name declarations that all differ by generic arity as non-ambiguous (a compilable call binds the unique matching extension; true N1.Widget/N2.Widget namespace splits, same arity, stay guarded).

Validation

  • RED demonstrated in commit history for all three fixes (generic member call, object-creation receiver, chained-return receiver, twins disambiguation).
  • Full suite green; all 143 C# tests pass.
  • C# retrieval eval (full Polly, Roslyn oracle): tp 3113 -> 3393, fp 0 -> 0, precision 1.0000, recall 0.7828 -> 0.8532.
  • Polly dead-code: unchanged at 1 (the verified PolicyBuilder true positive), zero new findings.

Remaining recall tail (~584)

Dominated by two classes for follow-up rounds: BCL-name collisions in the eval reduction (Cancel, Add, Dispose, ToString on BCL receivers that share a simple name with first-party declarations; needs eval-semantics investigation before touching the graph) and deeper chains through field-typed or awaited receivers.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances C# type inference and call resolution, particularly for generic types and fluent/chained method calls. It introduces tracking of C# class generic arity and method return types during ingestion. These additions allow the type inference engine to resolve chained invocations (such as Policy.Handle<T>().Wrap(...)), handle object creation expressions as receivers, and disambiguate same-name classes that differ by generic arity (e.g., Builder vs. Builder<TResult>). Corresponding unit tests have been added to verify these improvements. I have no feedback to provide as there are no review comments.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves C# call recall for fluent APIs and generic type variants. The main changes are:

  • Generic member call names are normalized before resolver lookup.
  • Object-creation and chained invocation receivers are typed for follow-up calls.
  • C# method return types and class generic arity are recorded during ingestion.
  • Extension method matching now includes receiver generic arity.
  • Tests cover generic member calls, fluent chained calls, object-creation receivers, and generic/plain type twin cases.

Confidence Score: 5/5

This PR appears safe to merge with low risk.

No blocking correctness or security issues were identified in the changed C# inference paths. The updated code includes focused tests for the main resolver cases changed by this PR. Previously reported arity-context issues appear addressed in the reviewed code.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Reviewed the focused pytest blocker log captured after C# parser dependencies were installed.
  • Verified that the fallback parser-level validation completed with EXIT_CODE: 0 and all C# parser smoke checks passed.
  • Inspected the generated executable harness used for the fallback parser-level validation.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
codebase_rag/parsers/csharp/type_inference.py Extends C# call resolution for generic member names, object-creation receivers, invocation-chain return types, and generic-arity disambiguation.
codebase_rag/parsers/csharp/utils.py Adds C# type normalization and generic-arity helpers and includes extension receiver arity in the extension index.
codebase_rag/parsers/class_ingest/mixin.py Records C# class generic arity and method return types during normal member ingestion.
codebase_rag/parsers/function_ingest.py Records C# method return types for recovered/truncated member ingestion paths.
codebase_rag/tests/test_csharp_type_inference.py Adds tests for object creation, chained return receivers, and generic/plain builder disambiguation.
codebase_rag/tests/test_csharp_extension_methods.py Adds tests preventing generic receivers from binding non-generic extension receivers.
codebase_rag/tests/test_csharp_calls.py Adds tests for generic member calls on class receivers.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Ingest as C# ingestion
participant Indexes as Arity/return-type indexes
participant Resolver as Type inference resolver
participant Calls as CALLS edge emission

Ingest->>Indexes: Record class generic arity and method return types
Ingest->>Indexes: Index extension receiver type and arity
Resolver->>Resolver: Strip generic call-name type arguments
Resolver->>Indexes: Resolve object creation or inner invocation receiver
Indexes-->>Resolver: Return receiver type and generic arity
Resolver->>Calls: Emit matching instance or extension method edge
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Ingest as C# ingestion
participant Indexes as Arity/return-type indexes
participant Resolver as Type inference resolver
participant Calls as CALLS edge emission

Ingest->>Indexes: Record class generic arity and method return types
Ingest->>Indexes: Index extension receiver type and arity
Resolver->>Resolver: Strip generic call-name type arguments
Resolver->>Indexes: Resolve object creation or inner invocation receiver
Indexes-->>Resolver: Return receiver type and generic arity
Resolver->>Calls: Emit matching instance or extension method edge
Loading

Reviews (3): Last reviewed commit: "fix(csharp): keep caller context when re..." | Re-trigger Greptile

Comment thread codebase_rag/parsers/csharp/type_inference.py
@vitali87

Copy link
Copy Markdown
Owner Author

@greptile review

Comment thread codebase_rag/parsers/csharp/type_inference.py Outdated
@vitali87

Copy link
Copy Markdown
Owner Author

@greptile review

@vitali87
vitali87 force-pushed the fix/csharp-recall-tail branch from ca59e6c to dcb0846 Compare July 18, 2026 09:53
@sonarqubecloud

Copy link
Copy Markdown

@vitali87
vitali87 merged commit ba162a9 into main Jul 18, 2026
22 checks passed
@vitali87
vitali87 deleted the fix/csharp-recall-tail branch July 18, 2026 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant