Namespace-aware C# type resolution and member-call receiver inference#1620
Open
TheFedaikin wants to merge 2 commits into
Open
Namespace-aware C# type resolution and member-call receiver inference#1620TheFedaikin wants to merge 2 commits into
TheFedaikin wants to merge 2 commits into
Conversation
# Conflicts: # graphify/extract.py
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 two C# capabilities and splits the C# extractor out of the 16.6k-line
graphify/extract.pyinto dedicated modules:class/interface/enum/struct/recordreferences resolve to their real definitions across files, namespace- and
using-aware, with lexical using-scope and qualified references.receiver.Method()calls become realcallsedges by inferring the receiver's type, under a strictnever-wrong-edge bar: any ambiguity is skipped, never guessed.
This supersedes #1609 (see below).
This builds on and improves upon
#1609(see below).Relationship to
#1609#1609 ("C# receiver-typed member-call resolution") introduced the first C#
receiver-typed resolver: a file-wide, first-binding-wins name → type table with
this/ capitalized-type / receiver-type resolution, inline inextract.py.This PR builds on that foundation and improves upon it with a modular, tiered
implementation — it keeps every
#1609case working (including the_server.Save()lowercase-field ambiguity) and adds more receiver tiers,method-return
varinference, lexical (rather than file-wide) scoping withshadow/poison handling, and the module split.
#1609's inline resolver is foldedinto the modular version here, and its cases are carried into the 61-test suite
alongside the new tiers.
Cross-file type resolution
file-scoped
namespace N;) and a lexical scope chain.using-aware: file-scopedusing,namespace-scoped
using,global using, and the global namespace.N.Type) and unqualified references both resolve tothe real definition, including cross-file inheritance (
class Weapon : Damage).namespaces, a reference binds only to the unique candidate reachable from the
referrer's usings; genuinely ambiguous references stay dangling rather than bind
to an arbitrary definition.
Member-call receiver resolution
obj.M()resolves to the real method when the receiver's type is known or safelyinferable:
Service x = …; x.M()this.field— including inherited membersthrough a single resolvable base chain
this.M()/ implicit-enclosing —M()inside a typeType.M(),Ns.Type.M()var—var x = Get(); x.M(), inferred from the callee'sunique bare return type resolved in the callee's namespace context
(emitted as
INFERRED)Everything else is skipped, not guessed: overloaded RHS, non-bare returns
(
T[],T?,N.T,Box<T>,ref, tuples, type parameters,void),reassigned/redeclared or shadowed locals, cross-file name collisions without a
unique resolution, extension methods, and chained receivers (
a.b.c.M()).Modular C# extractor (no behavior change from the split)
extractors/csharp_extract.py— per-file C# extraction (binding/type-table/shadow model, type references, imports).
extractors/csharp_resolve.py— the member-call resolver.extractors/csharp.py— cross-file name resolver + corpus passes.LanguageConfig→extractors/base.py; C#-only logic lifted out of the shared_extract_genericcore into fact-returning helpers.extract.pyre-exports every moved name (import surface unchanged); the splititself is byte-identical extractor output, verified by a per-entry-point
node/edge snapshot.
Docs
extractors/MIGRATION.mdupdated to record the C# module layout and the"split the language helpers + cross-file resolver, leave the config-driven
extract_<lang>entry point inextract.py" pattern — a middle path forconfig-driven languages the doctrine previously said had to wait for the shared
_extract_genericbatch.Testing
tests/test_csharp_member_calls.py: 61 receiver-resolution + never-wrong-edgetests.
tests/test_csharp_type_resolution.py: cross-file resolution.(overload, RHS allow-list, scope-shadow stop, callee-context resolution) fails
a test.