Skip to content

Commit

Permalink
Fix variadic function as callback
Browse files Browse the repository at this point in the history
  • Loading branch information
kubawerlos authored and sebastianbergmann committed Sep 9, 2024
1 parent f860ec8 commit 18911e5
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .psalm/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@
'arguments_call' => $this->argumentsForCall,
'return_declaration' => !empty($this->returnType->asString()) ? (': ' . $this->returnType->asString()) : '',
'return_type' => $this->returnType->asString(),
'arguments_count' => !empty($this->argumentsForCall) ? substr_count($this->argumentsForCall, ',') + 1 : 0,
'arguments_count' => $argumentsCount,
'class_name' => $this->className,
'method_name' => $this->methodName,
'modifier' => $this->modifier,
Expand Down
22 changes: 21 additions & 1 deletion src/Framework/Constraint/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
namespace PHPUnit\Framework\Constraint;

use ReflectionFunction;

/**
* @psalm-template CallbackInput of mixed
*
Expand Down Expand Up @@ -37,14 +39,32 @@ public function toString(): string
return 'is accepted by specified callback';
}

/**
* @psalm-suppress ArgumentTypeCoercion
*/
public function hasVariadicParam(): bool
{
foreach ((new ReflectionFunction($this->callback))->getParameters() as $parameter) {
if ($parameter->isVariadic()) {
return true;
}
}

return false;
}

/**
* Evaluates the constraint for parameter $value. Returns true if the
* constraint is met, false otherwise.
*
* @psalm-param CallbackInput $other
*
* @psalm-suppress InvalidArgument
*/
protected function matches(mixed $other): bool
{
return ($this->callback)($other);
return $this->hasVariadicParam()
? ($this->callback)(...$other)
: ($this->callback)($other);
}
}
12 changes: 11 additions & 1 deletion src/Framework/MockObject/Generator/MockMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/
namespace PHPUnit\Framework\MockObject\Generator;

use const PHP_INT_MAX;
use function count;
use function explode;
use function implode;
Expand All @@ -17,6 +18,7 @@
use function preg_match;
use function preg_replace;
use function sprintf;
use function str_contains;
use function strlen;
use function strpos;
use function substr;
Expand Down Expand Up @@ -211,13 +213,21 @@ public function generateCode(): string

$template = $this->loadTemplate($templateFile);

$argumentsCount = 0;

if (str_contains($this->argumentsForCall, '...')) {
$argumentsCount = PHP_INT_MAX; // @todo: change it to null and update end-to-end tests
} elseif (!empty($this->argumentsForCall)) {
$argumentsCount = substr_count($this->argumentsForCall, ',') + 1;
}

$template->setVar(
[
'arguments_decl' => $this->argumentsForDeclaration,
'arguments_call' => $this->argumentsForCall,
'return_declaration' => !empty($this->returnType->asString()) ? (': ' . $this->returnType->asString()) : '',
'return_type' => $this->returnType->asString(),
'arguments_count' => !empty($this->argumentsForCall) ? substr_count($this->argumentsForCall, ',') + 1 : 0,
'arguments_count' => $argumentsCount,
'class_name' => $this->className,
'method_name' => $this->methodName,
'modifier' => $this->modifier,
Expand Down
8 changes: 7 additions & 1 deletion src/Framework/MockObject/Runtime/Rule/Parameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use function count;
use function sprintf;
use Exception;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\Constraint\Constraint;
use PHPUnit\Framework\Constraint\IsAnything;
use PHPUnit\Framework\Constraint\IsEqual;
Expand Down Expand Up @@ -108,8 +109,13 @@ private function doVerify(): bool
}

foreach ($this->parameters as $i => $parameter) {
if ($parameter instanceof Callback && $parameter->hasVariadicParam()) {
$other = $this->invocation->parameters();
} else {
$other = $this->invocation->parameters()[$i];
}
$parameter->evaluate(
$this->invocation->parameters()[$i],
$other,
sprintf(
'Parameter %s for invocation %s does not match expected ' .
'value.',
Expand Down

0 comments on commit 18911e5

Please sign in to comment.