-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
fix(php): interface/trait/enum declarations mint canonical nodes; sourced declarations win over sourceless lookup rivals; refuse relative-scope callees #2536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
088ce5c
9e73fc0
325d614
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -582,6 +582,11 @@ def _php_name_text(node, source: bytes) -> str | None: | |||||||||||||||||||||||
| return None | ||||||||||||||||||||||||
| return _read_text(node, source).rsplit("\\", 1)[-1] or None | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
Comment on lines
583
to
584
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relative-scope PHP calls (parent::/self::/static::) silently dropped — agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Graphify suggests a fix:
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looked into this properly — measured rather than reasoned about — and I'd like to decline it, for two independent reasons. The suggested edit is anchored on a function this path never calls. It patches Applied as intended, it reintroduces the defect in a different place. I patched the actual branch so a relative scope emits the method name as an unqualified callee, and re-ran extraction on a PHPUnit-shaped corpus (base class out of corpus, one unrelated in-corpus And it cannot be resolved correctly at that point. The raw-call record carries caller, callee, receiver and receiver type — no enclosing or base class. The On "silently": fair as a description of runtime behaviour, and the drop has no diagnostic counter. It is not undocumented, though — four tests in |
||||||||||||||||||||||||
| # PHP's relative scopes. Each is resolvable only against the inheritance context | ||||||||||||||||||||||||
| # of the class it is written in, which the raw-call facts do not carry, so none of | ||||||||||||||||||||||||
| # them ever names a concrete callee. | ||||||||||||||||||||||||
| _PHP_RELATIVE_SCOPE_NAMES = frozenset({"self", "static", "parent"}) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def _php_collect_type_refs(node, source: bytes, generic: bool, out: list[tuple[str, str]]) -> None: | ||||||||||||||||||||||||
| """Walk a PHP type expression; append (name, role) tuples.""" | ||||||||||||||||||||||||
| if node is None: | ||||||||||||||||||||||||
|
|
@@ -4378,7 +4383,15 @@ def walk_calls( | |||||||||||||||||||||||
| # Static method call: Helper::format() → callee = "Helper" | ||||||||||||||||||||||||
| scope_node = node.child_by_field_name("scope") | ||||||||||||||||||||||||
| if scope_node: | ||||||||||||||||||||||||
| callee_name = _read_text(scope_node, source) | ||||||||||||||||||||||||
| scope_text = _read_text(scope_node, source) | ||||||||||||||||||||||||
| # `parent::m()` / `self::m()` / `static::m()` name no | ||||||||||||||||||||||||
| # callee: which class the scope denotes needs inheritance | ||||||||||||||||||||||||
| # context the raw-call facts do not carry. Naming | ||||||||||||||||||||||||
| # the scope anyway let the cross-file label match bind | ||||||||||||||||||||||||
| # them to any unrelated `->parent()` method in the | ||||||||||||||||||||||||
| # corpus. Absolute scopes are unaffected. | ||||||||||||||||||||||||
| if scope_text.lower() not in _PHP_RELATIVE_SCOPE_NAMES: | ||||||||||||||||||||||||
| callee_name = scope_text | ||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||
| # member_call_expression: $obj->method() | ||||||||||||||||||||||||
| is_member_call = True | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolve_seed()16 callers depend on it (afferent coupling).
Grounded coupling-delta finding (deterministic), not an LLM guess.