Resolve C# cross-file type references and extract enum/struct/record declarations#1466
Closed
TheFedaikin wants to merge 1 commit into
Closed
Resolve C# cross-file type references and extract enum/struct/record declarations#1466TheFedaikin wants to merge 1 commit into
TheFedaikin wants to merge 1 commit into
Conversation
…record extraction
safishamsi
pushed a commit
that referenced
this pull request
Jun 27, 2026
…cord (#1466) Adds _resolve_csharp_type_references (graphify/extractors/csharp.py), the C# counterpart to _resolve_java_type_references. It re-points dangling inherits/implements/references edges from no-source shadow stubs onto the real definitions, disambiguating same-named types across namespaces using the referencing file's `using` directives + enclosing namespace; ambiguous matches are refused (unique-hit guardrail), not guessed. Runs after id-disambiguation and the sourceless-stub rewire, on the ambiguous remainder, behind a log-and-skip try/except. _CSHARP_CONFIG is broadened to extract enum/struct/record as type definitions so references to them resolve too. Ported from PR #1466 by @TheFedaikin. Known follow-up: types declared in nested/multiple namespaces in one file aren't registered as targets yet (fails safe — under-resolves to a stub, never mis-resolves). Advances #1318 for C#. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
|
Thanks @TheFedaikin — faithful C# port of the Java type-reference resolver, with the unique-hit guardrail correctly refusing ambiguous |
This was referenced Jun 27, 2026
safishamsi
added a commit
that referenced
this pull request
Jun 28, 2026
Dates the 0.8.51 CHANGELOG and bumps the version. Highlights: Obsidian export no longer overwrites user notes / .obsidian config in an existing vault (#1506); cross-file node-ID cluster fixes — C# resolver (#1466), Go sourceless stubs (#1500), import-stub disambiguation (#1462); Java enum/annotation type nodes (#1512) + generic parents (#1510); explain/affected source-file path lookup (#1503); claude-cli Windows GBK fix (#1505); macOS install docs (#1471) and the global-add docs fix (#1489). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
safishamsi
pushed a commit
that referenced
this pull request
Jun 30, 2026
Extends the C# type-reference resolver (#1466) to be namespace-aware, advancing the #1318 shadow-node umbrella for C#: - The namespace is folded into the C# node id (_make_id(stem, namespace, name)), so two same-named types in different namespaces in one file no longer collapse — replacing #1466's detect-and-skip workaround for multi-namespace files. - Lexical per-block using-scope: a `using` applies only where it is in scope (file-level, or the enclosing namespace block via a scope chain), so sibling namespace blocks no longer share each other's usings. - Qualified references (`Namespace.Type`) resolve via in-scope aliases (`using Q = X.Y`) then exact known namespaces; generics are stripped. Preserves (and tightens) the refuse-rather-than-guess discipline: a bare reference resolves only when exactly one in-scope namespace provides the type; an ambiguous reference (e.g. `using A; using B;` both defining `Widget`) resolves to nothing rather than fanning out. Verified: `using A` -> A.Widget only; ambiguous -> no edge; qualified `B.Widget` -> B.Widget regardless of usings; sibling-block using-scope isolated; no dangling edges or fan-out. Reconciled onto current v8 (the PR predated the C++/ObjC member-call resolvers); full suite green, the C++/ObjC resolution coexists. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a deterministic C# cross-file type-reference resolver so dangling inherits / implements
/ references edges re-point from no-source "shadow" stubs to their real definitions,
disambiguating same-named collisions (e.g. WeaponData defined in two namespaces) by the
referencing file's using directives + enclosing namespace. This is the C# counterpart to the
Java type-reference resolver (#1318).
Motivation
Cross-file C# type references resolve by bare name and fall back to a no-source shadow stub.
_rewire_unique_stub_nodes repairs that only when a name is globally unique; when two
namespaces define a same-named type it bails, so the edge stays stuck on the shadow node and
the real type is wrongly isolated. A using N; directive (plus the enclosing namespace) names
the scope precisely, so it disambiguates where bare-name matching cannot.
What changed
all_nodes, all_edges). Mirrors _resolve_java_type_references. Runs after id-disambiguation
and _rewire_unique_stub_nodes, so it only handles the ambiguous remainder. Mutates
nodes/edges in place and drops shadow stubs no edge references anymore.
Java type-reference resolution, behind a try/except that logs-and-skips so extraction never
breaks. extract.py re-exports the resolver name (callers/imports unchanged).
enum_declaration, struct_declaration, and record_declaration as type definitions (previously
only class/interface). References to C# enums, structs, and records now get real definition
nodes the resolver can re-point to.
Design notes
C# deltas from the Java resolver:
namespace and accepting only a unique hit — the god-node guardrail (ambiguous matches are
refused, not picked arbitrarily).
Placement follows the extractor-split conventions (#1212): csharp.py imports shared
primitives (_read_text) from extractors.base, keeps the one-way import direction (extract.py
→ extractors/, never the reverse), and extract.py re-exports the moved name. The
config-driven extract_csharp extractor stays in extract.py for now — per
extractors/MIGRATION.md, config-driven languages can't be ported until the shared
_extract_generic core moves as its own coordinated batch; extractors/csharp.py is its
eventual home.
Tests
tests/test_csharp_type_resolution.py — 7 cases:
Verification
.cs inputs.
correct definition via using directives, while genuinely-external types (Unity/.NET)
correctly stay unresolved.