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 ;
2019use function sort ;
@@ -26,6 +25,7 @@ final class RequireExtendsCheck
2625{
2726
2827 public function __construct (
28+ private ReflectionProvider $ reflectionProvider ,
2929 private ClassNameCheck $ classCheck ,
3030 #[AutowiredParameter]
3131 private bool $ checkClassCaseSensitivity ,
@@ -59,12 +59,8 @@ public function checkExtendsTags(Scope $scope, Node $node, array $extendsTags):
5959 continue ;
6060 }
6161
62- sort ($ classNames );
63- $ referencedClassReflections = array_map (static fn ($ reflection ) => [$ reflection , $ reflection ->getName ()], $ type ->getObjectClassReflections ());
64- $ referencedClassReflectionsMap = array_column ($ referencedClassReflections , 0 , 1 );
6562 foreach ($ classNames as $ class ) {
66- $ referencedClassReflection = $ referencedClassReflectionsMap [$ class ] ?? null ;
67- if ($ referencedClassReflection === null ) {
63+ if (!$ this ->reflectionProvider ->hasClass ($ class )) {
6864 $ errorBuilder = RuleErrorBuilder::message (sprintf ('PHPDoc tag @phpstan-require-extends contains unknown class %s. ' , $ class ))
6965 ->identifier ('class.notFound ' );
7066
@@ -76,16 +72,17 @@ public function checkExtendsTags(Scope $scope, Node $node, array $extendsTags):
7672 continue ;
7773 }
7874
79- if ($ referencedClassReflection ->isInterface ()) {
75+ $ reflection = $ this ->reflectionProvider ->getClass ($ class );
76+ if ($ reflection ->isInterface ()) {
8077 $ errors [] = RuleErrorBuilder::message (sprintf ('PHPDoc tag @phpstan-require-extends cannot contain an interface %s, expected a class. ' , $ class ))
8178 ->tip ('If you meant an interface, use @phpstan-require-implements instead. ' )
8279 ->identifier ('requireExtends.interface ' )
8380 ->build ();
84- } elseif (!$ referencedClassReflection ->isClass ()) {
81+ } elseif (!$ reflection ->isClass ()) {
8582 $ errors [] = RuleErrorBuilder::message (sprintf ('PHPDoc tag @phpstan-require-extends cannot contain non-class type %s. ' , $ class ))
86- ->identifier (sprintf ('requireExtends.%s ' , strtolower ($ referencedClassReflection ->getClassTypeDescription ())))
83+ ->identifier (sprintf ('requireExtends.%s ' , strtolower ($ reflection ->getClassTypeDescription ())))
8784 ->build ();
88- } elseif ($ referencedClassReflection ->isFinal ()) {
85+ } elseif ($ reflection ->isFinal ()) {
8986 $ errors [] = RuleErrorBuilder::message (sprintf ('PHPDoc tag @phpstan-require-extends cannot contain final class %s. ' , $ class ))
9087 ->identifier ('requireExtends.finalClass ' )
9188 ->build ();
0 commit comments