From f0c596821d5daa748790539f28bb7d4b943568fc Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 1 Sep 2025 16:06:08 +0200 Subject: [PATCH 1/2] add ASSERT set list --- config/set/assert.php | 12 ++++++++++++ src/Set/ValueObject/SetList.php | 7 +++++++ 2 files changed, 19 insertions(+) create mode 100644 config/set/assert.php diff --git a/config/set/assert.php b/config/set/assert.php new file mode 100644 index 00000000000..ce911c9dccb --- /dev/null +++ b/config/set/assert.php @@ -0,0 +1,12 @@ +rules([ + AddAssertArrayFromClassMethodDocblockRector::class, + ]); +}; diff --git a/src/Set/ValueObject/SetList.php b/src/Set/ValueObject/SetList.php index 4084b417207..b6015410557 100644 --- a/src/Set/ValueObject/SetList.php +++ b/src/Set/ValueObject/SetList.php @@ -161,4 +161,11 @@ final class SetList * @var string */ public const BEHAT_ANNOTATIONS_TO_ATTRIBUTES = __DIR__ . '/../../../config/set/behat-annotations-to-attributes.php'; + + /** + * @experimental Check generic types in runtime with assert. Generics for impatient people. + * + * @var string + */ + public const ASSERT = __DIR__ . '/../../../config/set/assert.php'; } From 3aabf5865a823cd0346ae7f7d7b99beef6f412d1 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 1 Sep 2025 16:07:02 +0200 Subject: [PATCH 2/2] add fixture to cover float and bool types --- config/set/assert.php | 4 +- .../Fixture/float_int_bool.php.inc | 38 +++++++++++++++ ...sertArrayFromClassMethodDocblockRector.php | 46 ++++++++++++++----- 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 rules-tests/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector/Fixture/float_int_bool.php.inc diff --git a/config/set/assert.php b/config/set/assert.php index ce911c9dccb..c98e4dc42d9 100644 --- a/config/set/assert.php +++ b/config/set/assert.php @@ -6,7 +6,5 @@ use Rector\Config\RectorConfig; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([ - AddAssertArrayFromClassMethodDocblockRector::class, - ]); + $rectorConfig->rules([AddAssertArrayFromClassMethodDocblockRector::class]); }; diff --git a/rules-tests/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector/Fixture/float_int_bool.php.inc b/rules-tests/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector/Fixture/float_int_bool.php.inc new file mode 100644 index 00000000000..d7e47c0a078 --- /dev/null +++ b/rules-tests/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector/Fixture/float_int_bool.php.inc @@ -0,0 +1,38 @@ + +----- + diff --git a/rules/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector.php b/rules/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector.php index c4143c794a8..748beb96613 100644 --- a/rules/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector.php +++ b/rules/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector.php @@ -4,12 +4,12 @@ namespace Rector\Assert\Rector\ClassMethod; -use PhpParser\Node\Expr\Variable; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\StaticCall; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; @@ -17,8 +17,11 @@ use PhpParser\Node\Stmt\Expression; use PhpParser\PrettyPrinter\Standard; use PHPStan\Type\ArrayType; +use PHPStan\Type\BooleanType; +use PHPStan\Type\FloatType; use PHPStan\Type\IntegerType; use PHPStan\Type\StringType; +use PHPStan\Type\Type; use Rector\Assert\Enum\AssertClassName; use Rector\Assert\NodeAnalyzer\ExistingAssertStaticCallResolver; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; @@ -133,19 +136,17 @@ public function refactor(Node $node): ?ClassMethod continue; } - // assert value - if ($paramDocType->getItemType() instanceof IntegerType) { - $assertStaticCallStmts[] = $this->createAssertExpression($param->var, 'allInteger'); - } elseif ($paramDocType->getItemType() instanceof StringType) { - $assertStaticCallStmts[] = $this->createAssertExpression($param->var, 'allString'); + $valueAssertMethod = $this->matchTypeToAssertMethod($paramDocType->getItemType()); + + if (is_string($valueAssertMethod)) { + $assertStaticCallStmts[] = $this->createAssertExpression($param->var, $valueAssertMethod); } - // assert keys - $arrayKeys = new FuncCall(new Name('array_keys'), [new Arg($param->var)]); - if ($paramDocType->getKeyType() instanceof StringType) { - $assertStaticCallStmts[] = $this->createAssertExpression($arrayKeys, 'allString'); - } elseif ($paramDocType->getKeyType() instanceof IntegerType) { - $assertStaticCallStmts[] = $this->createAssertExpression($arrayKeys, 'allInteger'); + $keyAssertMethod = $this->matchTypeToAssertMethod($paramDocType->getKeyType()); + + if (is_string($keyAssertMethod)) { + $arrayKeys = new FuncCall(new Name('array_keys'), [new Arg($param->var)]); + $assertStaticCallStmts[] = $this->createAssertExpression($arrayKeys, $keyAssertMethod); } } @@ -192,4 +193,25 @@ private function filterOutExistingStaticCall(array $assertStaticCallStmts, array return ! in_array($currentStaticCallHash, $existingAssertCallHashes, true); }); } + + private function matchTypeToAssertMethod(Type $type): ?string + { + if ($type instanceof IntegerType) { + return 'allInteger'; + } + + if ($type instanceof StringType) { + return 'allString'; + } + + if ($type instanceof FloatType) { + return 'allFloat'; + } + + if ($type instanceof BooleanType) { + return 'allBoolean'; + } + + return null; + } }