From 722c1ed9d7c968c322980a751043ec10b31bf752 Mon Sep 17 00:00:00 2001 From: Emil Masiakowski Date: Tue, 30 Sep 2025 22:19:04 +0200 Subject: [PATCH 1/4] Support propertyExists --- src/Type/BeberleiAssert/AssertHelper.php | 4 ++++ tests/Type/BeberleiAssert/data/data.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/Type/BeberleiAssert/AssertHelper.php b/src/Type/BeberleiAssert/AssertHelper.php index f3f73a3..98685da 100644 --- a/src/Type/BeberleiAssert/AssertHelper.php +++ b/src/Type/BeberleiAssert/AssertHelper.php @@ -393,6 +393,10 @@ private static function getExpressionResolvers(): array [$key, $array], ), ), + 'propertyExists' => static fn (Scope $scope, Arg $object, Arg $property): Expr => new FuncCall( + new Name('property_exists'), + [$object, $property], + ), 'notBlank' => static fn (Scope $scope, Arg $value): Expr => new BooleanAnd( new BooleanAnd( new NotIdentical( diff --git a/tests/Type/BeberleiAssert/data/data.php b/tests/Type/BeberleiAssert/data/data.php index 57cf656..ee1232b 100644 --- a/tests/Type/BeberleiAssert/data/data.php +++ b/tests/Type/BeberleiAssert/data/data.php @@ -41,6 +41,9 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k, Assertion::objectOrClass($j); \PHPStan\Testing\assertType('object', $j); + Assertion::propertyExists($j, 'foo'); + \PHPStan\Testing\assertType('object&hasProperty(foo)', $j); + Assertion::isResource($k); \PHPStan\Testing\assertType('resource', $k); From b4df461555cfb0dccdc6e0d276647165f7c240fa Mon Sep 17 00:00:00 2001 From: Emil Masiakowski Date: Wed, 1 Oct 2025 13:26:34 +0200 Subject: [PATCH 2/4] Support `methodExists` --- src/Type/BeberleiAssert/AssertHelper.php | 4 ++++ tests/Type/BeberleiAssert/data/data.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/Type/BeberleiAssert/AssertHelper.php b/src/Type/BeberleiAssert/AssertHelper.php index 98685da..a403b68 100644 --- a/src/Type/BeberleiAssert/AssertHelper.php +++ b/src/Type/BeberleiAssert/AssertHelper.php @@ -397,6 +397,10 @@ private static function getExpressionResolvers(): array new Name('property_exists'), [$object, $property], ), + 'methodExists' => static fn (Scope $scope, Arg $object, Arg $property): Expr => new FuncCall( + new Name('method_exists'), + [$object, $property], + ), 'notBlank' => static fn (Scope $scope, Arg $value): Expr => new BooleanAnd( new BooleanAnd( new NotIdentical( diff --git a/tests/Type/BeberleiAssert/data/data.php b/tests/Type/BeberleiAssert/data/data.php index ee1232b..8b2e8a6 100644 --- a/tests/Type/BeberleiAssert/data/data.php +++ b/tests/Type/BeberleiAssert/data/data.php @@ -44,6 +44,9 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k, Assertion::propertyExists($j, 'foo'); \PHPStan\Testing\assertType('object&hasProperty(foo)', $j); + Assertion::methodExists($j, 'doBar'); + \PHPStan\Testing\assertType('object&hasMethod(doBar)&hasProperty(foo)', $j); + Assertion::isResource($k); \PHPStan\Testing\assertType('resource', $k); From d089af9d51f7d8779db5a308ee67a1eda37d9d0d Mon Sep 17 00:00:00 2001 From: Emil Masiakowski Date: Wed, 1 Oct 2025 13:39:51 +0200 Subject: [PATCH 3/4] Support `classExists` and `interfaceExists` --- src/Type/BeberleiAssert/AssertHelper.php | 8 ++++++++ tests/Type/BeberleiAssert/data/data.php | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/Type/BeberleiAssert/AssertHelper.php b/src/Type/BeberleiAssert/AssertHelper.php index a403b68..40caf40 100644 --- a/src/Type/BeberleiAssert/AssertHelper.php +++ b/src/Type/BeberleiAssert/AssertHelper.php @@ -401,6 +401,14 @@ private static function getExpressionResolvers(): array new Name('method_exists'), [$object, $property], ), + 'classExists' => static fn (Scope $scope, Arg $value): Expr => new FuncCall( + new Name('class_exists'), + [$value], + ), + 'interfaceExists' => static fn (Scope $scope, Arg $value): Expr => new FuncCall( + new Name('interface_exists'), + [$value], + ), 'notBlank' => static fn (Scope $scope, Arg $value): Expr => new BooleanAnd( new BooleanAnd( new NotIdentical( diff --git a/tests/Type/BeberleiAssert/data/data.php b/tests/Type/BeberleiAssert/data/data.php index 8b2e8a6..a38ae8a 100644 --- a/tests/Type/BeberleiAssert/data/data.php +++ b/tests/Type/BeberleiAssert/data/data.php @@ -47,6 +47,16 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k, Assertion::methodExists($j, 'doBar'); \PHPStan\Testing\assertType('object&hasMethod(doBar)&hasProperty(foo)', $j); + /** @var string $classString */ + $classString = doFoo(); + Assertion::classExists($classString); + \PHPStan\Testing\assertType('class-string', $classString); + + /** @var string $interfaceString */ + $interfaceString = doFoo(); + Assertion::interfaceExists($interfaceString); + \PHPStan\Testing\assertType('class-string', $interfaceString); + Assertion::isResource($k); \PHPStan\Testing\assertType('resource', $k); From bc11222e6399d5ee18219b26d169d20aafa61dc6 Mon Sep 17 00:00:00 2001 From: Emil Masiakowski Date: Wed, 1 Oct 2025 13:42:13 +0200 Subject: [PATCH 4/4] Fix parameter name --- src/Type/BeberleiAssert/AssertHelper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Type/BeberleiAssert/AssertHelper.php b/src/Type/BeberleiAssert/AssertHelper.php index 40caf40..49e34e2 100644 --- a/src/Type/BeberleiAssert/AssertHelper.php +++ b/src/Type/BeberleiAssert/AssertHelper.php @@ -397,9 +397,9 @@ private static function getExpressionResolvers(): array new Name('property_exists'), [$object, $property], ), - 'methodExists' => static fn (Scope $scope, Arg $object, Arg $property): Expr => new FuncCall( + 'methodExists' => static fn (Scope $scope, Arg $object, Arg $method): Expr => new FuncCall( new Name('method_exists'), - [$object, $property], + [$object, $method], ), 'classExists' => static fn (Scope $scope, Arg $value): Expr => new FuncCall( new Name('class_exists'),