Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
rodber committed Jan 3, 2024
1 parent 3666a5a commit 1f46ed5
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use function Chevere\Parameter\float;

#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER | Attribute::TARGET_CLASS_CONSTANT)]
class FloatAttribute implements ParameterAttributeInterface
class FloatAttr implements ParameterAttributeInterface
{
public readonly FloatParameterInterface $parameter;

Expand Down
17 changes: 13 additions & 4 deletions src/Attributes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function intAttr(string $name): IntAttr
return parameterAttr($name, $caller);
}

function floatAttr(string $name): FloatAttribute
function floatAttr(string $name): FloatAttr
{
$caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1];

Expand Down Expand Up @@ -93,10 +93,12 @@ function arrayArguments(string $name): ArgumentsInterface
$arguments = [];
foreach ($parameters->keys() as $named) {
$pos++;
$arguments[$named] = $args[$pos];
$arguments[$named] = match (true) {
array_key_exists($pos, $args) => $args[$pos],
default => $parameters->get($named)->default(),
};
}

// @phpstan-ignore-next-line
return $array->parameters()->__invoke(...$arguments[$name]);
}

Expand All @@ -120,6 +122,9 @@ function valid(?string $name = null): void
$arguments = [];
foreach ($parameters->keys() as $named) {
$pos++;
if (! isset($args[$pos])) {
continue;
}
$arguments[$named] = $args[$pos];
}
if ($name === null) {
Expand All @@ -129,7 +134,11 @@ function valid(?string $name = null): void
}

try {
$parameters->get($name)->__invoke($arguments[$name]);
$parameter = $parameters->get($name);
if ($parameters->optionalKeys()->contains($name) && ! array_key_exists($name, $arguments)) {
return;
}
$parameter->__invoke($arguments[$name]);
} catch (Throwable $e) {
$invoker = $trace[0];

Expand Down
36 changes: 35 additions & 1 deletion src/IterableParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
use Chevere\Parameter\Interfaces\TypeInterface;
use Chevere\Parameter\Traits\ArrayParameterTrait;
use Chevere\Parameter\Traits\ParameterTrait;
use InvalidArgumentException;
use Throwable;
use function Chevere\Message\message;

final class IterableParameter implements IterableParameterInterface
{
Expand Down Expand Up @@ -47,7 +50,38 @@ final public function __construct(
*/
public function __invoke(iterable $value): iterable
{
return assertIterable($this, $value);
if (empty($value)) {
throw new InvalidArgumentException(
(string) message('Argument value provided is empty')
);
}
$iterable = ' *iterable';
$iterableKey = '_K' . $iterable;

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 test on ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = $iterable . '_K'; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 test on ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = $iterable; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 test on ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = '_K'; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 test on ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = $iterable . '_K'; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 test on ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = $iterable; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 test on ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = '_K'; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 test on ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = $iterable . '_K'; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 test on ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = $iterable; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {

Check warning on line 59 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 test on ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new InvalidArgumentException((string) message('Argument value provided is empty')); } $iterable = ' *iterable'; - $iterableKey = '_K' . $iterable; + $iterableKey = '_K'; $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) {
$iterableValue = '_V' . $iterable;

try {
foreach ($value as $k => $v) {
assertNamedArgument($iterableKey, $this->key, $k);

Check warning on line 64 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 test on ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": --- Original +++ New @@ @@ $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) { - assertNamedArgument($iterableKey, $this->key, $k); + assertNamedArgument($iterableValue, $this->value, $v); } } catch (Throwable $e) {

Check warning on line 64 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 test on ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": --- Original +++ New @@ @@ $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) { - assertNamedArgument($iterableKey, $this->key, $k); + assertNamedArgument($iterableValue, $this->value, $v); } } catch (Throwable $e) {

Check warning on line 64 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 test on ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": --- Original +++ New @@ @@ $iterableValue = '_V' . $iterable; try { foreach ($value as $k => $v) { - assertNamedArgument($iterableKey, $this->key, $k); + assertNamedArgument($iterableValue, $this->value, $v); } } catch (Throwable $e) {
assertNamedArgument($iterableValue, $this->value, $v);
}
} catch (Throwable $e) {
$message = $e->getMessage();
$strstr = strstr($message, ':', false);
if (! is_string($strstr)) {
$strstr = $message; // @codeCoverageIgnore
} else {
$strstr = substr($strstr, 2);
}
$calledIn = strpos($strstr, ', called in');

$message = $calledIn
? substr($strstr, 0, $calledIn)

Check warning on line 78 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 test on ubuntu-latest

Escaped Mutant for Mutator "UnwrapSubstr": --- Original +++ New @@ @@ $strstr = substr($strstr, 2); } $calledIn = strpos($strstr, ', called in'); - $message = $calledIn ? substr($strstr, 0, $calledIn) : $strstr; + $message = $calledIn ? $strstr : $strstr; throw new InvalidArgumentException($message); } return $value;

Check warning on line 78 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 test on ubuntu-latest

Escaped Mutant for Mutator "UnwrapSubstr": --- Original +++ New @@ @@ $strstr = substr($strstr, 2); } $calledIn = strpos($strstr, ', called in'); - $message = $calledIn ? substr($strstr, 0, $calledIn) : $strstr; + $message = $calledIn ? $strstr : $strstr; throw new InvalidArgumentException($message); } return $value;

Check warning on line 78 in src/IterableParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 test on ubuntu-latest

Escaped Mutant for Mutator "UnwrapSubstr": --- Original +++ New @@ @@ $strstr = substr($strstr, 2); } $calledIn = strpos($strstr, ', called in'); - $message = $calledIn ? substr($strstr, 0, $calledIn) : $strstr; + $message = $calledIn ? $strstr : $strstr; throw new InvalidArgumentException($message); } return $value;
: $strstr;

