Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix psalm, clear psalm-baseline.yaml #57

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
515 changes: 29 additions & 486 deletions psalm-baseline.xml

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions psalm.xml
roxblnfk marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
<issueHandlers>
<RedundantConditionGivenDocblockType errorLevel="suppress"/>
<RedundantCastGivenDocblockType errorLevel="suppress"/>
<MixedAssignment errorLevel="suppress"/>
<MixedArrayOffset errorLevel="suppress"/>
<MixedArgument errorLevel="suppress"/>
<MixedMethodCall errorLevel="suppress"/>
<MixedPropertyTypeCoercion errorLevel="suppress"/>
<MixedArrayAccess errorLevel="suppress"/>
</issueHandlers>
<projectFiles>
<directory name="src"/>
Expand Down
4 changes: 2 additions & 2 deletions src/Sender/Console/Renderer/Smtp.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ public function render(OutputInterface $output, Frame $frame): void
foreach ($message->getAttachments() as $attach) {
Files::renderFile(
$output,
$attach->getClientFilename(),
$attach->getClientFilename() ?? 'undefined',
$attach->getSize(),
$attach->getClientMediaType(),
$attach->getClientMediaType() ?? 'undefined',
);
}
$output->writeln('');
Expand Down
1 change: 1 addition & 0 deletions src/Sender/Console/Renderer/TemplateRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public function __construct(

public function render(string $template, array $data = []): void
{
/** @psalm-suppress InternalMethod */
$this->renderer->render(
$this->templateEngine->render($template, $data),
0
Expand Down
4 changes: 2 additions & 2 deletions src/Sender/Console/Renderer/VarDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function describe(OutputInterface $output, Data $data, array $context, in
empty($request['method'] ?? '') or $meta['Method'] = $request['method'];
empty($request['uri'] ?? '') or $meta['URI'] = $request['uri'];
if ($controller = $request['controller']) {
$meta['Controller'] = rtrim($this->dumper->dump($controller, true), "\n");
$meta['Controller'] = rtrim((string) $this->dumper->dump($controller, true), "\n");
}
} elseif (isset($context['cli'])) {
$meta['Command'] = $context['cli']['command_line'];
Expand All @@ -107,7 +107,7 @@ public function describe(OutputInterface $output, Data $data, array $context, in
Common::renderMetadata($output, $meta);
$output->writeln('');

$output->write($this->dumper->dump($data, true), true, OutputInterface::OUTPUT_RAW);
$output->write((string) $this->dumper->dump($data, true), true, OutputInterface::OUTPUT_RAW);
}
};
}
Expand Down
8 changes: 4 additions & 4 deletions src/Sender/Console/Support/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ public static function renderHeader1(OutputInterface $output, string $title, ?st
$output->writeln(['', \implode('', $parts), '']);
}

public static function renderHeader2(OutputInterface $output, string $title, string ...$sub): void
public static function renderHeader2(OutputInterface $output, string $title, ?string ...$sub): void
{
$parts = ["<fg=white;options=bold># $title </>"];
foreach ($sub as $color => $value) {
$color = \is_string($color) ? $color : 'gray';
$parts[] = \sprintf('<fg=%s> %s </>', $color, $value);
$parts[] = \sprintf('<fg=%s> %s </>', $color, $value ?? 'NULL');
roxblnfk marked this conversation as resolved.
Show resolved Hide resolved
}

$output->writeln(['', \implode('', $parts), '']);
Expand All @@ -53,13 +53,13 @@ public static function renderHighlightedLine(OutputInterface $output, string $li
}

/**
* @param array<array-key, mixed> $data
* @param array<string, mixed> $data
roxblnfk marked this conversation as resolved.
Show resolved Hide resolved
*/
public static function renderMetadata(OutputInterface $output, array $data): void
{
/** @psalm-suppress ArgumentTypeCoercion */
$maxHeaderLength = \max(\array_map('strlen', \array_keys($data)));

/** @var mixed $value */
foreach ($data as $head => $value) {
// Align headers to the right
self::renderHeader(
Expand Down
6 changes: 5 additions & 1 deletion src/Sender/Console/Support/Files.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
final class Files
{
/**
*
* @param non-negative-int|null $size
*
* Render file info. Example:
* ┌───┐ logo.ico
* │ico│ 20.06 KiB
Expand All @@ -24,6 +27,7 @@ final class Files
* │ │ any value <= positional argument
* │ico│ unknown size
* └───┘ image/x-icon
*
*/
public static function renderFile(
OutputInterface $output,
Expand All @@ -33,7 +37,7 @@ public static function renderFile(
string ...$additional
): void {
// File extension
$ex = \substr($fileName, \strrpos($fileName, '.') + 1);
$ex = \substr($fileName, (int) \strrpos($fileName, '.') + 1);
$ex = \strlen($ex) > 3 ? ' ' : \str_pad($ex, 3, ' ', \STR_PAD_BOTH);

// File size
Expand Down
2 changes: 1 addition & 1 deletion src/Sender/Console/Support/Tables.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static function renderKeyValueTable(OutputInterface $output, string $titl
return;
}

$keyLength = \max(\array_map(static fn($key) => \strlen($key), \array_keys($data)));
$keyLength = \max(\array_map(static fn($key) => \strlen((string) $key), \array_keys($data)));
$valueLength = \max(1, (new Terminal())->getWidth() - 7 - $keyLength);

$table->setRows([...(static function (array $data) use ($valueLength): iterable {
Expand Down
2 changes: 2 additions & 0 deletions src/Sender/ConsoleSender.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ final class ConsoleSender implements Sender
{
public static function create(OutputInterface $output): self
{
/** @psalm-suppress InternalMethod, InternalClass */
Termwind::renderUsing($output);

/** @psalm-suppress InternalClass */
$templateRenderer = new TemplateRenderer(
new HtmlRenderer(),
new TemplateEngine(Info::TRAP_ROOT . '/resources/templates')
Expand Down
5 changes: 5 additions & 0 deletions src/Socket/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ final class Client implements Destroyable
private \Closure $onPayload;
private \Closure $onClose;

/**
* @param positive-int $payloadSize
*/
private function __construct(
private readonly \Socket $socket,
private readonly int $payloadSize,
Expand Down Expand Up @@ -117,6 +120,7 @@ protected function onInit(): void
*/
public function setOnPayload(callable $callable): void
{
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$this->onPayload = \Closure::bind($callable(...), $this);
}

Expand All @@ -126,6 +130,7 @@ public function setOnPayload(callable $callable): void
*/
public function setOnClose(callable $callable): void
{
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$this->onClose = \Closure::bind($callable(...), $this);
}

Expand Down
1 change: 1 addition & 0 deletions src/Socket/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public static function init(

public function process(): void
{
/** @psalm-suppress PossiblyInvalidArgument */
while (!$this->cancelled and false !== ($socket = \socket_accept($this->socket))) {
$client = null;
try {
Expand Down
2 changes: 1 addition & 1 deletion src/Support/StreamHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static function strpos(StreamInterface $stream, string $substr): int|fals
*
* @param non-empty-string $boundary
*
* @return int Bytes written
* @return non-negative-int Bytes written
*/
public static function writeStreamUntil(StreamInterface $from, StreamInterface $to, string $boundary): int
{
Expand Down
1 change: 1 addition & 0 deletions src/Traffic/Dispatcher/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function __construct(
$handlers[] = new Fallback($middlewares);

// Build pipeline of handlers.
/** @psalm-suppress MixedPropertyTypeCoercion */
$this->pipeline = Pipeline::build(
$handlers,
/** @see RequestHandler::handle() */
Expand Down
3 changes: 2 additions & 1 deletion src/Traffic/Dispatcher/Smtp.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public function __construct(
public function dispatch(StreamClient $stream): iterable
{
$stream->sendData($this->createResponse(self::READY, 'mailamie'));

$protocol = [];

$message = null;
Expand All @@ -40,9 +39,11 @@ public function dispatch(StreamClient $stream): iterable
if (\preg_match('/^(?:EHLO|HELO)/', $response)) {
$stream->sendData($this->createResponse(self::OK));
} elseif (\preg_match('/^MAIL FROM:\s*<(.*)>/', $response, $matches)) {
/** @var array{1: non-empty-string} $matches */
$protocol['FROM'][] = $matches[1];
$stream->sendData($this->createResponse(self::OK));
} elseif (\preg_match('/^RCPT TO:\s*<(.*)>/', $response, $matches)) {
/** @var array{1: non-empty-string} $matches */
$protocol['BCC'][] = $matches[1];
$stream->sendData($this->createResponse(self::OK));
} elseif (\str_starts_with($response, 'QUIT')) {
Expand Down
25 changes: 17 additions & 8 deletions src/Traffic/Message/Headers.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
*/
trait Headers
{
/** @var array Map of all registered headers, as original name => array of values */
/** @var array<non-empty-string, list<string>> Map of all registered headers, as original name => array of values */
private array $headers = [];

/** @var array Map of lowercase header name => original name at registration */
/** @var array<non-empty-string, non-empty-string> Map of lowercase header name => original name at registration */
private array $headerNames = [];

/**
* @return array<non-empty-string, list<string>>
*/
public function getHeaders(): array
{
return $this->headers;
Expand All @@ -26,7 +29,7 @@ public function hasHeader(string $header): bool
}

/**
* @return string[]
* @return list<string>
*/
public function getHeader(string $header): array
{
Expand All @@ -45,9 +48,10 @@ public function getHeaderLine(string $header): string
return \implode(', ', $this->getHeader($header));
}

public function withHeader(string $header, $value): static
public function withHeader(string $header, mixed $value): static
{
$value = $this->validateAndTrimHeader($header, $value);
/** @var non-empty-string $normalized */
$normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');

$new = clone $this;
Expand Down Expand Up @@ -87,7 +91,7 @@ public function withoutHeader(string $header): static
}

/**
* @param array<array-key, scalar|list<scalar>> $headers
* @param array<string|int, scalar|list<scalar>> $headers
*/
private function setHeaders(array $headers): void
{
Expand All @@ -98,6 +102,7 @@ private function setHeaders(array $headers): void
$header = (string)$header;
}
$value = $this->validateAndTrimHeader($header, $value);
/** @var non-empty-string $normalized */
$normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
if (isset($this->headerNames[$normalized])) {
$header = $this->headerNames[$normalized];
Expand Down Expand Up @@ -126,8 +131,12 @@ private function setHeaders(array $headers): void
* field-value = *( ( %x21-7E / %x80-FF ) [ 1*( SP / HTAB ) ( %x21-7E / %x80-FF ) ] )
*
* @see https://tools.ietf.org/html/rfc7230#section-3.2.4
*
* @psalm-assert non-empty-string $header
*
* @return non-empty-list<string>
*/
private function validateAndTrimHeader(string $header, $values): array
private function validateAndTrimHeader(string $header, mixed $values): array
{
if (1 !== \preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@D", $header)) {
throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string');
Expand Down Expand Up @@ -170,10 +179,10 @@ private function validateAndTrimHeader(string $header, $values): array
/**
* List of header values.
*
* @param array<string, list<non-empty-string>> $headers
* @param array<non-empty-string, list<string>> $headers
* @param non-empty-string $header
*
* @return list<non-empty-string>
* @return list<string>
*/
private static function findHeader(array $headers, string $header): array
{
Expand Down
6 changes: 5 additions & 1 deletion src/Traffic/Message/Multipart/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

/**
* @psalm-type FieldDataArray = array{
* headers: array<string, non-empty-list<string>>,
* headers: array<non-empty-string, list<string>>,
* name?: string,
* value: string
* }
Expand All @@ -15,6 +15,9 @@
*/
final class Field extends Part
{
/**
* @param array<non-empty-string, list<string>> $headers
*/
public function __construct(array $headers, ?string $name = null, private string $value = '')
{
parent::__construct($headers, $name);
Expand All @@ -30,6 +33,7 @@ public static function fromArray(array $data): self

/**
* @return FieldDataArray
* @psalm-suppress ImplementedReturnTypeMismatch
*/
public function jsonSerialize(): array
{
Expand Down
34 changes: 26 additions & 8 deletions src/Traffic/Message/Multipart/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@

/**
* @psalm-type FileDataArray = array{
* headers: array<string, non-empty-list<string>>,
* headers: array<non-empty-string, list<string>>,
* name?: string,
* fileName: string,
* size?: int
* fileName?: string,
* size?: non-negative-int
* }
*
* @internal
*/
final class File extends Part implements UploadedFileInterface
{
private ?UploadedFileInterface $uploadedFile = null;
/** @var non-negative-int|null */
private ?int $fileSize = null;

/**
* @param array<non-empty-string, list<string>> $headers
*/
public function __construct(array $headers, ?string $name = null, private ?string $fileName = null)
{
parent::__construct($headers, $name);
Expand All @@ -33,24 +37,35 @@ public function __construct(array $headers, ?string $name = null, private ?strin
*/
public static function fromArray(array $data): self
{
$self = new self($data['headers'], $data['name'] ?? null, $data['fileName']);
$self = new self($data['headers'], $data['name'] ?? null, $data['fileName'] ?? null);
$self->fileSize = $data['size'] ?? null;
return $self;
}

/**
* @return FileDataArray
*
* @psalm-suppress ImplementedReturnTypeMismatch
*/
public function jsonSerialize(): array
{
return parent::jsonSerialize() + [
'fileName' => $this->fileName,
'size' => $this->getSize(),
];
$data = parent::jsonSerialize();
if ($this->fileName !== null) {
$data['fileName'] = $this->fileName;
}
if ($this->fileSize !== null) {
$data['size'] = $this->fileSize;
}

return $data;
}

/**
* @param non-negative-int|null $size
*/
public function setStream(StreamInterface $stream, ?int $size = null, int $code = \UPLOAD_ERR_OK): void
{
/** @psalm-suppress PropertyTypeCoercion */
$this->fileSize = $size ?? $stream->getSize() ?? null;
$this->uploadedFile = new UploadedFile(
$stream,
Expand Down Expand Up @@ -83,6 +98,9 @@ public function moveTo(string $targetPath): void
$this->getUploadedFile()->moveTo($targetPath);
}

/**
* @return non-negative-int|null
*/
public function getSize(): ?int
{
return $this->fileSize;
Expand Down
Loading
Loading