From b79ba7fc94ad8618692859ced8ae9a2feedb044f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Mon, 4 Mar 2024 08:58:40 +0300 Subject: [PATCH] Psalm level 2 (#246) * 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * add sort * add sort --------- Co-authored-by: Dmitriy Derepko --- config/params.php | 2 -- psalm.xml | 3 +- src/Collector/ContainerProxyConfig.php | 5 ++- src/Collector/HttpClientCollector.php | 28 +++++++++------- src/Collector/LogCollector.php | 4 +-- src/Collector/ProxyLogTrait.php | 11 ++++--- src/Collector/ServiceCollector.php | 2 +- src/Collector/ServiceMethodProxy.php | 3 ++ src/Collector/ServiceProxy.php | 3 ++ src/Collector/TimelineCollector.php | 2 +- .../VarDumperHandlerInterfaceProxy.php | 2 +- src/Command/DebugContainerCommand.php | 2 +- src/Command/DebugEventsCommand.php | 7 ++-- src/Dumper.php | 33 ++++++++++--------- src/Helper/StreamWrapper/StreamWrapper.php | 3 ++ .../StreamWrapper/StreamWrapperInterface.php | 3 ++ 16 files changed, 68 insertions(+), 45 deletions(-) diff --git a/config/params.php b/config/params.php index f6d4d2cde..3457e19e3 100644 --- a/config/params.php +++ b/config/params.php @@ -6,7 +6,6 @@ use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Client\ClientInterface; use Psr\Log\LoggerInterface; -use Yiisoft\Cache\CacheInterface; use Yiisoft\Injector\Injector; use Yiisoft\Yii\Debug\Collector\Console\CommandCollector; use Yiisoft\Yii\Debug\Collector\Console\ConsoleAppInfoCollector; @@ -62,7 +61,6 @@ LoggerInterface::class => [LoggerInterfaceProxy::class, LogCollector::class], EventDispatcherInterface::class => [EventDispatcherInterfaceProxy::class, EventCollector::class], ClientInterface::class => [HttpClientInterfaceProxy::class, HttpClientCollector::class], - CacheInterface::class, ], 'dumper.excludedClasses' => [ 'PhpParser\\Parser\\Php7', diff --git a/psalm.xml b/psalm.xml index 91b98d3e8..2a2f7e560 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ + diff --git a/src/Collector/ContainerProxyConfig.php b/src/Collector/ContainerProxyConfig.php index b89cd04e0..969096bd9 100644 --- a/src/Collector/ContainerProxyConfig.php +++ b/src/Collector/ContainerProxyConfig.php @@ -11,6 +11,9 @@ final class ContainerProxyConfig { + /** + * @psalm-param array $decoratedServices + */ public function __construct( private bool $active = false, private array $decoratedServices = [], @@ -99,7 +102,7 @@ public function getProxyCachePath(): ?string return $this->proxyCachePath; } - public function getDecoratedServiceConfig($service) + public function getDecoratedServiceConfig(string $service): mixed { return $this->decoratedServices[$service]; } diff --git a/src/Collector/HttpClientCollector.php b/src/Collector/HttpClientCollector.php index 1080d7a83..55df1d1c0 100644 --- a/src/Collector/HttpClientCollector.php +++ b/src/Collector/HttpClientCollector.php @@ -10,22 +10,25 @@ use function count; +/** + * @psalm-type RequestEntry = array{ + * startTime: float, + * endTime: float, + * totalTime: float, + * method: string, + * uri: string, + * headers: string[][], + * line: string, + * responseRaw?: string, + * responseStatus?: int, + * } + */ final class HttpClientCollector implements SummaryCollectorInterface { use CollectorTrait; /** - * @psalm-var array> + * @psalm-var array> */ private array $requests = []; @@ -57,9 +60,10 @@ public function collectTotalTime(?ResponseInterface $response, float $endTime, ? return; } - if (!isset($this->requests[$uniqueId]) || !is_array($this->requests[$uniqueId])) { + if (!isset($this->requests[$uniqueId])) { return; } + /** @psalm-suppress UnsupportedReferenceUsage */ $entry = &$this->requests[$uniqueId][count($this->requests[$uniqueId]) - 1]; if ($response instanceof ResponseInterface) { $entry['responseRaw'] = Message::toString($response); diff --git a/src/Collector/LogCollector.php b/src/Collector/LogCollector.php index 291f44872..13fb73c1c 100644 --- a/src/Collector/LogCollector.php +++ b/src/Collector/LogCollector.php @@ -10,7 +10,7 @@ class LogCollector implements SummaryCollectorInterface private array $messages = []; - public function __construct(private TimelineCollector $timelineCollector, ) + public function __construct(private TimelineCollector $timelineCollector) { } @@ -22,7 +22,7 @@ public function getCollected(): array return $this->messages; } - public function collect(string $level, $message, array $context, string $line): void + public function collect(string $level, mixed $message, array $context, string $line): void { if (!$this->isActive()) { return; diff --git a/src/Collector/ProxyLogTrait.php b/src/Collector/ProxyLogTrait.php index b41c7bbbd..2b2b80918 100644 --- a/src/Collector/ProxyLogTrait.php +++ b/src/Collector/ProxyLogTrait.php @@ -15,7 +15,7 @@ protected function logProxy( object $instance, string $method, array $arguments, - $result, + mixed $result, float $timeStart ): void { $error = $this->getCurrentError(); @@ -30,7 +30,10 @@ protected function logProxy( } } - private function processLogData(array &$arguments, &$result, ?object &$error): void + /** + * @psalm-param-out array|null $arguments + */ + private function processLogData(array &$arguments, mixed &$result, ?object &$error): void { if (!($this->config->getLogLevel() & ContainerInterfaceProxy::LOG_ARGUMENTS)) { $arguments = null; @@ -50,7 +53,7 @@ private function logToCollector( object $instance, string $method, ?array $arguments, - $result, + mixed $result, ?object $error, float $timeStart ): void { @@ -72,7 +75,7 @@ private function logToEvent( object $instance, string $method, ?array $arguments, - $result, + mixed $result, ?object $error, float $timeStart ): void { diff --git a/src/Collector/ServiceCollector.php b/src/Collector/ServiceCollector.php index e281bc16d..ba95634ee 100644 --- a/src/Collector/ServiceCollector.php +++ b/src/Collector/ServiceCollector.php @@ -27,7 +27,7 @@ public function collect( string $class, string $method, ?array $arguments, - $result, + mixed $result, string $status, ?object $error, float $timeStart, diff --git a/src/Collector/ServiceMethodProxy.php b/src/Collector/ServiceMethodProxy.php index b4e9f6ddc..d596f27d0 100644 --- a/src/Collector/ServiceMethodProxy.php +++ b/src/Collector/ServiceMethodProxy.php @@ -33,6 +33,9 @@ protected function afterCall(string $methodName, array $arguments, mixed $result protected function getNewStaticInstance(object $instance): ObjectProxy { + /** + * @psalm-suppress UnsafeInstantiation Constructor should be consistent to `getNewStaticInstance()`. + */ return new static($this->getService(), $instance, $this->methods, $this->getConfig()); } } diff --git a/src/Collector/ServiceProxy.php b/src/Collector/ServiceProxy.php index eac850979..3131dc167 100644 --- a/src/Collector/ServiceProxy.php +++ b/src/Collector/ServiceProxy.php @@ -27,6 +27,9 @@ protected function afterCall(string $methodName, array $arguments, mixed $result protected function getNewStaticInstance(object $instance): ObjectProxy { + /** + * @psalm-suppress UnsafeInstantiation Constructor should be consistent to `getNewStaticInstance()`. + */ return new static($this->service, $instance, $this->config); } diff --git a/src/Collector/TimelineCollector.php b/src/Collector/TimelineCollector.php index 068ec0704..727caf0e4 100644 --- a/src/Collector/TimelineCollector.php +++ b/src/Collector/TimelineCollector.php @@ -18,7 +18,7 @@ public function getCollected(): array return $this->events; } - public function collect(CollectorInterface $collector, string|int $reference, ...$data): void + public function collect(CollectorInterface $collector, string|int $reference, mixed ...$data): void { if (!$this->isActive()) { return; diff --git a/src/Collector/VarDumperHandlerInterfaceProxy.php b/src/Collector/VarDumperHandlerInterfaceProxy.php index c8c7ae644..64c7e2aea 100644 --- a/src/Collector/VarDumperHandlerInterfaceProxy.php +++ b/src/Collector/VarDumperHandlerInterfaceProxy.php @@ -32,7 +32,7 @@ public function handle(mixed $variable, int $depth, bool $highlight = false): vo $callStack = $value; break; } - /** @psalm-var array{file: string, line: int} $callStack */ + /** @psalm-var array{file: string, line: int}|null $callStack */ $this->collector->collect( $variable, diff --git a/src/Command/DebugContainerCommand.php b/src/Command/DebugContainerCommand.php index 63f63f90e..cb1e55a51 100644 --- a/src/Command/DebugContainerCommand.php +++ b/src/Command/DebugContainerCommand.php @@ -116,7 +116,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($input->hasOption('groups') && $input->getOption('groups')) { $build = $this->getConfigBuild($config); $groups = array_keys($build); - ksort($groups); + sort($groups); $io->table(['Groups'], array_map(fn ($group) => [$group], $groups)); diff --git a/src/Command/DebugEventsCommand.php b/src/Command/DebugEventsCommand.php index c9a338c5e..372e7b053 100644 --- a/src/Command/DebugEventsCommand.php +++ b/src/Command/DebugEventsCommand.php @@ -5,6 +5,7 @@ namespace Yiisoft\Yii\Debug\Command; use Psr\Container\ContainerInterface; +use ReflectionClass; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputArgument; @@ -49,7 +50,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($input->hasOption('groups') && $input->getOption('groups')) { $build = $this->getConfigBuild($config); $groups = array_keys($build); - ksort($groups); + sort($groups); $io->table(['Groups'], array_map(fn ($group) => [$group], $groups)); @@ -89,7 +90,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int is_countable($listeners) ? count($listeners) : 0, implode( "\n", - array_map(function ($listener) { + array_map(function (mixed $listener) { if (is_array($listener)) { return sprintf( '%s::%s', @@ -113,7 +114,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int private function getConfigBuild(mixed $config): array { - $reflection = new \ReflectionClass($config); + $reflection = new ReflectionClass($config); $buildReflection = $reflection->getProperty('build'); $buildReflection->setAccessible(true); return $buildReflection->getValue($config); diff --git a/src/Dumper.php b/src/Dumper.php index 423c43477..f88440b08 100644 --- a/src/Dumper.php +++ b/src/Dumper.php @@ -4,6 +4,7 @@ namespace Yiisoft\Yii\Debug; +use __PHP_Incomplete_Class; use Closure; use Yiisoft\VarDumper\ClosureExporter; @@ -60,7 +61,7 @@ public function asJsonObjectsMap(int $depth = 50, bool $prettyPrint = false): st return $this->asJsonInternal($this->objects, $prettyPrint, $depth, 1, true); } - private function buildObjectsCache($variable, int $depth, int $level = 0): void + private function buildObjectsCache(mixed $variable, int $depth, int $level = 0): void { if ($depth <= $level) { return; @@ -89,7 +90,7 @@ private function buildObjectsCache($variable, int $depth, int $level = 0): void } private function asJsonInternal( - $variable, + mixed $variable, bool $format, int $depth, int $objectCollapseLevel, @@ -109,7 +110,7 @@ private function asJsonInternal( private function getObjectProperties(object $var): array { - if (\__PHP_Incomplete_Class::class !== $var::class && method_exists($var, '__debugInfo')) { + if (__PHP_Incomplete_Class::class !== $var::class && method_exists($var, '__debugInfo')) { $var = $var->__debugInfo(); } @@ -117,16 +118,16 @@ private function getObjectProperties(object $var): array } private function dumpNestedInternal( - $var, + mixed $variable, int $depth, int $level, int $objectCollapseLevel, bool $inlineObject ): mixed { - switch (gettype($var)) { + switch (gettype($variable)) { case 'array': if ($depth <= $level) { - $valuesCount = count($var); + $valuesCount = count($variable); if ($valuesCount === 0) { return []; } @@ -134,7 +135,7 @@ private function dumpNestedInternal( } $output = []; - foreach ($var as $key => $value) { + foreach ($variable as $key => $value) { $keyDisplay = str_replace("\0", '::', trim((string) $key)); $output[$keyDisplay] = $this->dumpNestedInternal( $value, @@ -147,16 +148,16 @@ private function dumpNestedInternal( break; case 'object': - $objectDescription = $this->getObjectDescription($var); - if ($depth <= $level || array_key_exists($var::class, $this->excludedClasses)) { + $objectDescription = $this->getObjectDescription($variable); + if ($depth <= $level || array_key_exists($variable::class, $this->excludedClasses)) { $output = $objectDescription . ' (...)'; break; } - if ($var instanceof Closure) { + if ($variable instanceof Closure) { $output = $inlineObject - ? $this->exportClosure($var) - : [$objectDescription => $this->exportClosure($var)]; + ? $this->exportClosure($variable) + : [$objectDescription => $this->exportClosure($variable)]; break; } @@ -165,7 +166,7 @@ private function dumpNestedInternal( break; } - $properties = $this->getObjectProperties($var); + $properties = $this->getObjectProperties($variable); if (empty($properties)) { if ($inlineObject) { $output = '{stateless object}'; @@ -194,10 +195,10 @@ private function dumpNestedInternal( break; case 'resource': case 'resource (closed)': - $output = $this->getResourceDescription($var); + $output = $this->getResourceDescription($variable); break; default: - $output = $var; + $output = $variable; } return $output; @@ -226,7 +227,7 @@ private function normalizeProperty(string $property): string return 'public $' . $property; } - private function getResourceDescription($resource): array|string + private function getResourceDescription(mixed $resource): array|string { if (!is_resource($resource)) { return '{closed resource}'; diff --git a/src/Helper/StreamWrapper/StreamWrapper.php b/src/Helper/StreamWrapper/StreamWrapper.php index 7bafcc087..608e1ff48 100644 --- a/src/Helper/StreamWrapper/StreamWrapper.php +++ b/src/Helper/StreamWrapper/StreamWrapper.php @@ -102,6 +102,9 @@ public function rmdir(string $path, int $options): bool return rmdir($path, $this->context); } + /** + * @psalm-suppress InvalidReturnType Unfortunately, I don't know what to return here. + */ public function stream_cast(int $castAs) { // ??? diff --git a/src/Helper/StreamWrapper/StreamWrapperInterface.php b/src/Helper/StreamWrapper/StreamWrapperInterface.php index 76443a701..5ffd740fc 100644 --- a/src/Helper/StreamWrapper/StreamWrapperInterface.php +++ b/src/Helper/StreamWrapper/StreamWrapperInterface.php @@ -23,6 +23,9 @@ public function stream_eof(): bool; public function stream_seek(int $offset, int $whence = SEEK_SET): bool; + /** + * @return resource + */ public function stream_cast(int $castAs); public function stream_stat(): array|false;