77use PHPStan \DependencyInjection \AutowiredParameter ;
88use PHPStan \DependencyInjection \AutowiredService ;
99use PHPStan \PhpDoc \Tag \RequireExtendsTag ;
10+ use PHPStan \Reflection \ReflectionProvider ;
1011use PHPStan \Rules \ClassNameCheck ;
1112use PHPStan \Rules \ClassNameNodePair ;
1213use PHPStan \Rules \ClassNameUsageLocation ;
1314use PHPStan \Rules \IdentifierRuleError ;
1415use PHPStan \Rules \RuleErrorBuilder ;
1516use PHPStan \Type \VerbosityLevel ;
16- use function array_column ;
17- use function array_map ;
1817use function array_merge ;
1918use function count ;
20- use function sort ;
2119use function sprintf ;
2220use function strtolower ;
2321
@@ -26,6 +24,7 @@ final class RequireExtendsCheck
2624{
2725
2826 public function __construct (
27+ private ReflectionProvider $ reflectionProvider ,
2928 private ClassNameCheck $ classCheck ,
3029 #[AutowiredParameter]
3130 private bool $ checkClassCaseSensitivity ,
@@ -59,12 +58,8 @@ public function checkExtendsTags(Scope $scope, Node $node, array $extendsTags):
5958 continue ;
6059 }
6160
62- sort ($ classNames );
63- $ referencedClassReflections = array_map (static fn ($ reflection ) => [$ reflection , $ reflection ->getName ()], $ type ->getObjectClassReflections ());
64- $ referencedClassReflectionsMap = array_column ($ referencedClassReflections , 0 , 1 );
6561 foreach ($ classNames as $ class ) {
66- $ referencedClassReflection = $ referencedClassReflectionsMap [$ class ] ?? null ;
67- if ($ referencedClassReflection === null ) {
62+ if (!$ this ->reflectionProvider ->hasClass ($ class )) {
6863 $ errorBuilder = RuleErrorBuilder ::message (sprintf ('PHPDoc tag @phpstan-require-extends contains unknown class %s. ' , $ class ))
6964 ->identifier ('class.notFound ' );
7065
@@ -76,16 +71,17 @@ public function checkExtendsTags(Scope $scope, Node $node, array $extendsTags):
7671 continue ;
7772 }
7873
79- if ($ referencedClassReflection ->isInterface ()) {
74+ $ reflection = $ this ->reflectionProvider ->getClass ($ class );
75+ if ($ reflection ->isInterface ()) {
8076 $ errors [] = RuleErrorBuilder ::message (sprintf ('PHPDoc tag @phpstan-require-extends cannot contain an interface %s, expected a class. ' , $ class ))
8177 ->tip ('If you meant an interface, use @phpstan-require-implements instead. ' )
8278 ->identifier ('requireExtends.interface ' )
8379 ->build ();
84- } elseif (!$ referencedClassReflection ->isClass ()) {
80+ } elseif (!$ reflection ->isClass ()) {
8581 $ errors [] = RuleErrorBuilder ::message (sprintf ('PHPDoc tag @phpstan-require-extends cannot contain non-class type %s. ' , $ class ))
86- ->identifier (sprintf ('requireExtends.%s ' , strtolower ($ referencedClassReflection ->getClassTypeDescription ())))
82+ ->identifier (sprintf ('requireExtends.%s ' , strtolower ($ reflection ->getClassTypeDescription ())))
8783 ->build ();
88- } elseif ($ referencedClassReflection ->isFinal ()) {
84+ } elseif ($ reflection ->isFinal ()) {
8985 $ errors [] = RuleErrorBuilder ::message (sprintf ('PHPDoc tag @phpstan-require-extends cannot contain final class %s. ' , $ class ))
9086 ->identifier ('requireExtends.finalClass ' )
9187 ->build ();
0 commit comments