First Commit

This commit is contained in:
Esteban
2026-07-03 16:27:34 +02:00
commit 7a7440daab
8955 changed files with 1117958 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/comparator.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Comparator;
use function assert;
use function spl_object_id;
use function sprintf;
use Closure;
use ReflectionFunction;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for sebastian/comparator
*
* @internal This class is not covered by the backward compatibility promise for sebastian/comparator
*/
final class ClosureComparator extends Comparator
{
public function accepts(mixed $expected, mixed $actual): bool
{
return $expected instanceof Closure && $actual instanceof Closure;
}
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void
{
assert($expected instanceof Closure);
assert($actual instanceof Closure);
if ($expected === $actual) {
return;
}
$expectedReflector = new ReflectionFunction($expected);
$actualReflector = new ReflectionFunction($actual);
if ($this->declarationIsEqual($expectedReflector, $actualReflector) &&
$this->bindingIsEqual($expectedReflector, $actualReflector) &&
$this->capturedStateIsEqual($expectedReflector, $actualReflector)) {
return;
}
$expectedFilename = $expectedReflector->getFileName();
$expectedStartLine = $expectedReflector->getStartLine();
$actualFilename = $actualReflector->getFileName();
$actualStartLine = $actualReflector->getStartLine();
assert($expectedFilename !== false);
assert($expectedStartLine !== false);
assert($actualFilename !== false);
assert($actualStartLine !== false);
throw new ComparisonFailure(
$expected,
$actual,
'Closure Object #' . spl_object_id($expected) . ' ()',
'Closure Object #' . spl_object_id($actual) . ' ()',
sprintf(
'Failed asserting that closure declared at %s:%d is equal to closure declared at %s:%d.',
$expectedFilename,
$expectedStartLine,
$actualFilename,
$actualStartLine,
),
);
}
private function declarationIsEqual(ReflectionFunction $expected, ReflectionFunction $actual): bool
{
return $expected->getName() === $actual->getName() &&
$expected->getFileName() === $actual->getFileName() &&
$expected->getStartLine() === $actual->getStartLine() &&
$expected->getEndLine() === $actual->getEndLine();
}
private function bindingIsEqual(ReflectionFunction $expected, ReflectionFunction $actual): bool
{
if ($expected->getClosureScopeClass()?->getName() !== $actual->getClosureScopeClass()?->getName()) {
return false;
}
return $this->recursivelyEqual(
$expected->getClosureThis(),
$actual->getClosureThis(),
);
}
private function capturedStateIsEqual(ReflectionFunction $expected, ReflectionFunction $actual): bool
{
return $this->recursivelyEqual(
$expected->getClosureUsedVariables(),
$actual->getClosureUsedVariables(),
);
}
private function recursivelyEqual(mixed $expected, mixed $actual): bool
{
try {
$this->factory()->getComparatorFor($expected, $actual)->assertEquals($expected, $actual);
} catch (ComparisonFailure) {
return false;
}
return true;
}
}