refacto(phpstan-to-8): few adjustments

This commit is contained in:
Nuno Maduro
2021-11-18 23:39:37 +00:00
parent 7ea6d8a35d
commit 94585789dc
18 changed files with 107 additions and 94 deletions

View File

@ -4,7 +4,7 @@ includes:
- vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon - vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon
parameters: parameters:
level: 9 level: max
paths: paths:
- src - src

View File

@ -15,7 +15,7 @@ final class BootSubscribers
/** /**
* The Kernel subscribers. * The Kernel subscribers.
* *
* @var array<int, class-string> * @var array<int, class-string<\PHPUnit\Event\Subscriber>>
*/ */
private static array $subscribers = [ private static array $subscribers = [
Subscribers\EnsureConfigurationIsValid::class, Subscribers\EnsureConfigurationIsValid::class,
@ -29,7 +29,7 @@ final class BootSubscribers
{ {
foreach (self::$subscribers as $subscriber) { foreach (self::$subscribers as $subscriber) {
Event\Facade::registerSubscriber( Event\Facade::registerSubscriber(
new $subscriber() //@phpstan-ignore-line new $subscriber()
); );
} }
} }

View File

@ -34,7 +34,7 @@ final class Datasets
/** /**
* Sets the given. * Sets the given.
* *
* @phpstan-param Closure|iterable<int|string, mixed> $data * @param Closure|iterable<int|string, mixed> $data
*/ */
public static function set(string $name, Closure|iterable $data): void public static function set(string $name, Closure|iterable $data): void
{ {
@ -46,9 +46,9 @@ final class Datasets
} }
/** /**
* Sets the given. * Sets the given "with".
* *
* @phpstan-param array<Closure|iterable<int|string, mixed>|string> $with * @param array<Closure|iterable<int|string, mixed>|string> $with
*/ */
public static function with(string $filename, string $description, array $with): void public static function with(string $filename, string $description, array $with): void
{ {
@ -56,7 +56,9 @@ final class Datasets
} }
/** /**
* @return Closure|iterable<int|string, mixed> * @return Closure|iterable<int|string, mixed>|never
*
* @throws ShouldNotHappen
*/ */
public static function get(string $filename, string $description): Closure|iterable public static function get(string $filename, string $description): Closure|iterable
{ {
@ -65,7 +67,7 @@ final class Datasets
$dataset = self::resolve($description, $dataset); $dataset = self::resolve($description, $dataset);
if ($dataset === null) { if ($dataset === null) {
throw ShouldNotHappen::fromMessage('Could not resolve dataset.'); throw ShouldNotHappen::fromMessage('Dataset [%s] not resolvable.');
} }
return $dataset; return $dataset;
@ -87,39 +89,40 @@ final class Datasets
$dataset = self::processDatasets($dataset); $dataset = self::processDatasets($dataset);
$datasetCombinations = self::getDataSetsCombinations($dataset); $datasetCombinations = self::getDatasetsCombinations($dataset);
$dataSetDescriptions = []; $datasetDescriptions = [];
$dataSetValues = []; $datasetValues = [];
foreach ($datasetCombinations as $datasetCombination) { foreach ($datasetCombinations as $datasetCombination) {
$partialDescriptions = []; $partialDescriptions = [];
$values = []; $values = [];
foreach ($datasetCombination as $dataset_data) { foreach ($datasetCombination as $datasetCombinationElement) {
$partialDescriptions[] = $dataset_data['label']; $partialDescriptions[] = $datasetCombinationElement['label'];
//@phpstan-ignore-next-line
$values = array_merge($values, $dataset_data['values']); // @phpstan-ignore-next-line
$values = array_merge($values, $datasetCombinationElement['values']);
} }
$dataSetDescriptions[] = $description . ' with ' . implode(' / ', $partialDescriptions); $datasetDescriptions[] = $description . ' with ' . implode(' / ', $partialDescriptions);
$dataSetValues[] = $values; $datasetValues[] = $values;
} }
foreach (array_count_values($dataSetDescriptions) as $descriptionToCheck => $count) { foreach (array_count_values($datasetDescriptions) as $descriptionToCheck => $count) {
if ($count > 1) { if ($count > 1) {
$index = 1; $index = 1;
foreach ($dataSetDescriptions as $i => $dataSetDescription) { foreach ($datasetDescriptions as $i => $datasetDescription) {
if ($dataSetDescription === $descriptionToCheck) { if ($datasetDescription === $descriptionToCheck) {
$dataSetDescriptions[$i] .= sprintf(' #%d', $index++); $datasetDescriptions[$i] .= sprintf(' #%d', $index++);
} }
} }
} }
} }
$namedData = []; $namedData = [];
foreach ($dataSetDescriptions as $i => $dataSetDescription) { foreach ($datasetDescriptions as $i => $datasetDescription) {
$namedData[$dataSetDescription] = $dataSetValues[$i]; $namedData[$datasetDescription] = $datasetValues[$i];
} }
return $namedData; return $namedData;
@ -157,7 +160,7 @@ final class Datasets
foreach ($datasets[$index] as $key => $values) { foreach ($datasets[$index] as $key => $values) {
$values = is_array($values) ? $values : [$values]; $values = is_array($values) ? $values : [$values];
$processedDataset[] = [ $processedDataset[] = [
'label' => self::getDataSetDescription($key, $values), //@phpstan-ignore-line 'label' => self::getDatasetDescription($key, $values), //@phpstan-ignore-line
'values' => $values, 'values' => $values,
]; ];
} }
@ -173,7 +176,7 @@ final class Datasets
* *
* @return array<array<array<mixed>>> * @return array<array<array<mixed>>>
*/ */
private static function getDataSetsCombinations(array $combinations): array private static function getDatasetsCombinations(array $combinations): array
{ {
$result = [[]]; $result = [[]];
foreach ($combinations as $index => $values) { foreach ($combinations as $index => $values) {
@ -193,7 +196,7 @@ final class Datasets
/** /**
* @param array<int, mixed> $data * @param array<int, mixed> $data
*/ */
private static function getDataSetDescription(int|string $key, array $data): string private static function getDatasetDescription(int|string $key, array $data): string
{ {
$exporter = new Exporter(); $exporter = new Exporter();

View File

@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Pest\Exceptions;
/**
* @internal
*/
final class ExpectationException extends \Exception
{
public static function invalidCurrentValueType(string $expectationName, string $valueRequired): ExpectationException
{
return new ExpectationException(sprintf('%s expectation requires a %s value.', $expectationName, $valueRequired));
}
public static function invalidExpectedValueType(string $expectationName, string $valueRequired): ExpectationException
{
return new ExpectationException(sprintf('%s expectation requires a %s as expected value.', $expectationName, $valueRequired));
}
}

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Pest\Exceptions;
use InvalidArgumentException;
/**
* @internal
*/
final class InvalidExpectationValue extends InvalidArgumentException
{
/**
* @return never
*
* @throws self
*/
public static function expected(string $type): void
{
throw new self(sprintf('Invalid expectation value type. Expected [%s].', $type));
}
}

View File

@ -9,7 +9,7 @@ use Closure;
use InvalidArgumentException; use InvalidArgumentException;
use Pest\Concerns\Extendable; use Pest\Concerns\Extendable;
use Pest\Concerns\RetrievesValues; use Pest\Concerns\RetrievesValues;
use Pest\Exceptions\ExpectationException; use Pest\Exceptions\InvalidExpectationValue;
use Pest\Support\Arr; use Pest\Support\Arr;
use Pest\Support\NullClosure; use Pest\Support\NullClosure;
use PHPUnit\Framework\Assert; use PHPUnit\Framework\Assert;
@ -70,7 +70,7 @@ final class Expectation
public function json(): Expectation public function json(): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('json', 'string'); InvalidExpectationValue::expected('string');
} }
return $this->toBeJson()->and(json_decode($this->value, true)); return $this->toBeJson()->and(json_decode($this->value, true));
@ -360,13 +360,11 @@ final class Expectation
{ {
foreach ($needles as $needle) { foreach ($needles as $needle) {
if (is_string($this->value)) { if (is_string($this->value)) {
if (!is_string($needle)) { // @phpstan-ignore-next-line
throw ExpectationException::invalidExpectedValueType('toContain', 'string'); Assert::assertStringContainsString((string) $needle, $this->value);
}
Assert::assertStringContainsString($needle, $this->value);
} else { } else {
if (!is_iterable($this->value)) { if (!is_iterable($this->value)) {
throw ExpectationException::invalidCurrentValueType('toContain', 'iterable'); InvalidExpectationValue::expected('iterable');
} }
Assert::assertContains($needle, $this->value); Assert::assertContains($needle, $this->value);
} }
@ -383,7 +381,7 @@ final class Expectation
public function toStartWith(string $expected): Expectation public function toStartWith(string $expected): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toStartWith', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertStringStartsWith($expected, $this->value); Assert::assertStringStartsWith($expected, $this->value);
@ -399,7 +397,7 @@ final class Expectation
public function toEndWith(string $expected): Expectation public function toEndWith(string $expected): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toEndWith', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertStringEndsWith($expected, $this->value); Assert::assertStringEndsWith($expected, $this->value);
@ -443,7 +441,7 @@ final class Expectation
public function toHaveCount(int $count): Expectation public function toHaveCount(int $count): Expectation
{ {
if (!is_countable($this->value) && !is_iterable($this->value)) { if (!is_countable($this->value) && !is_iterable($this->value)) {
throw ExpectationException::invalidCurrentValueType('toHaveCount', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertCount($count, $this->value); Assert::assertCount($count, $this->value);
@ -743,7 +741,7 @@ final class Expectation
public function toBeDirectory(): Expectation public function toBeDirectory(): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toBeDirectory', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertDirectoryExists($this->value); Assert::assertDirectoryExists($this->value);
@ -757,7 +755,7 @@ final class Expectation
public function toBeReadableDirectory(): Expectation public function toBeReadableDirectory(): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toBeReadableDirectory', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertDirectoryIsReadable($this->value); Assert::assertDirectoryIsReadable($this->value);
@ -771,7 +769,7 @@ final class Expectation
public function toBeWritableDirectory(): Expectation public function toBeWritableDirectory(): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toBeWritableDirectory', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertDirectoryIsWritable($this->value); Assert::assertDirectoryIsWritable($this->value);
@ -785,7 +783,7 @@ final class Expectation
public function toBeFile(): Expectation public function toBeFile(): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toBeFile', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertFileExists($this->value); Assert::assertFileExists($this->value);
@ -799,8 +797,9 @@ final class Expectation
public function toBeReadableFile(): Expectation public function toBeReadableFile(): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toBeReadableFile', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertFileIsReadable($this->value); Assert::assertFileIsReadable($this->value);
return $this; return $this;
@ -812,7 +811,7 @@ final class Expectation
public function toBeWritableFile(): Expectation public function toBeWritableFile(): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toBeWritableFile', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertFileIsWritable($this->value); Assert::assertFileIsWritable($this->value);
@ -859,8 +858,9 @@ final class Expectation
{ {
foreach ((array) $object as $property => $value) { foreach ((array) $object as $property => $value) {
if (!is_object($this->value) && !is_string($this->value)) { if (!is_object($this->value) && !is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toMatchObject', 'object|string'); InvalidExpectationValue::expected('object|string');
} }
Assert::assertTrue(property_exists($this->value, $property)); Assert::assertTrue(property_exists($this->value, $property));
/* @phpstan-ignore-next-line */ /* @phpstan-ignore-next-line */
@ -885,7 +885,7 @@ final class Expectation
public function toMatch(string $expression): Expectation public function toMatch(string $expression): Expectation
{ {
if (!is_string($this->value)) { if (!is_string($this->value)) {
throw ExpectationException::invalidCurrentValueType('toMatch', 'string'); InvalidExpectationValue::expected('string');
} }
Assert::assertMatchesRegularExpression($expression, $this->value); Assert::assertMatchesRegularExpression($expression, $this->value);

View File

@ -15,11 +15,11 @@ final class Depends
/** /**
* Adds annotations regarding the "depends" feature. * Adds annotations regarding the "depends" feature.
* *
* @param array<string> $annotations * @param array<int, string> $annotations
* *
* @return array<string> * @return array<int, string>
*/ */
public function add(TestCaseMethodFactory $method, array $annotations): array public function __invoke(TestCaseMethodFactory $method, array $annotations): array
{ {
foreach ($method->depends as $depend) { foreach ($method->depends as $depend) {
$depend = Str::evaluable($depend); $depend = Str::evaluable($depend);

View File

@ -14,11 +14,11 @@ final class Groups
/** /**
* Adds annotations regarding the "groups" feature. * Adds annotations regarding the "groups" feature.
* *
* @param array<string> $annotations * @param array<int, string> $annotations
* *
* @return array<string> * @return array<int, string>
*/ */
public function add(TestCaseMethodFactory $method, array $annotations): array public function __invoke(TestCaseMethodFactory $method, array $annotations): array
{ {
foreach ($method->groups as $group) { foreach ($method->groups as $group) {
$annotations[] = "@group $group"; $annotations[] = "@group $group";

View File

@ -73,9 +73,9 @@ final class TestCaseFactory
{ {
$methodsUsingOnly = $this->methodsUsingOnly(); $methodsUsingOnly = $this->methodsUsingOnly();
$methods = array_filter($this->methods, function ($method) use ($methodsUsingOnly) { $methods = array_values(array_filter($this->methods, function ($method) use ($methodsUsingOnly) {
return count($methodsUsingOnly) === 0 || in_array($method, $methodsUsingOnly, true); return count($methodsUsingOnly) === 0 || in_array($method, $methodsUsingOnly, true);
}); }));
if (count($methods) > 0) { if (count($methods) > 0) {
$this->evaluate($this->filename, $methods); $this->evaluate($this->filename, $methods);
@ -99,7 +99,7 @@ final class TestCaseFactory
/** /**
* Creates a Test Case class using a runtime evaluate. * Creates a Test Case class using a runtime evaluate.
* *
* @param array<TestCaseMethodFactory> $methods * @param array<int, TestCaseMethodFactory> $methods
*/ */
public function evaluate(string $filename, array $methods): string public function evaluate(string $filename, array $methods): string
{ {
@ -152,8 +152,8 @@ final class TestCaseFactory
$annotations = ['@test']; $annotations = ['@test'];
foreach (self::$annotations as $annotation) { foreach (self::$annotations as $annotation) {
//@phpstan-ignore-next-line /** @phpstan-ignore-next-line */
$annotations = (new $annotation())->add($method, $annotations); $annotations = (new $annotation())->__invoke($method, $annotations);
} }
if (count($method->datasets) > 0) { if (count($method->datasets) > 0) {

View File

@ -89,7 +89,7 @@ final class TestCaseMethodFactory
$testCase->chains->chain($this); $testCase->chains->chain($this);
$method->chains->chain($this); $method->chains->chain($this);
return \Pest\Support\Closure::safeBind($closure, $this, $this::class)(...func_get_args()); return \Pest\Support\Closure::bind($closure, $this, $this::class)(...func_get_args());
}; };
} }

View File

@ -77,7 +77,7 @@ if (!function_exists('uses')) {
{ {
$filename = Backtrace::file(); $filename = Backtrace::file();
return new UsesCall($filename, $classAndTraits); return new UsesCall($filename, array_values($classAndTraits));
} }
} }

View File

@ -36,14 +36,14 @@ final class UsesCall
/** /**
* Holds the groups of the uses. * Holds the groups of the uses.
* *
* @var array<string> * @var array<int, string>
*/ */
private array $groups = []; private array $groups = [];
/** /**
* Creates a new Pending Call. * Creates a new Pending Call.
* *
* @param array<string> $classAndTraits * @param array<int, string> $classAndTraits
*/ */
public function __construct( public function __construct(
private string $filename, private string $filename,
@ -89,7 +89,7 @@ final class UsesCall
*/ */
public function group(string ...$groups): UsesCall public function group(string ...$groups): UsesCall
{ {
$this->groups = $groups; $this->groups = array_values($groups);
return $this; return $this;
} }

View File

@ -80,10 +80,10 @@ final class Coverage implements AddsOutput, HandlesArguments
} }
if ($input->getOption(self::MIN_OPTION) !== null) { if ($input->getOption(self::MIN_OPTION) !== null) {
/** @var int|float $min_option */ /** @var int|float $minOption */
$min_option = $input->getOption(self::MIN_OPTION); $minOption = $input->getOption(self::MIN_OPTION);
$this->coverageMin = (float) $min_option; $this->coverageMin = (float) $minOption;
} }
return $originals; return $originals;

View File

@ -12,7 +12,7 @@ final class Arr
/** /**
* Checks if the given array has the given key. * Checks if the given array has the given key.
* *
* @param array<mixed> $array * @param array<array-key, mixed> $array
*/ */
public static function has(array $array, string|int $key): bool public static function has(array $array, string|int $key): bool
{ {
@ -36,7 +36,7 @@ final class Arr
/** /**
* Gets the given key value. * Gets the given key value.
* *
* @param array<mixed> $array * @param array<array-key, mixed> $array
*/ */
public static function get(array $array, string|int $key, mixed $default = null): mixed public static function get(array $array, string|int $key, mixed $default = null): mixed
{ {

View File

@ -22,8 +22,8 @@ final class ChainableClosure
throw ShouldNotHappen::fromMessage('$this not bound to chainable closure.'); throw ShouldNotHappen::fromMessage('$this not bound to chainable closure.');
} }
\Pest\Support\Closure::safeBind($closure, $this, $this::class)(...func_get_args()); \Pest\Support\Closure::bind($closure, $this, $this::class)(...func_get_args());
\Pest\Support\Closure::safeBind($next, $this, $this::class)(...func_get_args()); \Pest\Support\Closure::bind($next, $this, $this::class)(...func_get_args());
}; };
} }
@ -33,8 +33,8 @@ final class ChainableClosure
public static function fromStatic(Closure $closure, Closure $next): Closure public static function fromStatic(Closure $closure, Closure $next): Closure
{ {
return static function () use ($closure, $next): void { return static function () use ($closure, $next): void {
\Pest\Support\Closure::safeBind($closure, null, self::class)(...func_get_args()); \Pest\Support\Closure::bind($closure, null, self::class)(...func_get_args());
\Pest\Support\Closure::safeBind($next, null, self::class)(...func_get_args()); \Pest\Support\Closure::bind($next, null, self::class)(...func_get_args());
}; };
} }
} }

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Pest\Support; namespace Pest\Support;
use Closure as BaseClosure;
use Pest\Exceptions\ShouldNotHappen; use Pest\Exceptions\ShouldNotHappen;
/** /**
@ -11,13 +12,20 @@ use Pest\Exceptions\ShouldNotHappen;
*/ */
final class Closure final class Closure
{ {
public static function safeBind(\Closure|null $closure, ?object $newThis, object|string|null $newScope = 'static'): \Closure /**
* Binds the given closure to the given "this".
*
* @return BaseClosure|never
*
* @throws ShouldNotHappen
*/
public static function bind(BaseClosure|null $closure, ?object $newThis, object|string|null $newScope = 'static'): BaseClosure
{ {
if ($closure == null) { if ($closure == null) {
throw ShouldNotHappen::fromMessage('Could not bind null closure.'); throw ShouldNotHappen::fromMessage('Could not bind null closure.');
} }
$closure = \Closure::bind($closure, $newThis, $newScope); $closure = BaseClosure::bind($closure, $newThis, $newScope);
if ($closure == false) { if ($closure == false) {
throw ShouldNotHappen::fromMessage('Could not bind closure.'); throw ShouldNotHappen::fromMessage('Could not bind closure.');

View File

@ -51,7 +51,7 @@ final class ExceptionTrace
$property = new ReflectionProperty($t, 'serializableTrace'); $property = new ReflectionProperty($t, 'serializableTrace');
$property->setAccessible(true); $property->setAccessible(true);
/** @var array<array<string>> $trace */ /** @var array<int, array<string, string>> $trace */
$trace = $property->getValue($t); $trace = $property->getValue($t);
$cleanedTrace = []; $cleanedTrace = [];

View File

@ -25,7 +25,7 @@ final class HigherOrderCallables
* *
* Create a new expectation. Callable values will be executed prior to returning the new expectation. * Create a new expectation. Callable values will be executed prior to returning the new expectation.
* *
* @param (callable():TValue)|TValue $value * @param (Closure():TValue)|TValue $value
* *
* @return Expectation<TValue> * @return Expectation<TValue>
*/ */