Skip to content
72 changes: 44 additions & 28 deletions src/Dependency/DependencyResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,17 @@
use PHPStan\Type\ClosureType;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\Type;
use function array_key_exists;
use function array_merge;
use function count;

#[AutowiredService]
final class DependencyResolver
{

/** @var array<string, list<ClassReflection|FunctionReflection>> */
private array $classDependencies = [];

public function __construct(
private FileHelper $fileHelper,
private ReflectionProvider $reflectionProvider,
Expand Down Expand Up @@ -520,30 +524,43 @@ private function considerArrayForCallableTest(Scope $scope, Array_ $arrayNode):
* @param array<int, ClassReflection|FunctionReflection> $dependenciesReflections
*/
private function addClassToDependencies(string $className, array &$dependenciesReflections): void
{
if (!array_key_exists($className, $this->classDependencies)) {
$this->classDependencies[$className] = $this->buildClassDependencies($className);
}

$dependenciesReflections = array_merge($dependenciesReflections, $this->classDependencies[$className]);
}

/**
* @return list<ClassReflection|FunctionReflection>
*/
private function buildClassDependencies(string $className): array
{
try {
$classReflection = $this->reflectionProvider->getClass($className);
} catch (ClassNotFoundException) {
return;
return [];
}

$dependencies = [];
do {
$dependenciesReflections[] = $classReflection;
$dependencies[] = $classReflection;

foreach ($classReflection->getInterfaces() as $interface) {
$dependenciesReflections[] = $interface;
$dependencies[] = $interface;
}

foreach ($classReflection->getTraits(true) as $trait) {
$dependenciesReflections[] = $trait;
$dependencies[] = $trait;
}

foreach ($classReflection->getResolvedMixinTypes() as $mixinType) {
foreach ($mixinType->getReferencedClasses() as $referencedClass) {
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

Expand All @@ -552,7 +569,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

Expand All @@ -561,7 +578,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

Expand All @@ -570,7 +587,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}

$default = $templateTag->getDefault();
Expand All @@ -581,7 +598,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

Expand All @@ -591,7 +608,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

Expand All @@ -603,7 +620,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

Expand All @@ -612,14 +629,14 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
foreach ($methodTag->getParameters() as $parameter) {
foreach ($parameter->getType()->getReferencedClasses() as $referencedClass) {
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
if ($parameter->getDefaultValue() === null) {
continue;
Expand All @@ -628,7 +645,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}
}
Expand All @@ -638,7 +655,7 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

Expand All @@ -647,19 +664,21 @@ private function addClassToDependencies(string $className, array &$dependenciesR
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
$dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass);
$dependencies[] = $this->reflectionProvider->getClass($referencedClass);
}
}

$phpDoc = $classReflection->getResolvedPhpDoc();
if ($phpDoc !== null) {
foreach ($phpDoc->getTypeAliasImportTags() as $importTag) {
$dependenciesReflections[] = $this->reflectionProvider->getClass($importTag->getImportedFrom());
$dependencies[] = $this->reflectionProvider->getClass($importTag->getImportedFrom());
}
}

$classReflection = $classReflection->getParentClass();
} while ($classReflection !== null);

return $dependencies;
}

private function getFunctionReflection(Node\Name $nameNode, ?Scope $scope): FunctionReflection
Expand All @@ -676,12 +695,10 @@ private function extractFromParametersAcceptor(
): void
{
foreach ($parametersAcceptor->getParameters() as $parameter) {
$referencedClasses = array_merge(
$parameter->getNativeType()->getReferencedClasses(),
$parameter->getPhpDocType()->getReferencedClasses(),
);

foreach ($referencedClasses as $referencedClass) {
foreach ($parameter->getNativeType()->getReferencedClasses() as $referencedClass) {
$this->addClassToDependencies($referencedClass, $dependenciesReflections);
}
foreach ($parameter->getPhpDocType()->getReferencedClasses() as $referencedClass) {
$this->addClassToDependencies($referencedClass, $dependenciesReflections);
}

Expand All @@ -698,11 +715,10 @@ private function extractFromParametersAcceptor(
}
}

$returnTypeReferencedClasses = array_merge(
$parametersAcceptor->getNativeReturnType()->getReferencedClasses(),
$parametersAcceptor->getPhpDocReturnType()->getReferencedClasses(),
);
foreach ($returnTypeReferencedClasses as $referencedClass) {
foreach ($parametersAcceptor->getNativeReturnType()->getReferencedClasses() as $referencedClass) {
$this->addClassToDependencies($referencedClass, $dependenciesReflections);
}
foreach ($parametersAcceptor->getPhpDocReturnType()->getReferencedClasses() as $referencedClass) {
$this->addClassToDependencies($referencedClass, $dependenciesReflections);
}
}
Expand Down
Loading