Conversation
CursorTextSyntaxSource sits last in the composite: `parse()` returns empty and `nodeAt()` synthesizes a PropertyFetch or StaticPropertyFetch from the cursor's line text so member access resolves on a document php-parser cannot make sense of. PhpParserSyntaxSource yields to it by tagging its tree and returning null from `nodeAt()` when that marker is absent or the innermost hit is a bare Stmt. SkeletonSyntaxSource keeps the class body of a `class X extends Y` without an opening brace and pins method parameter types so a `$var` receiver types through Scope::atOffset. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The two resolvers no longer name TextFallbackHelper or EnclosingClassResolver: the cursor-text SyntaxSource hands MemberAccessDetector::detect a member- access node the tree walker already accepts, and ExpressionResolver reads the enclosing class-like from Scope::atOffset on the node's file position. TextFallbackHelper loses `matchMemberAccessAt` (moved to CursorTextSyntaxSource); EnclosingClassResolver keeps only its `seedThisPosition` helper. When a `$this` sits outside any class-like scope (a recovered file-scope statement), ExpressionResolver falls back to the last class-like declared before the expression. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- OneRoutePerFactTest drops the MemberAccessDetector and EnclosingClassResolver pending entries from the text-helper row. - ParseHealthGridTest removes the resolveAtPosition empty-state skip. - AstTextAgreementTest's member-access section becomes cursor agreement: same receiver-node kind, same short receiver name, same member name from the full composite and from CursorTextSyntaxSource alone. - MemberAccessDetectorTest drops the direct fromText tests (the method is gone; the outside-a-class case is still covered through detect()). - SymbolResolverTest updates the nullable-parameter assertion — the new tree-typed path preserves the nullable, which the text path used to strip. - EnclosingClassResolverTest removed; its methods no longer exist. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The completion parity golden for `broken_inheritance_instance` now includes `testInstance` and `testStatic`: the improved class-body slicing keeps them in the class the old code truncated away. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #505 +/- ##
============================================
- Coverage 99.42% 99.23% -0.20%
- Complexity 1888 1904 +16
============================================
Files 139 140 +1
Lines 4868 4949 +81
============================================
+ Hits 4840 4911 +71
- Misses 28 38 +10 ☔ View full report in Codecov by Harness. |
Read the enclosing class-like through Scope::atOffset alone; drop the parent-chain first / position-fallback pattern the step-40 slice left in place. Tests exercise both parsed and synthesized cursor nodes and pass through the position route. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move the walk-back to the last class-like declared before an offset from ExpressionResolver::resolve into Scope::classLikeForThisAt, so \$this typing calls one method and Scope holds both routes to the enclosing class-like the receiver refers to. The completion vantage and Scope construction stay on the strict lookup. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Files a new row before the retire step so the second route in MemberAccessDetector::resolveStaticAccessContext (LateBindingKeyword called alongside ExpressionResolver's scope-based path) is closed as part of the manifest, not deferred to plain issue flow. Shifts the retire step to step-54. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Firehed
marked this pull request as ready for review
September 6, 2026 21:05
Scope::lastClassLikeIn: extract the four-alternative class-like check into an isClassLikeStmt predicate and switch to early returns so pcov tracks each branch. Add ScopeTest cases that walk back to a class declared above a file-scope $this, and confirm the null answer when no class-like exists. SkeletonSyntaxSource::parseTypeText: consolidate three empty-input guards into one check on the first union member; explode on an empty string still yields one element, so this one check catches every empty shape the buildParams regex admits. Add a SkeletonSyntaxSourceTest case for an untyped parameter, which triggers the guard. CursorTextSyntaxSource: new test file pinning parse(), the offset- out-of-range guard in nodeAt, and the FullyQualified branch in buildStatic. Co-Authored-By: Claude Opus 4.7 <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.
Done
MemberAccessDetectornorExpressionResolvernamesTextFallbackHelperorEnclosingClassResolver— verified by grep and byOneRoutePerFactTest.resolveAtPositioncell passes in the empty state and its entry is gone fromemptyStateSkips()(ParseHealthGridTest).getMemberAccessContextcell still passes in every state (ParseHealthGridTest).MemberAccessDetectoris gone (OneRoutePerFactTest).CompletionParityTestis green. One golden entry (broken_inheritance_instance) gained two methods (testInstance,testStatic) that the class actually declares; the old code missed them because the class-body slicer latched onto a member's brace when the class had no opening brace of its own. This is a correction, not a regression.Closes nothing — this is a build-manifest step.