Connects paired classes across files: Main.cpp's `Foo f; f.bar()` now resolves
to Foo::bar, and ObjC `Foo *f = [[Foo alloc] init]; [f doThing]` to Foo's
doThing — the "connect with other classes" goal of #1547/#1556.
Design grounded in prior-art research (ctags qualified-name matching, Doxygen's
name-keyed false-edge failure modes, PAIGE's receiver-type approach, Clang USR):
resolve by RECEIVER TYPE, never bare name, and skip when the type can't be
inferred rather than guess (a false call edge / god-node is worse than a missing
one). Mirrors the existing Swift/Python/Ruby/TS member-call resolvers.
- C++ extractor now captures the member-call receiver (field_expression /
qualified_identifier / pointer access) and builds a per-file type table from
local declarations (`Foo f;`, `Foo* f;`, `Foo *f = ...;`); emits raw_calls.
- ObjC extractor emits raw_calls for message sends with the receiver + selector
and a type table from `Foo *f = ...;` locals (existing in-file selector /
alloc-init / dot-syntax / @selector matching preserved).
- New _resolve_cpp_member_calls / _resolve_objc_member_calls, registered for
their suffixes. Receiver tiers: `Foo::bar()` / capitalized ObjC receiver and
this/self/super (enclosing class) -> EXTRACTED; local-var-typed -> INFERRED.
Single-definition god-node guard (skip unless exactly one type def matches);
the just-shipped decl/def class merge makes a paired class one def so the
guard resolves it. Verified: a.run() -> A::run only (not a same-named B::run);
an uninferable receiver with run() in two classes emits zero edges (no
fan-out); ObjC [f doThing] -> Foo only.
- build.py: the cross-language INFERRED-call prune treated .h/.cpp/.m as
different families and dropped header/impl interop calls; unified the C family
(.c .h .cc .cpp .hpp .cxx .hh .hxx .cu .cuh .metal .m .mm) so a .cpp/.m call to
a .h-declared method survives.
Still open (tracked on #1547/#1556): the file-level `#include` edge can stay
uncanonicalized when the project root isn't symlink-resolved (the extract()
id-remap `continue`s on a /var-vs-/private/var mismatch) — the class connection
above is robust to it; include-reachability candidate narrowing and ObjC
dynamic-dispatch/id-typed receivers also deferred (expected low ObjC recall, per
the research).
Reported by @c0dezer019 (#1547) and @JabberYQ (#1556).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>