throw new InvalidArgumentException($message);
}

return $value;
}

public function default(): ?iterable
Expand Down
18 changes: 16 additions & 2 deletions src/NullParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

use Chevere\Parameter\Interfaces\NullParameterInterface;
use Chevere\Parameter\Interfaces\TypeInterface;
use Chevere\Parameter\Traits\ParameterDefaultNullTrait;
use Chevere\Parameter\Traits\ParameterTrait;
use Chevere\Parameter\Traits\SchemaTrait;
use TypeError;
Expand All @@ -24,9 +23,11 @@
final class NullParameter implements NullParameterInterface
{
use ParameterTrait;
use ParameterDefaultNullTrait;
use SchemaTrait;

// @phpstan-ignore-next-line
private mixed $default;

public function __invoke(mixed $value): mixed
{
if ($value === null) {
Expand All @@ -38,6 +39,19 @@ public function __invoke(mixed $value): mixed
);
}

public function default(): mixed
{
return null;
}

public function withDefault(mixed $null): NullParameterInterface
{
$new = clone $this;

Check warning on line 49 in src/NullParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 test on ubuntu-latest

Escaped Mutant for Mutator "CloneRemoval": --- Original +++ New @@ @@ } public function withDefault(mixed $null) : NullParameterInterface { - $new = clone $this; + $new = $this; $new->default = $null; return $new; }

Check warning on line 49 in src/NullParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 test on ubuntu-latest

Escaped Mutant for Mutator "CloneRemoval": --- Original +++ New @@ @@ } public function withDefault(mixed $null) : NullParameterInterface { - $new = clone $this; + $new = $this; $new->default = $null; return $new; }

Check warning on line 49 in src/NullParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 test on ubuntu-latest

Escaped Mutant for Mutator "CloneRemoval": --- Original +++ New @@ @@ } public function withDefault(mixed $null) : NullParameterInterface { - $new = clone $this; + $new = $this; $new->default = $null; return $new; }
$new->default = $null;

return $new;
}

/**
* @codeCoverageIgnore
*/
Expand Down
22 changes: 0 additions & 22 deletions src/Traits/ParameterDefaultNullTrait.php

This file was deleted.

68 changes: 26 additions & 42 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,45 +133,6 @@ function assertNamedArgument(
}
}

// @phpstan-ignore-next-line
function assertIterable(
IterableParameterInterface $parameter,
iterable $argument,
): iterable {
if (empty($argument)) {
throw new InvalidArgumentException(
(string) message('Argument value provided is empty')
);
}
$iterable = ' *iterable';
$iterableKey = '_K' . $iterable;
$iterableValue = '_V' . $iterable;

try {
foreach ($argument as $key => $value) {
assertNamedArgument($iterableKey, $parameter->key(), $key);
assertNamedArgument($iterableValue, $parameter->value(), $value);
}
} catch (Throwable $e) {
$message = $e->getMessage();
$strstr = strstr($message, ':', false);
if (! is_string($strstr)) {
$strstr = $message; // @codeCoverageIgnore
} else {
$strstr = substr($strstr, 2);
}
$calledIn = strpos($strstr, ', called in');

$message = $calledIn
? substr($strstr, 0, $calledIn)
: $strstr;

throw new InvalidArgumentException($message);
}

return $argument;
}

