Skip to content

Add type-aware cross-file resolver for C##355

Open
Esderal wants to merge 1 commit intosafishamsi:v4from
Esderal:csharp-cross-file-resolver
Open

Add type-aware cross-file resolver for C##355
Esderal wants to merge 1 commit intosafishamsi:v4from
Esderal:csharp-cross-file-resolver

Conversation

@Esderal
Copy link
Copy Markdown

@Esderal Esderal commented Apr 14, 2026

Builds a global type registry (classes, interfaces, structs, records with
methods, fields, properties, and base types) from all .cs files, then
re-walks each method body with a type-tracking scope to resolve call
receivers through fields, properties, parameters, locals, this/base, and
inheritance chains. Respects using directives for namespace-scoped
disambiguation. Emits calls and instantiates edges for cross-file
resolutions only; same-file calls remain with the per-file extractor to
avoid duplication.

On a 112-file C# corpus this lifts cross-file edges from 0 to ~1445
(1028 calls + 417 instantiates) and produces god-node rankings that
match human intuition about subsystem hubs.

Known limitations (documented in comments):

  • Chained calls (.A().B()) needs return-type tracking
  • Extension methods needs using-static + this-parameter detection
  • Generic type arguments collapsed to base type name
  • Overloads: last declaration wins on name collisions

Open to feedback on:

  • Whether instantiates is the right relation name, or if the project prefers creates / constructs

  • Whether same-file filtering should be opt-out behind a flag (currently always on — rationale: the per-file extractor already captures same-file calls, so emitting them again would duplicate edges)

  • Placement — I put the new code next to _resolve_cross_file_imports since it plays the same role for C#; happy to move it to a separate module if you'd prefer

  • The _CS_NOISE concept from the earlier naive version is gone entirely in this patch — type resolution replaces name-based filtering. If you'd like me to add a safety net list anyway, let me know.

    First open-source PR for me, so please be blunt about anything that doesn't fit the project's style — I'd rather fix it than have it linger.

Builds a global type registry (classes, interfaces, structs, records with
methods, fields, properties, and base types) from all .cs files, then
re-walks each method body with a type-tracking scope to resolve call
receivers through fields, properties, parameters, locals, this/base, and
inheritance chains. Respects using directives for namespace-scoped
disambiguation. Emits calls and instantiates edges for cross-file
resolutions only; same-file calls remain with the per-file extractor to
avoid duplication.

On a 112-file C# corpus this lifts cross-file edges from 0 to ~1445
(1028 calls + 417 instantiates) and produces god-node rankings that
match human intuition about subsystem hubs.

Known limitations (documented in comments):
- Chained calls (.A().B()) needs return-type tracking
- Extension methods needs using-static + this-parameter detection
- Generic type arguments collapsed to base type name
- Overloads: last declaration wins on name collisions
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