66use PhpParser \Node \Expr \MethodCall ;
77use PhpParser \Node \Identifier ;
88use PHPStan \Analyser \Scope ;
9+ use PHPStan \Reflection \ReflectionProvider ;
910use PHPStan \Symfony \MessageMap ;
1011use PHPStan \Symfony \MessageMapFactory ;
1112use PHPStan \Type \ExpressionTypeResolverExtension ;
1819 * Configurable extension for resolving return types of methods that internally use HandleTrait.
1920 *
2021 * Configured via PHPStan parameters under symfony.messenger.handleTraitWrappers with
21- * "Class ::method" patterns, e.g.:
22+ * "class ::method" patterns, e.g.:
2223 * - App\Bus\QueryBus::dispatch
2324 * - App\Bus\QueryBus::query
2425 * - App\Bus\CommandBus::execute
@@ -34,11 +35,14 @@ final class MessengerHandleTraitWrapperReturnTypeExtension implements Expression
3435 /** @var array<string> */
3536 private array $ wrappers ;
3637
38+ private ReflectionProvider $ reflectionProvider ;
39+
3740 /** @param array{handleTraitWrappers: array<string>}|null $messenger */
38- public function __construct (MessageMapFactory $ messageMapFactory , ?array $ messenger )
41+ public function __construct (MessageMapFactory $ messageMapFactory , ?array $ messenger, ReflectionProvider $ reflectionProvider )
3942 {
4043 $ this ->messageMapFactory = $ messageMapFactory ;
4144 $ this ->wrappers = $ messenger ['handleTraitWrappers ' ] ?? [];
45+ $ this ->reflectionProvider = $ reflectionProvider ;
4246 }
4347
4448 public function getType (Expr $ expr , Scope $ scope ): ?Type
@@ -91,8 +95,23 @@ private function isSupported(Expr $expr, Scope $scope): bool
9195 $ className = $ classNames [0 ];
9296 $ classMethodCombination = $ className . ':: ' . $ methodName ;
9397
94- // Check if this class::method combination is configured
95- return in_array ($ classMethodCombination , $ this ->wrappers , true );
98+ // Check if this exact class::method combination is configured
99+ if (in_array ($ classMethodCombination , $ this ->wrappers , true )) {
100+ return true ;
101+ }
102+
103+ // Check if any interface implemented by this class::method is configured
104+ if ($ this ->reflectionProvider ->hasClass ($ className )) {
105+ $ classReflection = $ this ->reflectionProvider ->getClass ($ className );
106+ foreach ($ classReflection ->getInterfaces () as $ interface ) {
107+ $ interfaceMethodCombination = $ interface ->getName () . ':: ' . $ methodName ;
108+ if (in_array ($ interfaceMethodCombination , $ this ->wrappers , true )) {
109+ return true ;
110+ }
111+ }
112+ }
113+
114+ return false ;
96115 }
97116
98117 private function getMessageMap (): MessageMap
0 commit comments