function toParameter(string $type): ParameterInterface
{
$class = TypeInterface::TYPE_TO_PARAMETER[$type]
Expand Down Expand Up @@ -287,14 +248,37 @@ function reflectionToParameters(ReflectionFunction|ReflectionMethod $reflection)
} catch (LogicException) {
$push = new ReflectionParameterTyped($parameter);
}
$callable = match ($parameter->isOptional()) {
$push = $push->parameter();
if ($parameter->isDefaultValueAvailable()) {
try {
$push = $push->withDefault($parameter->getDefaultValue());
} catch (Throwable $e) {
$name = $parameter->getName();
$class = $parameter->getDeclaringClass()?->getName() ?? null;
$function = $parameter->getDeclaringFunction()->getName();
$caller = match (true) {
$class === null => $function,
default => $class . '::' . $function,
};

throw new InvalidArgumentException(
(string) message(
'Unable to use default value for parameter `%name%` in `%caller%`: %message%',
name: $name,
caller: $caller,
message: $e->getMessage(),
)
);
}
}
$withMethod = match ($parameter->isOptional()) {
true => 'withOptional',
default => 'withRequired',
};

$parameters = $parameters->{$callable}(
$parameters = $parameters->{$withMethod}(
$parameter->getName(),
$push->parameter()
$push
);
}

Expand Down
5 changes: 2 additions & 3 deletions tests/ArgumentsIterableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use function Chevere\Parameter\arrayp;
use function Chevere\Parameter\assertIterable;
use function Chevere\Parameter\int;
use function Chevere\Parameter\iterable;
use function Chevere\Parameter\parameters;
Expand Down Expand Up @@ -194,7 +193,7 @@ public function testIterableArray(array $args): void
K: string()
);
$this->expectNotToPerformAssertions();
assertIterable($parameter, $args);
$parameter($args);
}

/**
Expand All @@ -208,6 +207,6 @@ public function testIterableArrayConflict(array $args): void
);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessageMatches('/^\[_V \*iterable\]\:.*/');
assertIterable($parameter, $args);
$parameter($args);
}
}
18 changes: 14 additions & 4 deletions tests/IterableParameterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use function Chevere\Parameter\arguments;
use function Chevere\Parameter\assertIterable;
use function Chevere\Parameter\int;
use function Chevere\Parameter\iterable;
use function Chevere\Parameter\string;
Expand Down Expand Up @@ -102,7 +101,7 @@ public function testNestedIterable(): void
$argument = [
'a' => 'A',
];
assertIterable($parameter, $argument);
$parameter($argument);
$parameter = iterable(
V: $parameter,
);
Expand All @@ -114,7 +113,7 @@ public function testNestedIterable(): void
'c' => 'C',
],
];
assertIterable($parameter, $argument);
$parameter($argument);
}

public function testIterableArguments(): void
Expand Down Expand Up @@ -151,6 +150,17 @@ public function testInvoke(): void
$parameter = iterable(union(int(), string()));
$parameter($value);
$this->expectException(InvalidArgumentException::class);
$parameter([null, false]);
$parameter([]);
}

public function testWithDefault(): void
{
$value = [10, '10'];
$parameter = iterable(union(int(), string()));
$with = $parameter->withDefault($value);
$this->assertNotSame($parameter, $with);
$this->assertSame($value, $with->default());
$this->expectException(InvalidArgumentException::class);
$parameter->withDefault([null, false]);
}
}
20 changes: 18 additions & 2 deletions tests/src/UsesParameterAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
namespace Chevere\Tests\src;

use Chevere\Parameter\Attributes\ArrayAttr;
use Chevere\Parameter\Attributes\BoolAttr;
use Chevere\Parameter\Attributes\CallableAttr;
use Chevere\Parameter\Attributes\EnumAttr;
use Chevere\Parameter\Attributes\FloatAttr;
use Chevere\Parameter\Attributes\IntAttr;
use Chevere\Parameter\Attributes\IterableAttr;
use Chevere\Parameter\Attributes\NullAttr;
use Chevere\Parameter\Attributes\ReturnAttr;
use Chevere\Parameter\Attributes\StringAttr;
use Chevere\Parameter\Interfaces\ParameterInterface;
Expand All @@ -42,16 +46,28 @@ public function __construct(
#[ArrayAttr(
id: new CallableAttr(__CLASS__ . '::callable'),
)]
array $cols = [],
array $cols = [
'id' => 1,
],
#[IterableAttr(
new StringAttr('/^[A-Za-z]+$/'),
)]
iterable $tags = [],
iterable $tags = ['Chevere', 'Chevere', 'Chevere', 'Uh'],
#[BoolAttr()]
bool $flag = false,
#[FloatAttr(min: 0)]
float $amount = 0,
#[NullAttr()]
mixed $null = null,
#[EnumAttr('test', 'value')]
string $enum = 'value',
) {
valid('name');
valid('age');
valid('cols');
valid('tags');
valid('flag');
valid('amount');
valid();
$name = stringAttr('name')($name);
$age = intAttr('age')($age);
Expand Down

0 comments on commit 1f46ed5

Please sign in to comment.