diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ca35341dc9a..76efc63f397 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -669,18 +669,6 @@ parameters: count: 1 path: src/Rules/Generics/TemplateTypeCheck.php - - - rawMessage: 'Function class_implements() is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine. Use objects retrieved from ReflectionProvider instead.' - identifier: phpstanApi.runtimeReflection - count: 1 - path: src/Rules/LazyRegistry.php - - - - rawMessage: 'Function class_parents() is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine. Use objects retrieved from ReflectionProvider instead.' - identifier: phpstanApi.runtimeReflection - count: 1 - path: src/Rules/LazyRegistry.php - - rawMessage: 'Method PHPStan\Rules\LazyRegistry::getRulesByNodeType() return type with generic interface PHPStan\Rules\Rule does not specify its types: TNodeType' identifier: missingType.generics diff --git a/src/Collectors/Registry.php b/src/Collectors/Registry.php index c0ff3dd4048..9bcfdc39030 100644 --- a/src/Collectors/Registry.php +++ b/src/Collectors/Registry.php @@ -4,8 +4,8 @@ use PhpParser\Node; use PHPStan\DependencyInjection\AutowiredService; -use function class_implements; -use function class_parents; +use PHPStan\Reflection\ReflectionProvider; +use PHPStan\Type\ExtensionClassHelper; #[AutowiredService(factory: '@PHPStan\Collectors\RegistryFactory::create')] final class Registry @@ -20,7 +20,10 @@ final class Registry /** * @param Collector[] $collectors */ - public function __construct(array $collectors) + public function __construct( + array $collectors, + private ReflectionProvider $reflectionProvider, + ) { foreach ($collectors as $collector) { $this->collectors[$collector->getNodeType()][] = $collector; @@ -35,7 +38,7 @@ public function __construct(array $collectors) public function getCollectors(string $nodeType): array { if (!isset($this->cache[$nodeType])) { - $parentNodeTypes = [$nodeType] + class_parents($nodeType) + class_implements($nodeType); + $parentNodeTypes = ExtensionClassHelper::getExtensionClassNames($this->reflectionProvider, $nodeType); $collectors = []; foreach ($parentNodeTypes as $parentNodeType) { diff --git a/src/Collectors/RegistryFactory.php b/src/Collectors/RegistryFactory.php index 8ae688dc04e..a387fa2a948 100644 --- a/src/Collectors/RegistryFactory.php +++ b/src/Collectors/RegistryFactory.php @@ -6,6 +6,7 @@ use PHPStan\DependencyInjection\AutowiredExtensions; use PHPStan\DependencyInjection\AutowiredService; use PHPStan\DependencyInjection\ExtensionsCollection; +use PHPStan\Reflection\ReflectionProvider; #[AutowiredService] final class RegistryFactory @@ -19,6 +20,7 @@ final class RegistryFactory public function __construct( #[AutowiredExtensions(of: Collector::class)] private ExtensionsCollection $collectors, + private ReflectionProvider $reflectionProvider, ) { } @@ -27,6 +29,7 @@ public function create(): Registry { return new Registry( $this->collectors->getAll(), + $this->reflectionProvider, ); } diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index d15b89bcdc0..5e79bbd8a38 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -11,6 +11,7 @@ use PHPStan\DependencyInjection\Container; use PHPStan\DependencyInjection\ContainerFactory; use PHPStan\DependencyInjection\DerivativeContainerFactory; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\DirectRegistry as DirectRuleRegistry; use Throwable; use function array_fill_keys; @@ -59,7 +60,7 @@ public function validate(array $stubFiles, bool $debug): array $analysedFiles = array_fill_keys($stubFiles, true); $ruleRegistry = new DirectRuleRegistry($container->getServicesByTag(self::SERVICE_RULE_TAG)); - $collectorRegistry = new CollectorRegistry([]); + $collectorRegistry = new CollectorRegistry([], $container->getByType(ReflectionProvider::class)); $errors = []; foreach ($stubFiles as $stubFile) { diff --git a/src/Rules/LazyRegistry.php b/src/Rules/LazyRegistry.php index feb0593424e..de9ce48e01f 100644 --- a/src/Rules/LazyRegistry.php +++ b/src/Rules/LazyRegistry.php @@ -6,8 +6,8 @@ use PHPStan\DependencyInjection\AutowiredExtensions; use PHPStan\DependencyInjection\AutowiredService; use PHPStan\DependencyInjection\ExtensionsCollection; -use function class_implements; -use function class_parents; +use PHPStan\Reflection\ReflectionProvider; +use PHPStan\Type\ExtensionClassHelper; #[AutowiredService(name: 'registry', as: Registry::class)] final class LazyRegistry implements Registry @@ -27,6 +27,7 @@ final class LazyRegistry implements Registry public function __construct( #[AutowiredExtensions(of: Rule::class)] private ExtensionsCollection $rules, + private ReflectionProvider $reflectionProvider, ) { } @@ -39,7 +40,7 @@ public function __construct( public function getRules(string $nodeType): array { if (!isset($this->cache[$nodeType])) { - $parentNodeTypes = [$nodeType] + class_parents($nodeType) + class_implements($nodeType); + $parentNodeTypes = ExtensionClassHelper::getExtensionClassNames($this->reflectionProvider, $nodeType); $rules = []; $rulesFromContainer = $this->getRulesByNodeType(); diff --git a/src/Testing/RuleTestCase.php b/src/Testing/RuleTestCase.php index d070726072c..7b975cd2475 100644 --- a/src/Testing/RuleTestCase.php +++ b/src/Testing/RuleTestCase.php @@ -134,13 +134,18 @@ protected function createNodeScopeResolver(): NodeScopeResolver private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser { if ($this->analyser === null) { - $collectorRegistry = new CollectorRegistry($this->getCollectors()); + $reflectionProvider = $this->createReflectionProvider(); + + $collectorRegistry = new CollectorRegistry( + $this->getCollectors(), + $reflectionProvider, + ); $nodeScopeResolver = $this->createNodeScopeResolver(); $fileAnalyser = new FileAnalyser( self::createScopeFactory( - $this->createReflectionProvider(), + $reflectionProvider, $this->getTypeSpecifier(), ), $nodeScopeResolver, diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index 586aa791332..fa8b8c4078b 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -802,14 +802,14 @@ private function runAnalyser( private function createAnalyser(): Analyser { + $reflectionProvider = self::createReflectionProvider(); + $ruleRegistry = new DirectRuleRegistry([ new AlwaysFailRule(), ]); - $collectorRegistry = new CollectorRegistry([]); + $collectorRegistry = new CollectorRegistry([], $reflectionProvider); - $reflectionProvider = self::createReflectionProvider(); $fileHelper = $this->getFileHelper(); - $container = self::getContainer(); $typeSpecifier = $container->getService('typeSpecifier'); $fileTypeMapper = $container->getByType(FileTypeMapper::class); diff --git a/tests/PHPStan/Collectors/RegistryTest.php b/tests/PHPStan/Collectors/RegistryTest.php index ac7e0c2e9d3..ee5ad046e31 100644 --- a/tests/PHPStan/Collectors/RegistryTest.php +++ b/tests/PHPStan/Collectors/RegistryTest.php @@ -13,9 +13,10 @@ public function testGetCollectors(): void { $collector = new DummyCollector(); - $registry = new Registry([ - $collector, - ]); + $registry = new Registry( + [$collector], + $this->createReflectionProvider(), + ); $collectors = $registry->getCollectors(Node\Expr\FuncCall::class); $this->assertCount(1, $collectors); @@ -29,10 +30,10 @@ public function testGetCollectorsWithTwoDifferentInstances(): void $fooCollector = new UniversalCollector(Node\Expr\FuncCall::class, static fn (Node\Expr\FuncCall $node, Scope $scope): array => ['Foo error']); $barCollector = new UniversalCollector(Node\Expr\FuncCall::class, static fn (Node\Expr\FuncCall $node, Scope $scope): array => ['Bar error']); - $registry = new Registry([ - $fooCollector, - $barCollector, - ]); + $registry = new Registry( + [$fooCollector, $barCollector], + $this->createReflectionProvider(), + ); $collectors = $registry->getCollectors(Node\Expr\FuncCall::class); $this->assertCount(2, $collectors);