diff --git a/src/PhpDoc/PhpDocInheritanceResolver.php b/src/PhpDoc/PhpDocInheritanceResolver.php index 628b3e62df..01b7043e58 100644 --- a/src/PhpDoc/PhpDocInheritanceResolver.php +++ b/src/PhpDoc/PhpDocInheritanceResolver.php @@ -8,6 +8,7 @@ use PHPStan\Type\FileTypeMapper; use function array_key_exists; use function count; +use function explode; use function is_bool; use function strtolower; @@ -81,10 +82,12 @@ public function resolvePhpDocForMethod( array $currentPositionalParameterNames, ): ?ResolvedPhpDocBlock { + $methodNameForLookup = $this->resolveOriginalMethodName($declaringClass, $methodName); + $parent = $declaringClass->getParentClass(); if ($parent !== null) { - if ($parent->hasNativeMethod($methodName)) { - $parentMethod = $parent->getNativeMethod($methodName); + if ($parent->hasNativeMethod($methodNameForLookup)) { + $parentMethod = $parent->getNativeMethod($methodNameForLookup); if (!$parentMethod->isPrivate() && $parentMethod->getResolvedPhpDoc() !== null) { if ($parentMethod->getName() !== '__construct' || !$parentMethod->getDeclaringClass()->isBuiltin()) { return $this->resolveMethodPhpDocFromParentClass($parentMethod, $parentMethod->getResolvedPhpDoc(), $declaringClass, $parent, $currentResolvedPhpDoc, $currentPositionalParameterNames); @@ -94,11 +97,11 @@ public function resolvePhpDocForMethod( } foreach ($declaringClass->getImmediateInterfaces() as $interface) { - if (!$interface->hasNativeMethod($methodName)) { + if (!$interface->hasNativeMethod($methodNameForLookup)) { continue; } - $interfaceMethod = $interface->getNativeMethod($methodName); + $interfaceMethod = $interface->getNativeMethod($methodNameForLookup); if ($interfaceMethod->isPrivate()) { continue; } @@ -110,11 +113,11 @@ public function resolvePhpDocForMethod( } foreach ($declaringClass->getTraits() as $trait) { - if (!$trait->hasNativeMethod($methodName)) { + if (!$trait->hasNativeMethod($methodNameForLookup)) { continue; } - $traitMethod = $trait->getNativeMethod($methodName); + $traitMethod = $trait->getNativeMethod($methodNameForLookup); if ($traitMethod->getDocComment() === null) { continue; } @@ -135,7 +138,7 @@ public function resolvePhpDocForMethod( $declaringClass->getFileName(), $declaringClass->getName(), $trait->getName(), - $methodName, + $methodNameForLookup, $traitMethod->getDocComment(), ); @@ -210,6 +213,19 @@ private static function remapParameterNames( return $parameterNameMapping; } + private function resolveOriginalMethodName(ClassReflection $declaringClass, string $methodName): string + { + $traitAliases = $declaringClass->getNativeReflection()->getTraitAliases(); + if (array_key_exists($methodName, $traitAliases)) { + $parts = explode('::', $traitAliases[$methodName]); + if (count($parts) === 2) { + return $parts[1]; + } + } + + return $methodName; + } + private function resolveConstantPhpDocFromParentClass( ClassReflection $declaringClass, ClassReflection $parent, diff --git a/tests/PHPStan/Analyser/nsrt/bug-9733.php b/tests/PHPStan/Analyser/nsrt/bug-9733.php new file mode 100644 index 0000000000..d0db2c78bb --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-9733.php @@ -0,0 +1,28 @@ +', $array); + } +} + +class Concrete extends Base +{ + use MyTrait { + test as test2; + } +}