Skip to content

[Reflection] Add ClassReflectionProvider facade over PHPStan ReflectionProvider - #8216

Open
TomasVotruba wants to merge 1 commit into
mainfrom
decouple-reflection-provider-facade
Open

[Reflection] Add ClassReflectionProvider facade over PHPStan ReflectionProvider#8216
TomasVotruba wants to merge 1 commit into
mainfrom
decouple-reflection-provider-facade

Conversation

@TomasVotruba

Copy link
Copy Markdown
Member

First step of lowering direct phpstan/phpstan coupling, while keeping all rules running on PHPStan's reflection underneath.

What

Class lookups now go through a narrow Rector-owned facade instead of PHPStan\Reflection\ReflectionProvider:

namespace Rector\Reflection;

final readonly class ClassReflectionProvider
{
    public function __construct(
        private ReflectionProvider $reflectionProvider,
    ) {
    }

    public function hasClass(string $className): bool;

    public function getClass(string $className): ClassReflection;
}

Call sites change mechanically:

-use PHPStan\Reflection\ReflectionProvider;
+use Rector\Reflection\ClassReflectionProvider;

 final class FinalizeTestCaseClassRector extends AbstractRector
 {
     public function __construct(
-        private readonly ReflectionProvider $reflectionProvider,
+        private readonly ClassReflectionProvider $classReflectionProvider,
         private readonly VisibilityManipulator $visibilityManipulator
     ) {
     }
 ...
-        if (! $this->reflectionProvider->hasClass($className)) {
+        if (! $this->classReflectionProvider->hasClass($className)) {
             return null;
         }

-        $classReflection = $this->reflectionProvider->getClass($className);
+        $classReflection = $this->classReflectionProvider->getClass($className);

Some files lose their last PHPStan import outright:

 namespace Rector\Skipper\SkipVoter;

-use PHPStan\Reflection\ReflectionProvider;
+use Rector\Reflection\ClassReflectionProvider;

Why

ReflectionProvider was imported in 68 files, but only 6 of its methods were ever called — and 55 files used nothing but hasClass() / getClass(). That is a wide import surface over a very narrow API.

Routing it through one class means a future change to how Rector resolves class reflection has a single edit point instead of 68.

Numbers

before after
files importing ReflectionProvider 68 16
rules/ files importing any PHPStan\ 342 336
changed files with zero phpstan/phpstan imports 0 10

The 16 remaining are engine internals (PHPStanNodeScopeResolver, NodeTypeResolver, AstResolver, ReflectionResolver, the DI factories) plus rules doing function/constant lookups — those need hasFunction() / getFunction() / hasConstant() / getAnonymousClassReflection(), deliberately left out of this facade. A function-lookup equivalent can follow separately.

No behaviour change: the facade delegates straight to the same ReflectionProvider instance, resolved by autowiring from the existing PUBLIC_PHPSTAN_SERVICE_TYPES registration.

…onProvider

Route class lookups through a narrow Rector-owned facade, so rules and
services no longer depend on PHPStan\Reflection\ReflectionProvider directly.

Files importing ReflectionProvider drop from 68 to 16; the remaining ones
are engine internals that also need function/constant/anonymous-class
lookups. 10 files lose their last phpstan/phpstan import entirely.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant