Skip to content

Take SymbolExtractor's declarations from the scanner - #418

Merged
Firehed merged 2 commits into
mainfrom
slice/SC.3
Aug 14, 2026
Merged

Take SymbolExtractor's declarations from the scanner#418
Firehed merged 2 commits into
mainfrom
slice/SC.3

Conversation

@Firehed

@Firehed Firehed commented Aug 14, 2026

Copy link
Copy Markdown
Owner

SymbolExtractor walked the AST itself to decide what a file declares, while every other consumer asked DeclarationScanner. Two opinions about the same question is how a function_exists-guarded polyfill came to resolve on hover while being invisible to completion (SC.5), and how its class_exists twin dropped out of open-document lookup (SC.9). This is the last of those in src/, so no consumer can now disagree about what a file declares.

Slice SC.3. Plan step: 0002 Step 3a teardown. RFC 1 §4.2, §8.1.

What changed

SymbolExtractor no longer extends NodeVisitorAbstract or builds a NodeTraverser. It reads DeclarationScanner's class-likes and functions, and takes each class-like's methods from ClassLike::getMethods() on the node the scanner already hands back.

Deleted with it: the hand-tracked $namespace field, the Stmt\Namespace_ branch, the leaveNode reset, and the three places an FQN was rebuilt by string concatenation against a namespacedName the parser had already computed.

The one thing added is a sort. The scanner returns class-likes and functions as separate lists, and callers read $symbols[0] as the file's first declaration, so the output is ordered by position rather than by kind.

Behaviour

Preserved, and proven by tests that already existed rather than new ones: WritePathParityTest and PrefixSearchParityTest both drive a real SymbolExtractor and passed without regenerating a golden, alongside SymbolExtractorTest's per-kind cases.

One latent bug goes away as a side effect. leaveNode reset the current class to null rather than to the enclosing one, so after a nested class-like closed, the outer class's remaining methods stopped being indexed. Methods now come from each class-like's own node, so nesting cannot drop them.

Baseline

phpstan-baseline.neon 43 → 39. The four drained are exactly this file's frozen AST-traversal violations; bin/check-baseline-shrink records the shrink. The confinement rule in phpstan.neon was already enforcing this — the entries were what kept it quiet.

Checklist

  • SymbolExtractor no longer references NodeVisitorAbstract, NodeTraverser or NodeFinder
  • Class-like kind mapping and Class::method FQN strings unchanged, pinned by the existing tests
  • Its four baseline entries drained, not relocated
  • Parity goldens pass unregenerated
  • No new fixtures, no new enforcement — the rule for this already exists

Notes

Two manifest rows are now wrong and neither is edited here, to keep this diff to one file. SC.3's own note says Class::method FQNs "are its own and stay", which read as blocking — getMethods() is the route it missed. SC.10 is filed as "the invariant has no mechanism"; phpstan.neon has enforced it all along, so that row has no work in it.

Candidate closes (pending review verification): none.

@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.61%. Comparing base (d101d21) to head (2aea286).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##               main     #418      +/-   ##
============================================
- Coverage     98.62%   98.61%   -0.02%     
+ Complexity     1814     1805       -9     
============================================
  Files           128      128              
  Lines          4571     4534      -37     
============================================
- Hits           4508     4471      -37     
  Misses           63       63              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@Firehed
Firehed marked this pull request as ready for review August 14, 2026 23:56
@Firehed
Firehed merged commit 71835ac into main Aug 14, 2026
9 checks passed
@Firehed
Firehed deleted the slice/SC.3 branch August 14, 2026 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant