From 04a6ff44268b60f49ab04a558cd501224dd58163 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Sat, 1 Jun 2024 23:46:22 +0400 Subject: [PATCH] chore(psalm): fix psalm issues --- psalm-baseline.xml | 14 ----------- src/Client/TrapHandle.php | 1 + src/Client/TrapHandle/StackTrace.php | 18 +++++++++++---- src/Command/Run.php | 2 ++ src/Config/Server/Files/ObserverConfig.php | 1 + src/Proto/Frame/Profiler.php | 5 ++++ src/Proto/Frame/Profiler/Payload.php | 19 +++++++++++---- src/Sender/ConsoleSender.php | 2 +- src/Service/Config/ConfigLoader.php | 8 +++---- src/Service/FilesObserver/FileInfo.php | 15 ++++++++++++ src/Service/FilesObserver/Handler.php | 3 +-- src/Socket/Client.php | 8 +++++-- src/functions.php | 27 +++++++++++----------- 13 files changed, 78 insertions(+), 45 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index c2612d42..438f66cf 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -222,18 +222,4 @@ - - - - - - - - - - - - - - diff --git a/src/Client/TrapHandle.php b/src/Client/TrapHandle.php index 24041b36..f4ba6edf 100644 --- a/src/Client/TrapHandle.php +++ b/src/Client/TrapHandle.php @@ -41,6 +41,7 @@ public static function fromArray(array $array): self * * @param int<0, max> $number The tick number. * @param float $delta The time delta between the current and previous tick. + * @param int<0, max> $memory The memory usage. * * @internal */ diff --git a/src/Client/TrapHandle/StackTrace.php b/src/Client/TrapHandle/StackTrace.php index a8a9bb06..4072bee2 100644 --- a/src/Client/TrapHandle/StackTrace.php +++ b/src/Client/TrapHandle/StackTrace.php @@ -47,11 +47,19 @@ public static function stackTrace(string $baseDir = '', bool $provideObjects = f $cwdLen = \strlen($dir); $stack = []; $internal = false; - foreach ( - \debug_backtrace( - ($provideObjects ? \DEBUG_BACKTRACE_PROVIDE_OBJECT : 0) | \DEBUG_BACKTRACE_IGNORE_ARGS, - ) as $frame - ) { + + /** @var array{ + * function: non-empty-string, + * line?: int, + * file?: string, + * class?: class-string, + * type?: string, + * object?: object, + * args?: list + * } $frame */ + foreach (\debug_backtrace( + ($provideObjects ? \DEBUG_BACKTRACE_PROVIDE_OBJECT : 0) | \DEBUG_BACKTRACE_IGNORE_ARGS, + ) as $frame) { $class = $frame['class'] ?? ''; if (\str_starts_with($class, 'Buggregator\\Trap\\Client\\')) { $internal = true; diff --git a/src/Command/Run.php b/src/Command/Run.php index 69d430c0..a303e48c 100644 --- a/src/Command/Run.php +++ b/src/Command/Run.php @@ -95,7 +95,9 @@ public function createRegistry(OutputInterface $output): Sender\SenderRegistry public function getSubscribedSignals(): array { $result = []; + /** @psalm-suppress MixedAssignment */ \defined('SIGINT') and $result[] = \SIGINT; + /** @psalm-suppress MixedAssignment */ \defined('SIGTERM') and $result[] = \SIGTERM; return $result; diff --git a/src/Config/Server/Files/ObserverConfig.php b/src/Config/Server/Files/ObserverConfig.php index e9a20ac7..0d7e7a5e 100644 --- a/src/Config/Server/Files/ObserverConfig.php +++ b/src/Config/Server/Files/ObserverConfig.php @@ -26,6 +26,7 @@ abstract class ObserverConfig */ public function isValid(): bool { + /** @psalm-suppress RedundantCondition */ return $this->path !== null && $this->converterClass !== null && $this->path !== '' && \is_a($this->converterClass, FrameConverter::class, true) && $this->scanInterval > 0.0; } diff --git a/src/Proto/Frame/Profiler.php b/src/Proto/Frame/Profiler.php index 578faac9..3ef19393 100644 --- a/src/Proto/Frame/Profiler.php +++ b/src/Proto/Frame/Profiler.php @@ -5,10 +5,14 @@ namespace Buggregator\Trap\Proto\Frame; use Buggregator\Trap\Proto\Frame; +use Buggregator\Trap\Proto\Frame\Profiler\Type as PayloadType; use Buggregator\Trap\ProtoType; use Buggregator\Trap\Support\Json; /** + * @psalm-import-type Calls from \Buggregator\Trap\Proto\Frame\Profiler\Payload + * @psalm-import-type Metadata from \Buggregator\Trap\Proto\Frame\Profiler\Payload + * * @internal * @psalm-internal Buggregator */ @@ -23,6 +27,7 @@ public function __construct( public static function fromString(string $payload, \DateTimeImmutable $time): static { + /** @var array{type: non-empty-string}&Calls&Metadata $data */ $data = Json::decode($payload); return new self(Frame\Profiler\Payload::fromArray($data), $time); diff --git a/src/Proto/Frame/Profiler/Payload.php b/src/Proto/Frame/Profiler/Payload.php index 4162b40f..685d1798 100644 --- a/src/Proto/Frame/Profiler/Payload.php +++ b/src/Proto/Frame/Profiler/Payload.php @@ -21,7 +21,7 @@ * @internal * @psalm-internal Buggregator */ -class Payload implements \JsonSerializable +final class Payload implements \JsonSerializable { /** * @param PayloadType $type @@ -46,17 +46,25 @@ public static function new( array $metadata, \Closure $callsProvider, ): self { - return new static($type, $metadata, $callsProvider); + return new self($type, $metadata, $callsProvider); } + /** + * @param array{type: non-empty-string}&Calls&Metadata $data + * @param PayloadType|null $type + */ public static function fromArray(array $data, ?Type $type = null): static { $metadata = $data; unset($metadata['edges'], $metadata['peaks']); - return new static( + + /** @var \Closure(): Calls $provider */ + $provider = static fn(): array => $data; + + return new self( $type ?? PayloadType::from($data['type']), $metadata, - static fn(): array => $data, + $provider, ); } @@ -76,6 +84,9 @@ public function getMetadata(): array return $this->metadata; } + /** + * @return array{type: non-empty-string}&Calls&Metadata + */ public function toArray(): array { return ['type' => $this->type->value] + $this->getCalls() + $this->getMetadata(); diff --git a/src/Sender/ConsoleSender.php b/src/Sender/ConsoleSender.php index 821ee2a1..a5d9ed0d 100644 --- a/src/Sender/ConsoleSender.php +++ b/src/Sender/ConsoleSender.php @@ -43,7 +43,7 @@ public static function create(OutputInterface $output): self $renderer->register(new Renderer\Http()); $renderer->register(new Renderer\Profiler()); $renderer->register(new Renderer\Binary()); - $renderer->register(new Renderer\Plain($templateRenderer)); + $renderer->register(new Renderer\Plain()); return new self($renderer); } diff --git a/src/Service/Config/ConfigLoader.php b/src/Service/Config/ConfigLoader.php index f1cdb8f5..9fde86c8 100644 --- a/src/Service/Config/ConfigLoader.php +++ b/src/Service/Config/ConfigLoader.php @@ -59,10 +59,10 @@ private function injectValue(object $config, \ReflectionProperty $property, arra /** @var mixed $value */ $value = match (true) { - $attribute instanceof XPath => (static fn(?array $value, int $key): mixed => match (true) { - \array_key_exists($key, $value) => $value[$key], - default => null, - })($this->xml?->xpath($attribute->path), $attribute->key), + $attribute instanceof XPath => (static fn(array|false|null $value, int $key): mixed + => \is_array($value) && \array_key_exists($key, $value) + ? $value[$key] + : null)($this->xml?->xpath($attribute->path), $attribute->key), $attribute instanceof Env => $this->env[$attribute->name] ?? null, $attribute instanceof InputOption => $this->inputOptions[$attribute->name] ?? null, $attribute instanceof InputArgument => $this->inputArguments[$attribute->name] ?? null, diff --git a/src/Service/FilesObserver/FileInfo.php b/src/Service/FilesObserver/FileInfo.php index c8572edb..020064c2 100644 --- a/src/Service/FilesObserver/FileInfo.php +++ b/src/Service/FilesObserver/FileInfo.php @@ -9,6 +9,12 @@ */ final class FileInfo { + /** + * @param non-empty-string $path + * @param int<0, max> $size + * @param int<0, max> $ctime + * @param int<0, max> $mtime + */ public function __construct( public readonly string $path, public readonly int $size, @@ -18,6 +24,7 @@ public function __construct( public static function fromSplFileInfo(\SplFileInfo $fileInfo): self { + /** @psalm-suppress ArgumentTypeCoercion */ return new self( $fileInfo->getRealPath(), $fileInfo->getSize(), @@ -26,6 +33,14 @@ public static function fromSplFileInfo(\SplFileInfo $fileInfo): self ); } + /** + * @param array{ + * path: non-empty-string, + * size: int<0, max>, + * ctime: int<0, max>, + * mtime: int<0, max> + * } $data + */ public static function fromArray(array $data): self { return new self( diff --git a/src/Service/FilesObserver/Handler.php b/src/Service/FilesObserver/Handler.php index 41e651c7..bda3f919 100644 --- a/src/Service/FilesObserver/Handler.php +++ b/src/Service/FilesObserver/Handler.php @@ -69,7 +69,7 @@ private function syncFiles(): array foreach ($files as $info) { $path = $info->path; - if (!\is_string($path) || \array_key_exists($path, $this->cache)) { + if (\array_key_exists($path, $this->cache)) { $newState[$path] = $this->cache[$path]; continue; } @@ -102,7 +102,6 @@ private function getFiles(): \Traversable } catch (\Throwable $e) { $this->logger->info('Failed to read files from path `%s`', $this->path); $this->logger->exception($e); - return []; } } } diff --git a/src/Socket/Client.php b/src/Socket/Client.php index 9b1a2692..61d0ec55 100644 --- a/src/Socket/Client.php +++ b/src/Socket/Client.php @@ -112,7 +112,9 @@ public function process(): void */ public function setOnPayload(callable $callable): void { - $this->onPayload = @\Closure::bind($callable(...), $this) ?? $callable(...); + $closure = $callable(...); + /** @psalm-suppress PossiblyNullPropertyAssignmentValue, InvalidArgument */ + $this->onPayload = @\Closure::bind($closure, $this) ?? $closure; } /** @@ -121,7 +123,9 @@ public function setOnPayload(callable $callable): void */ public function setOnClose(callable $callable): void { - $this->onClose = @\Closure::bind($callable(...), $this) ?? $callable(...); + $closure = $callable(...); + /** @psalm-suppress PossiblyNullPropertyAssignmentValue, InvalidArgument */ + $this->onClose = @\Closure::bind($closure, $this) ?? $closure; } public function send(string $payload): void diff --git a/src/functions.php b/src/functions.php index 88f0f5fa..59552128 100644 --- a/src/functions.php +++ b/src/functions.php @@ -54,11 +54,13 @@ function tr(mixed ...$values): mixed $mem = $time = \microtime(true); try { if ($values === []) { + /** @var int<0, max> $memory */ + $memory = \memory_get_usage(); /** @psalm-suppress InternalMethod */ return TrapHandle::fromTicker( $counter, $counter === 0 ? 0 : $mem - $previous, - \memory_get_usage(), + $memory, )->return(); } @@ -95,16 +97,15 @@ function td(mixed ...$values): never * Register the var-dump caster for protobuf messages */ if (\class_exists(AbstractCloner::class)) { - /** @psalm-suppress MixedAssignment */ - AbstractCloner::$defaultCasters[Message::class] ??= [ProtobufCaster::class, 'cast']; - /** @psalm-suppress MixedAssignment */ - AbstractCloner::$defaultCasters[RepeatedField::class] ??= [ProtobufCaster::class, 'castRepeated']; - /** @psalm-suppress MixedAssignment */ - AbstractCloner::$defaultCasters[MapField::class] ??= [ProtobufCaster::class, 'castMap']; - /** @psalm-suppress MixedAssignment */ - AbstractCloner::$defaultCasters[EnumValue::class] ??= [ProtobufCaster::class, 'castEnum']; - /** @psalm-suppress MixedAssignment */ - AbstractCloner::$defaultCasters[Trace::class] = [TraceCaster::class, 'cast']; - /** @psalm-suppress MixedAssignment */ - AbstractCloner::$defaultCasters[TraceFile::class] = [TraceCaster::class, 'castLine']; + /** @var array $casters */ + $casters = AbstractCloner::$defaultCasters; + + $casters[Message::class] ??= [ProtobufCaster::class, 'cast']; + $casters[RepeatedField::class] ??= [ProtobufCaster::class, 'castRepeated']; + $casters[MapField::class] ??= [ProtobufCaster::class, 'castMap']; + $casters[EnumValue::class] ??= [ProtobufCaster::class, 'castEnum']; + $casters[Trace::class] = [TraceCaster::class, 'cast']; + $casters[TraceFile::class] = [TraceCaster::class, 'castLine']; + + unset($casters); }