Skip to content

Commit fc5f35a

Browse files
Bartłomiej Nowakbnowak
Bartłomiej Nowak
authored andcommitted
phpstan fix
1 parent eed37f2 commit fc5f35a

8 files changed

+39
-57
lines changed

src/Symfony/Message.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Symfony;
44

5+
use PHPStan\Type\Type;
56
use function count;
67

78
final class Message
@@ -10,9 +11,10 @@ final class Message
1011
/** @var string */
1112
private $class;
1213

13-
/** @var array */
14+
/** @var Type[] */
1415
private $returnTypes;
1516

17+
/** @param Type[] $returnTypes */
1618
public function __construct(string $class, array $returnTypes)
1719
{
1820
$this->class = $class;
@@ -24,6 +26,7 @@ public function getClass(): string
2426
return $this->class;
2527
}
2628

29+
/** @return Type[] */
2730
public function getReturnTypes(): array
2831
{
2932
return $this->returnTypes;

src/Symfony/MessageMap.php

-7
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
namespace PHPStan\Symfony;
44

5-
use function array_key_exists;
6-
75
final class MessageMap
86
{
97

@@ -25,9 +23,4 @@ public function getMessageForClass(string $class): ?Message
2523
return $this->messages[$class] ?? null;
2624
}
2725

28-
public function hasMessageForClass(string $class): bool
29-
{
30-
return array_key_exists($class, $this->messages);
31-
}
32-
3326
}

src/Symfony/MessageMapFactory.php

