chore: adjusts to new types on arch

This commit is contained in:
Nuno Maduro
2025-03-30 18:42:00 +01:00
parent 2e11e9e65d
commit 0171617c1d
3 changed files with 118 additions and 31 deletions

View File

@ -24,7 +24,7 @@ final readonly class Thanks
*/
private const FUNDING_MESSAGES = [
'Star' => 'https://github.com/pestphp/pest',
'News' => 'https://twitter.com/pestphp',
'News' => 'https://x.com/enunomaduro',
'Videos' => 'https://youtube.com/@nunomaduro',
'Sponsor' => 'https://github.com/sponsors/nunomaduro',
];

View File

@ -74,7 +74,10 @@ final readonly class OppositeExpectation
*/
public function toUse(array|string $targets): ArchExpectation
{
return GroupArchExpectation::fromExpectations($this->original, array_map(fn (string $target): SingleArchExpectation => ToUse::make($this->original, $target)->opposite(
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return GroupArchExpectation::fromExpectations($original, array_map(fn (string $target): SingleArchExpectation => ToUse::make($original, $target)->opposite(
fn () => $this->throwExpectationFailedException('toUse', $target),
), is_string($targets) ? [$targets] : $targets));
}
@ -84,8 +87,11 @@ final readonly class OppositeExpectation
*/
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => substr(sprintf('%o', fileperms($object->path)), -4) !== $permissions,
sprintf('permissions not to be [%s]', $permissions),
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
@ -105,8 +111,11 @@ final readonly class OppositeExpectation
*/
public function toHaveMethodsDocumented(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|| array_filter(
Reflection::getMethodsFromReflectionClass($object->reflectionClass),
@ -124,8 +133,11 @@ final readonly class OppositeExpectation
*/
public function toHavePropertiesDocumented(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|| array_filter(
Reflection::getPropertiesFromReflectionClass($object->reflectionClass),
@ -144,8 +156,11 @@ final readonly class OppositeExpectation
*/
public function toUseStrictTypes(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! (bool) preg_match('/^<\?php\s+declare\(.*?strict_types\s?=\s?1.*?\);/', (string) file_get_contents($object->path)),
'not to use strict types',
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
@ -157,8 +172,11 @@ final readonly class OppositeExpectation
*/
public function toUseStrictEquality(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), ' === ') && ! str_contains((string) file_get_contents($object->path), ' !== '),
'to use strict equality',
FileLineFinder::where(fn (string $line): bool => str_contains($line, ' === ') || str_contains($line, ' !== ')),
@ -170,8 +188,11 @@ final readonly class OppositeExpectation
*/
public function toBeFinal(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && ! $object->reflectionClass->isFinal(),
'not to be final',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -183,8 +204,11 @@ final readonly class OppositeExpectation
*/
public function toBeReadonly(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && ! $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line
'not to be readonly',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -196,8 +220,11 @@ final readonly class OppositeExpectation
*/
public function toBeTrait(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(),
'not to be trait',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -217,8 +244,11 @@ final readonly class OppositeExpectation
*/
public function toBeAbstract(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(),
'not to be abstract',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -234,8 +264,11 @@ final readonly class OppositeExpectation
{
$methods = is_array($method) ? $method : [$method];
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => array_filter(
$methods,
fn (string $method): bool => $object->reflectionClass->hasMethod($method),
@ -266,8 +299,11 @@ final readonly class OppositeExpectation
$state = new stdClass;
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
function (ObjectDescription $object) use ($methods, &$state): bool {
$reflectionMethods = isset($object->reflectionClass)
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PUBLIC)
@ -309,8 +345,11 @@ final readonly class OppositeExpectation
$state = new stdClass;
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
function (ObjectDescription $object) use ($methods, &$state): bool {
$reflectionMethods = isset($object->reflectionClass)
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PROTECTED)
@ -352,8 +391,11 @@ final readonly class OppositeExpectation
$state = new stdClass;
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
function (ObjectDescription $object) use ($methods, &$state): bool {
$reflectionMethods = isset($object->reflectionClass)
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PRIVATE)
@ -389,8 +431,11 @@ final readonly class OppositeExpectation
*/
public function toBeEnum(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(),
'not to be enum',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -410,8 +455,11 @@ final readonly class OppositeExpectation
*/
public function toBeClass(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! class_exists($object->name),
'not to be class',
FileLineFinder::where(fn (string $line): bool => true),
@ -431,8 +479,11 @@ final readonly class OppositeExpectation
*/
public function toBeInterface(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(),
'not to be interface',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -452,8 +503,11 @@ final readonly class OppositeExpectation
*/
public function toExtend(string $class): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isSubclassOf($class),
sprintf("not to extend '%s'", $class),
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -465,8 +519,11 @@ final readonly class OppositeExpectation
*/
public function toExtendNothing(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() !== false,
'to extend a class',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -490,8 +547,11 @@ final readonly class OppositeExpectation
{
$traits = is_array($traits) ? $traits : [$traits];
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
function (ObjectDescription $object) use ($traits): bool {
foreach ($traits as $trait) {
if (in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
@ -515,8 +575,11 @@ final readonly class OppositeExpectation
{
$interfaces = is_array($interfaces) ? $interfaces : [$interfaces];
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
function (ObjectDescription $object) use ($interfaces): bool {
foreach ($interfaces as $interface) {
if ($object->reflectionClass->implementsInterface($interface)) {
@ -536,8 +599,11 @@ final readonly class OppositeExpectation
*/
public function toImplementNothing(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [],
'to implement an interface',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -557,8 +623,11 @@ final readonly class OppositeExpectation
*/
public function toHavePrefix(string $prefix): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! str_starts_with($object->reflectionClass->getShortName(), $prefix),
"not to have prefix '{$prefix}'",
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -570,8 +639,11 @@ final readonly class OppositeExpectation
*/
public function toHaveSuffix(string $suffix): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! str_ends_with($object->reflectionClass->getName(), $suffix),
"not to have suffix '{$suffix}'",
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -599,7 +671,10 @@ final readonly class OppositeExpectation
*/
public function toBeUsed(): ArchExpectation
{
return ToBeUsedInNothing::make($this->original);
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return ToBeUsedInNothing::make($original);
}
/**
@ -609,7 +684,10 @@ final readonly class OppositeExpectation
*/
public function toBeUsedIn(array|string $targets): ArchExpectation
{
return GroupArchExpectation::fromExpectations($this->original, array_map(fn (string $target): GroupArchExpectation => ToBeUsedIn::make($this->original, $target)->opposite(
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return GroupArchExpectation::fromExpectations($original, array_map(fn (string $target): GroupArchExpectation => ToBeUsedIn::make($original, $target)->opposite(
fn () => $this->throwExpectationFailedException('toBeUsedIn', $target),
), is_string($targets) ? [$targets] : $targets));
}
@ -632,8 +710,11 @@ final readonly class OppositeExpectation
*/
public function toBeInvokable(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->hasMethod('__invoke'),
'to not be invokable',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
@ -645,8 +726,11 @@ final readonly class OppositeExpectation
*/
public function toHaveAttribute(string $attribute): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) === [],
"to not have attribute '{$attribute}'",
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
@ -737,8 +821,11 @@ final readonly class OppositeExpectation
*/
private function toBeBackedEnum(string $backingType): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
$original = $this->original;
return Targeted::make(
$this->original,
$original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum()
|| ! (new \ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
|| (string) (new \ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line