Skip to content

Commit

Permalink
phpstan fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Bartłomiej Nowak committed Aug 14, 2024
1 parent a3ed090 commit e3790e0
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 57 deletions.
5 changes: 4 additions & 1 deletion src/Symfony/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Symfony;

use PHPStan\Type\Type;
use function count;

final class Message
Expand All @@ -10,9 +11,10 @@ final class Message
/** @var string */
private $class;

/** @var array */
/** @var Type[] */
private $returnTypes;

/** @param Type[] $returnTypes */
public function __construct(string $class, array $returnTypes)
{
$this->class = $class;
Expand All @@ -24,6 +26,7 @@ public function getClass(): string
return $this->class;
}

/** @return Type[] */
public function getReturnTypes(): array
{
return $this->returnTypes;
Expand Down
7 changes: 0 additions & 7 deletions src/Symfony/MessageMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace PHPStan\Symfony;

use function array_key_exists;

final class MessageMap
{

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

public function hasMessageForClass(string $class): bool
{
return array_key_exists($class, $this->messages);
}

}
53 changes: 18 additions & 35 deletions src/Symfony/MessageMapFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ObjectType;
use PHPStan\Type\UnionType;
use RuntimeException;
use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
use function count;
Expand All @@ -18,6 +16,8 @@
final class MessageMapFactory
{

private const DEFAULT_HANDLER_METHOD = '__invoke';

/** @var ReflectionProvider */
private $reflectionProvider;

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

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

foreach ($handles as $messageClassName => $options) {
if (is_int($messageClassName) && is_string($options)) {
$messageClassName = $options;
$options = [];
}

$options['method'] = $options['method'] ?? '__invoke';

$methodReflection = $reflectionClass->getNativeMethod($options['method']);
$variant = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());

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

/** @return array<string, array<string, string>> */
private function guessHandledMessages(ClassReflection $reflectionClass): iterable
{
if ($reflectionClass->implementsInterface(MessageSubscriberInterface::class)) {
// todo handle different return formats
return $reflectionClass->getName()::getHandledMessages();
foreach ($reflectionClass->getName()::getHandledMessages() as $index => $value) {
if (is_int($index) && is_string($value)) {
yield $value => ['method' => self::DEFAULT_HANDLER_METHOD];
} else {
yield $index => $value;
}
}

return;
}

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

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

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

if ($type instanceof UnionType) {
$types = [];
foreach ($type->getTypes() as $type) {
if (!$type instanceof ObjectType) {
// todo handle error
throw new RuntimeException('invalid handler');
}

$types[] = $type->getClassName();
}

if ($types) {
return $types;
}

// todo handle error
throw new RuntimeException('invalid handler');
// todo many class names?
foreach ($type->getObjectClassNames() as $className) {
yield $className => ['method' => self::DEFAULT_HANDLER_METHOD];
}

if (!$type instanceof ObjectType) {
throw new RuntimeException('invalid handler');
}

return [$type->getClassName()];
}

}
3 changes: 2 additions & 1 deletion src/Symfony/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ final class Service implements ServiceDefinition
/** @var string|null */
private $alias;

/** @var array */
/** @var ServiceTag[] */
private $tags;

/** @param ServiceTag[] $tags */
public function __construct(
string $id,
?string $class,
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/ServiceDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public function isSynthetic(): bool;

public function getAlias(): ?string;

/** @return ServiceTag[] */
public function getTags(): array;

}
3 changes: 2 additions & 1 deletion src/Symfony/ServiceTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ final class ServiceTag implements ServiceTagDefinition
/** @var string */
private $name;

/** @var array */
/** @var array<string, string> */
private $attributes;

/** @param array<string, string> $attributes */
public function __construct(string $name, array $attributes = [])
{
$this->name = $name;
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/ServiceTagDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface ServiceTagDefinition

public function getName(): string;

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

}
23 changes: 11 additions & 12 deletions src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
use PHPStan\Symfony\MessageMap;
use PHPStan\Symfony\MessageMapFactory;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use function count;
use function is_null;

final class MessengerHandleTraitDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
{

/** @var MessageMapFactory */
private $messageMapFactory;

/** @var MessageMap */
/** @var MessageMap|null */
private $messageMap;

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

// todo temporarily hardcoded test class here
return HandleTraitClass::class;
return HandleTraitClass::class; // @phpstan-ignore-line todo temporarily hardcoded test class here

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, lowest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, highest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.3, lowest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.3, highest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, lowest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, highest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, lowest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, highest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, lowest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, highest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, lowest)

No error to ignore is reported on line 38.

Check failure on line 38 in src/Type/Symfony/MessengerHandleTraitDynamicReturnTypeExtension.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, highest)

No error to ignore is reported on line 38.
}

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

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

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

if ($message->countReturnTypes() === 1) {
return $message->getReturnTypes()[0];
}
if (!is_null($message) && $message->countReturnTypes() === 1) {
return $message->getReturnTypes()[0];
}
}

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

private function getMessageMap(): MessageMap
{
if (!$this->messageMap) {
if (is_null($this->messageMap)) {
$this->messageMap = $this->messageMapFactory->create();
}

Expand Down

0 comments on commit e3790e0

Please sign in to comment.