fix(objc): resolve dot-syntax property access and @selector() calls (#1475)#1543
fix(objc): resolve dot-syntax property access and @selector() calls (#1475)#1543guyoron1 wants to merge 1 commit into
Conversation
safishamsi
left a comment
There was a problem hiding this comment.
Thanks for tackling the two deferred ObjC follow-ups. A few changes needed before this can land.
1. Drop the #1308 commit from this PR. It re-includes the workspace exports-map work, but that already shipped on v8 (e8dabad, from your #1541) — and the merged version has two things this copy is missing: a package-dir containment guard (so an exports target like "./x": "../../../etc/..." can't resolve outside the package) and default consulted last in the condition order. The duplicate is also what's causing all the merge conflicts here. Please rebase on current v8 and reduce this PR to the ObjC changes only.
2. The dot-syntax / @selector resolution needs a scoping guard — this is the blocker. These two were deferred specifically because resolving an untyped name globally floods false edges. Right now the resolution suffix-matches the property/selector name against every method id, with no receiver-type restriction and no single-definition check. On a fixture with two classes that each declare a property named name, one self.product.name access fans out to both -name methods (plus the product class node) — four edges from one access. @selector(doThing) with two doThing methods resolves to both. That's the god-node inflation (#543/#1219) the deferral was meant to avoid.
Please resolve only to an unambiguous, in-scope definition:
- for
self.<prop>, restrict to the current class's own declared properties / the known receiver type; - for
@selector(...), emit only when exactly one method matches; - skip emission entirely when 0 or >1 candidates match (and don't match property names against class node ids).
3. Use accesses for dot-syntax, not calls. The issue scopes self.product.name to a property-access edge; the PR currently emits calls.
4. Add a fan-out regression test. The current tests are happy-path (one uniquely-named method, any(... in ...) assertions) and wouldn't catch the flooding above. Please add a two-same-named-property fixture asserting the exact edge count (no fan-out), plus an unresolvable-property case asserting zero edges, and the same for a two-same-named @selector.
For reference, the alloc/init reference edges that just landed (#1475 on v8) use the unique-stub guard (ensure_named_node + _rewire_unique_stub_nodes, which only resolves when exactly one class of that name exists) — the same "resolve only when unambiguous" idea applies here. The new walk_calls branches otherwise coexist fine with that change, so once the guard and the rebase are in, this should be a clean ObjC-only PR. Thanks again.
5bd5d0b to
9142946
Compare
|
Hey !!!
All tests pass. |
Graphify-Labs#1475) Add field_expression handler in walk_calls so dot-syntax property access (self.name) produces an `accesses` edge scoped to the current class — only resolves when exactly one sibling method matches, preventing god-node fan-out when multiple classes declare the same property name. Add selector_expression handler so @selector(method) compile-time references produce a `calls` edge — only when exactly one method matches across the entire file, skipping ambiguous names entirely. Both guards follow the same "resolve only when unambiguous" principle as the alloc/init unique-stub guard from Graphify-Labs#1475. Five new tests cover happy-path, fan-out regression (two same-named properties/selectors), and unresolvable-property edge cases.
9142946 to
476fac1
Compare
…1475, #1543) `self.product.name` dot-syntax now emits an `accesses` edge and `@selector(method)` emits a `calls` edge, both resolved only to an unambiguous in-scope definition (a sibling method of the same class for dot-syntax; exactly one method by exact selector name for @selector) so no false-edge fan-out occurs when multiple classes share a name. Hardened over the original PR: resolution now matches the method node id EXACTLY (a method id is _make_id(container, name)) rather than by `endswith` suffix. The substring match would mis-resolve `self.name` to a sibling `-surname` (false positive) and, when a substring-colliding sibling existed, suppress the correct edge (false negative); exact matching fixes both. Adds substring-collision regression tests (`-name`/`-surname`, `-doThing`/`-reallyDoThing`). Completes the #1475 ObjC follow-ups (Bug 5 dot-syntax accesses, Bug 6b @selector target-action). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Merged into One change I made on top: the resolver matched the method node id by |
README: document that `reflect --graph` writes the .graphify_learning.json overlay and that explain/query surface a Lesson hint (with the code-changed staleness flag). CHANGELOG: add an Unreleased section for the post-0.9.2 work — the work-memory overlay (#1441/#1542), this.field.method() injected-field resolution (#1316), TS wildcard path aliases (#1544), JS namespace re-exports (#1552), and the ObjC dot-syntax/@selector edges (#1475/#1543). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
field_expressionhandler inwalk_callsso dot-syntax property access (self.name,self.product.name) producescallsedges — previously invisible because the grammar emitsfield_identifier, not a message sendselector_expressionhandler so@selector(method)compile-time references producecallsedges — previously unhandled node typemessage_expressionhandlerCloses the remaining two sub-bugs from #1475 (Bug 5: dot-syntax, Bug 6: @selector).
Test plan
test_objc_dot_syntax_property_calls_edge— verifiesself.nameresolves to a calls edgetest_objc_selector_expression_calls_edge— verifies@selector(fetch)resolves to a calls edge