-
Notifications
You must be signed in to change notification settings - Fork 94
Support for Messenger HandleTrait return types #404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
4c95d32
5985362
bd75cb6
9768de5
0c8cb34
224c478
9438e5e
8a44be8
46e0cc8
5cba4ba
f7bf1e0
d62ec03
89c7534
df90a3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
/tests/tmp | ||
/build-cs | ||
/vendor | ||
/.idea | ||
/composer.lock | ||
.phpunit.result.cache |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,6 @@ | |
namespace PHPStan\Symfony; | ||
|
||
use PHPStan\Reflection\ClassReflection; | ||
use PHPStan\Reflection\MissingMethodFromReflectionException; | ||
use PHPStan\Reflection\ReflectionProvider; | ||
use PHPStan\ShouldNotHappenException; | ||
use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; | ||
|
@@ -47,9 +46,14 @@ public function create(): MessageMap | |
continue; | ||
} | ||
|
||
if (!$this->reflectionProvider->hasClass($serviceClass)) { | ||
continue; | ||
} | ||
|
||
$reflectionClass = $this->reflectionProvider->getClass($serviceClass); | ||
|
||
/** @var array{handles?: class-string, method?: string} $tagAttributes */ | ||
$tagAttributes = $tag->getAttributes(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shape is dynamic and rely on what tag we're using from SF config. In this case I'm ensuring above that we're handling only As far I know stubs are static only, so unfortunately we cannot use them here. Do you have other idea or it could stay as it is? |
||
$reflectionClass = $this->reflectionProvider->getClass($serviceClass); | ||
|
||
if (isset($tagAttributes['handles'])) { | ||
$handles = [$tagAttributes['handles'] => ['method' => $tagAttributes['method'] ?? self::DEFAULT_HANDLER_METHOD]]; | ||
|
@@ -58,7 +62,13 @@ public function create(): MessageMap | |
} | ||
|
||
foreach ($handles as $messageClassName => $options) { | ||
$methodReflection = $reflectionClass->getNativeMethod($options['method'] ?? self::DEFAULT_HANDLER_METHOD); | ||
$methodName = $options['method'] ?? self::DEFAULT_HANDLER_METHOD; | ||
|
||
if (!$reflectionClass->hasNativeMethod($methodName)) { | ||
continue; | ||
} | ||
|
||
$methodReflection = $reflectionClass->getNativeMethod($methodName); | ||
|
||
foreach ($methodReflection->getVariants() as $variant) { | ||
$returnTypesMap[$messageClassName][] = $variant->getReturnType(); | ||
|
@@ -79,27 +89,33 @@ public function create(): MessageMap | |
return new MessageMap($messageMap); | ||
} | ||
|
||
/** @return array<class-string, array<string, string>> */ | ||
/** @return iterable<string, array<string, string>> */ | ||
private function guessHandledMessages(ClassReflection $reflectionClass): iterable | ||
{ | ||
if ($reflectionClass->implementsInterface(MessageSubscriberInterface::class)) { | ||
foreach ($reflectionClass->getName()::getHandledMessages() as $index => $value) { | ||
if (self::containOptions($index, $value)) { | ||
yield $index => $value; | ||
} else { | ||
yield $value => ['method' => self::DEFAULT_HANDLER_METHOD]; | ||
$className = $reflectionClass->getName(); | ||
|
||
foreach ($className::getHandledMessages() as $index => $value) { | ||
try { | ||
if (self::containOptions($index, $value)) { | ||
yield $index => $value; | ||
} else { | ||
yield $value => ['method' => self::DEFAULT_HANDLER_METHOD]; | ||
} | ||
} catch (ShouldNotHappenException $e) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Never catch ShouldNotHappenException. |
||
continue; | ||
} | ||
} | ||
|
||
return; | ||
} | ||
|
||
try { | ||
$methodReflection = $reflectionClass->getNativeMethod(self::DEFAULT_HANDLER_METHOD); | ||
} catch (MissingMethodFromReflectionException $e) { | ||
if (!$reflectionClass->hasNativeMethod(self::DEFAULT_HANDLER_METHOD)) { | ||
return; | ||
} | ||
|
||
$methodReflection = $reflectionClass->getNativeMethod(self::DEFAULT_HANDLER_METHOD); | ||
|
||
$variants = $methodReflection->getVariants(); | ||
if (count($variants) !== 1) { | ||
return; | ||
|
@@ -111,7 +127,6 @@ private function guessHandledMessages(ClassReflection $reflectionClass): iterabl | |
return; | ||
} | ||
|
||
/** @var class-string[] $classNames */ | ||
$classNames = $parameters[0]->getType()->getObjectClassNames(); | ||
|
||
if (count($classNames) !== 1) { | ||
|
@@ -124,10 +139,10 @@ private function guessHandledMessages(ClassReflection $reflectionClass): iterabl | |
/** | ||
* @param mixed $index | ||
* @param mixed $value | ||
* @phpstan-assert-if-true class-string $index | ||
* @phpstan-assert-if-true array<string, mixed> $value | ||
* @phpstan-assert-if-false int $index | ||
* @phpstan-assert-if-false class-string $value | ||
* @phpstan-assert-if-true =class-string $index | ||
* @phpstan-assert-if-true =array<string, mixed> $value | ||
* @phpstan-assert-if-false =int $index | ||
* @phpstan-assert-if-false =class-string $value | ||
*/ | ||
private static function containOptions($index, $value): bool | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,6 @@ | |
use PHPStan\Symfony\MessageMapFactory; | ||
use PHPStan\Type\ExpressionTypeResolverExtension; | ||
use PHPStan\Type\Type; | ||
use ReflectionException; | ||
use function count; | ||
use function is_null; | ||
|
||
|
@@ -35,7 +34,6 @@ public function getType(Expr $expr, Scope $scope): ?Type | |
{ | ||
if ($this->isSupported($expr, $scope)) { | ||
$arg = $expr->getArgs()[0]->value; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
/** @var class-string[] $argClassNames */ | ||
$argClassNames = $scope->getType($arg)->getObjectClassNames(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't add this |
||
|
||
if (count($argClassNames) === 1) { | ||
|
@@ -61,7 +59,7 @@ private function getMessageMap(): MessageMap | |
} | ||
|
||
/** | ||
* @phpstan-assert-if-true MethodCall $expr | ||
* @phpstan-assert-if-true =MethodCall $expr | ||
*/ | ||
private function isSupported(Expr $expr, Scope $scope): bool | ||
{ | ||
|
@@ -73,14 +71,16 @@ private function isSupported(Expr $expr, Scope $scope): bool | |
return false; | ||
} | ||
|
||
try { | ||
$methodReflection = $scope->getClassReflection()->getNativeReflection()->getMethod(self::TRAIT_METHOD_NAME); | ||
$declaringClassReflection = $methodReflection->getBetterReflection()->getDeclaringClass(); | ||
$reflectionClass = $scope->getClassReflection()->getNativeReflection(); | ||
|
||
return $declaringClassReflection->getName() === self::TRAIT_NAME; | ||
} catch (ReflectionException $e) { | ||
if (!$reflectionClass->hasMethod(self::TRAIT_METHOD_NAME)) { | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of catching exception, check if the method exists first. |
||
} | ||
|
||
$methodReflection = $reflectionClass->getMethod(self::TRAIT_METHOD_NAME); | ||
$declaringClassReflection = $methodReflection->getBetterReflection()->getDeclaringClass(); | ||
|
||
return $declaringClassReflection->getName() === self::TRAIT_NAME; | ||
} | ||
|
||
} |
Uh oh!
There was an error while loading. Please reload this page.