3030use PHPStan \Type \ClosureType ;
3131use PHPStan \Type \FileTypeMapper ;
3232use PHPStan \Type \Type ;
33+ use function array_key_exists ;
3334use function array_merge ;
3435use function count ;
3536
3637#[AutowiredService]
3738final class DependencyResolver
3839{
3940
41+ /** @var array<string, list<ClassReflection|FunctionReflection>> */
42+ private array $ classDependencies = [];
43+
4044 public function __construct (
4145 private FileHelper $ fileHelper ,
4246 private ReflectionProvider $ reflectionProvider ,
@@ -520,30 +524,43 @@ private function considerArrayForCallableTest(Scope $scope, Array_ $arrayNode):
520524 * @param array<int, ClassReflection|FunctionReflection> $dependenciesReflections
521525 */
522526 private function addClassToDependencies (string $ className , array &$ dependenciesReflections ): void
527+ {
528+ if (!array_key_exists ($ className , $ this ->classDependencies )) {
529+ $ this ->classDependencies [$ className ] = $ this ->buildClassDependencies ($ className );
530+ }
531+
532+ $ dependenciesReflections = array_merge ($ dependenciesReflections , $ this ->classDependencies [$ className ]);
533+ }
534+
535+ /**
536+ * @return list<ClassReflection|FunctionReflection>
537+ */
538+ private function buildClassDependencies (string $ className ): array
523539 {
524540 try {
525541 $ classReflection = $ this ->reflectionProvider ->getClass ($ className );
526542 } catch (ClassNotFoundException ) {
527- return ;
543+ return [] ;
528544 }
529545
546+ $ dependencies = [];
530547 do {
531- $ dependenciesReflections [] = $ classReflection ;
548+ $ dependencies [] = $ classReflection ;
532549
533550 foreach ($ classReflection ->getInterfaces () as $ interface ) {
534- $ dependenciesReflections [] = $ interface ;
551+ $ dependencies [] = $ interface ;
535552 }
536553
537554 foreach ($ classReflection ->getTraits (true ) as $ trait ) {
538- $ dependenciesReflections [] = $ trait ;
555+ $ dependencies [] = $ trait ;
539556 }
540557
541558 foreach ($ classReflection ->getResolvedMixinTypes () as $ mixinType ) {
542559 foreach ($ mixinType ->getReferencedClasses () as $ referencedClass ) {
543560 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
544561 continue ;
545562 }
546- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
563+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
547564 }
548565 }
549566
@@ -552,7 +569,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
552569 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
553570 continue ;
554571 }
555- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
572+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
556573 }
557574 }
558575
@@ -561,7 +578,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
561578 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
562579 continue ;
563580 }
564- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
581+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
565582 }
566583 }
567584
@@ -570,7 +587,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
570587 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
571588 continue ;
572589 }
573- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
590+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
574591 }
575592
576593 $ default = $ templateTag ->getDefault ();
@@ -581,7 +598,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
581598 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
582599 continue ;
583600 }
584- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
601+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
585602 }
586603 }
587604
@@ -591,7 +608,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
591608 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
592609 continue ;
593610 }
594- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
611+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
595612 }
596613 }
597614
@@ -603,7 +620,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
603620 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
604621 continue ;
605622 }
606- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
623+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
607624 }
608625 }
609626
@@ -612,14 +629,14 @@ private function addClassToDependencies(string $className, array &$dependenciesR
612629 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
613630 continue ;
614631 }
615- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
632+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
616633 }
617634 foreach ($ methodTag ->getParameters () as $ parameter ) {
618635 foreach ($ parameter ->getType ()->getReferencedClasses () as $ referencedClass ) {
619636 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
620637 continue ;
621638 }
622- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
639+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
623640 }
624641 if ($ parameter ->getDefaultValue () === null ) {
625642 continue ;
@@ -628,7 +645,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
628645 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
629646 continue ;
630647 }
631- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
648+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
632649 }
633650 }
634651 }
@@ -638,7 +655,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
638655 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
639656 continue ;
640657 }
641- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
658+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
642659 }
643660 }
644661
@@ -647,19 +664,21 @@ private function addClassToDependencies(string $className, array &$dependenciesR
647664 if (!$ this ->reflectionProvider ->hasClass ($ referencedClass )) {
648665 continue ;
649666 }
650- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
667+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ referencedClass );
651668 }
652669 }
653670
654671 $ phpDoc = $ classReflection ->getResolvedPhpDoc ();
655672 if ($ phpDoc !== null ) {
656673 foreach ($ phpDoc ->getTypeAliasImportTags () as $ importTag ) {
657- $ dependenciesReflections [] = $ this ->reflectionProvider ->getClass ($ importTag ->getImportedFrom ());
674+ $ dependencies [] = $ this ->reflectionProvider ->getClass ($ importTag ->getImportedFrom ());
658675 }
659676 }
660677
661678 $ classReflection = $ classReflection ->getParentClass ();
662679 } while ($ classReflection !== null );
680+
681+ return $ dependencies ;
663682 }
664683
665684 private function getFunctionReflection (Node \Name $ nameNode , ?Scope $ scope ): FunctionReflection
@@ -676,12 +695,10 @@ private function extractFromParametersAcceptor(
676695 ): void
677696 {
678697 foreach ($ parametersAcceptor ->getParameters () as $ parameter ) {
679- $ referencedClasses = array_merge (
680- $ parameter ->getNativeType ()->getReferencedClasses (),
681- $ parameter ->getPhpDocType ()->getReferencedClasses (),
682- );
683-
684- foreach ($ referencedClasses as $ referencedClass ) {
698+ foreach ($ parameter ->getNativeType ()->getReferencedClasses () as $ referencedClass ) {
699+ $ this ->addClassToDependencies ($ referencedClass , $ dependenciesReflections );
700+ }
701+ foreach ($ parameter ->getPhpDocType ()->getReferencedClasses () as $ referencedClass ) {
685702 $ this ->addClassToDependencies ($ referencedClass , $ dependenciesReflections );
686703 }
687704
@@ -698,11 +715,10 @@ private function extractFromParametersAcceptor(
698715 }
699716 }
700717
701- $ returnTypeReferencedClasses = array_merge (
702- $ parametersAcceptor ->getNativeReturnType ()->getReferencedClasses (),
703- $ parametersAcceptor ->getPhpDocReturnType ()->getReferencedClasses (),
704- );
705- foreach ($ returnTypeReferencedClasses as $ referencedClass ) {
718+ foreach ($ parametersAcceptor ->getNativeReturnType ()->getReferencedClasses () as $ referencedClass ) {
719+ $ this ->addClassToDependencies ($ referencedClass , $ dependenciesReflections );
720+ }
721+ foreach ($ parametersAcceptor ->getPhpDocReturnType ()->getReferencedClasses () as $ referencedClass ) {
706722 $ this ->addClassToDependencies ($ referencedClass , $ dependenciesReflections );
707723 }
708724 }
0 commit comments