+18-35
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
use PHPStan\Reflection\ClassReflection;
66
use PHPStan\Reflection\ParametersAcceptorSelector;
77
use PHPStan\Reflection\ReflectionProvider;
8-
use PHPStan\Type\ObjectType;
9-
use PHPStan\Type\UnionType;
108
use RuntimeException;
119
use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
1210
use function count;
@@ -18,6 +16,8 @@
1816
final class MessageMapFactory
1917
{
2018

19+
private const DEFAULT_HANDLER_METHOD = '__invoke';
20+
2121
/** @var ReflectionProvider */
2222
private $reflectionProvider;
2323

@@ -53,19 +53,13 @@ public function create(): MessageMap
5353
$reflectionClass = $this->reflectionProvider->getClass($serviceClass);
5454

5555
if (isset($tagAttributes['handles'])) {
56-
$handles = isset($tag['method']) ? [$tag['handles'] => $tag['method']] : [$tag['handles']];
56+
// todo cover by test case
57+
$handles = [$tagAttributes['handles'] => ['method' => $tagAttributes['method'] ?? self::DEFAULT_HANDLER_METHOD]];
5758
} else {
5859
$handles = $this->guessHandledMessages($reflectionClass);
5960
}
6061

6162
foreach ($handles as $messageClassName => $options) {
62-
if (is_int($messageClassName) && is_string($options)) {
63-
$messageClassName = $options;
64-
$options = [];
65-
}
66-
67-
$options['method'] = $options['method'] ?? '__invoke';
68-
6963
$methodReflection = $reflectionClass->getNativeMethod($options['method']);
7064
$variant = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
7165

@@ -82,15 +76,24 @@ public function create(): MessageMap
8276
return new MessageMap($messages);
8377
}
8478

79+
/** @return array<string, array<string, string>> */
8580
private function guessHandledMessages(ClassReflection $reflectionClass): iterable
8681
{
8782
if ($reflectionClass->implementsInterface(MessageSubscriberInterface::class)) {
8883
// todo handle different return formats
89-
return $reflectionClass->getName()::getHandledMessages();
84+
foreach ($reflectionClass->getName()::getHandledMessages() as $index => $value) {
85+
if (is_int($index) && is_string($value)) {
86+
yield $value => ['method' => self::DEFAULT_HANDLER_METHOD];
87+
} else {
88+
yield $index => $value;
89+
}
90+
}
91+
92+
return;
9093
}
9194

9295
// todo handle if doesn't exists
93-
$methodReflection = $reflectionClass->getNativeMethod('__invoke');
96+
$methodReflection = $reflectionClass->getNativeMethod(self::DEFAULT_HANDLER_METHOD);
9497

9598
$variant = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
9699
$parameters = $variant->getParameters();
@@ -102,30 +105,10 @@ private function guessHandledMessages(ClassReflection $reflectionClass): iterabl
102105

103106
$type = $parameters[0]->getType();
104107

105-
if ($type instanceof UnionType) {
106-
$types = [];
107-
foreach ($type->getTypes() as $type) {
108-
if (!$type instanceof ObjectType) {
109-
// todo handle error
110-
throw new RuntimeException('invalid handler');
111-
}
112-
113-
$types[] = $type->getClassName();
114-
}
115-
116-
if ($types) {
117-
return $types;
118-
}
119-
120-
// todo handle error
121-
throw new RuntimeException('invalid handler');
108+
// todo many class names?
109+
foreach ($type->getObjectClassNames() as $className) {
110+
yield $className => ['method' => self::DEFAULT_HANDLER_METHOD];
122111
}
123-
124-
if (!$type instanceof ObjectType) {
125-
throw new RuntimeException('invalid handler');
126-
}
127-
128-
return [$type->getClassName()];
129112
}
130113

131114
}

src/Symfony/Service.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ final class Service implements ServiceDefinition
2020
/** @var string|null */
2121
private $alias;
2222

23-
/** @var array */
23+
/** @var ServiceTag[] */
2424
private $tags;
2525

26+
/** @param ServiceTag[] $tags */
2627
public function __construct(
2728
string $id,
2829
?string $class,

src/Symfony/ServiceDefinition.php

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public function isSynthetic(): bool;
1515

1616
public function getAlias(): ?string;
1717

18+
/** @return ServiceTag[] */
1819
public function getTags(): array;
1920

2021
}

src/Symfony/ServiceTag.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ final class ServiceTag implements ServiceTagDefinition
88
/** @var string */
99
private $name;
1010

11-
/** @var array */
11+
/** @var array<string, string> */
1212
private $attributes;
1313

14+
/** @param array<string, string> $attributes */
1415
public function __construct(string $name, array $attributes = [])
1516
{
1617
$this->name = $name;

src/Symfony/ServiceTagDefinition.php

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ interface ServiceTagDefinition
77

88
public function getName(): string;
99

10+
/** @return array<string, string> */
1011
public function getAttributes(): array;
1112

1213
}

src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

+11-12
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
use PHPStan\Symfony\MessageMap;
1010
use PHPStan\Symfony\MessageMapFactory;
1111
use PHPStan\Type\DynamicMethodReturnTypeExtension;
12-
use PHPStan\Type\ObjectType;
1312
use PHPStan\Type\Type;
13+
use function count;
14+
use function is_null;
1415

1516
final class MessengerHandleTraitDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
1617
{
1718

1819
/** @var MessageMapFactory */
1920
private $messageMapFactory;
2021

21-
/** @var MessageMap */
22+
/** @var MessageMap|null */
2223
private $messageMap;
2324

2425
public function __construct(MessageMapFactory $symfonyMessageMapFactory)
@@ -34,8 +35,7 @@ public function getClass(): string
3435
// todo or make it configurable with passing concrete classes names to extension config
3536
// todo or use reflection somehow to get all classes that use HandleTrait and configure it dynamically
3637

37-
// todo temporarily hardcoded test class here
38-
return HandleTraitClass::class;
38+
return HandleTraitClass::class; // @phpstan-ignore-line todo temporarily hardcoded test class here
3939
}
4040

4141
public function isMethodSupported(MethodReflection $methodReflection): bool
@@ -56,16 +56,15 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
5656
// - [] read SF doc to determine any other cases to covers
5757

5858
$arg = $methodCall->getArgs()[0]->value;
59-
$argType = $scope->getType($arg);
59+
$argClassNames = $scope->getType($arg)->getObjectClassNames();
6060

61-
if ($argType instanceof ObjectType) {
61+
// todo filter out not handled cases on map creation?
62+
if (count($argClassNames) === 1) {
6263
$messageMap = $this->getMessageMap();
63-
if ($messageMap->hasMessageForClass($argType->getClassName())) {
64-
$message = $messageMap->getMessageForClass($argType->getClassName());
64+
$message = $messageMap->getMessageForClass($argClassNames[0]);
6565

66-
if ($message->countReturnTypes() === 1) {
67-
return $message->getReturnTypes()[0];
68-
}
66+
if (!is_null($message) && $message->countReturnTypes() === 1) {
67+
return $message->getReturnTypes()[0];
6968
}
7069
}
7170

@@ -74,7 +73,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
7473

7574
private function getMessageMap(): MessageMap
7675
{
77-
if (!$this->messageMap) {
76+
if (is_null($this->messageMap)) {
7877
$this->messageMap = $this->messageMapFactory->create();
7978
}
8079

0 commit comments

Comments
 (0)