Skip to content

Commit b32cebd

Browse files
authored
Improve assert rule (#7207)
* add ASSERT set list * add fixture to cover float and bool types
1 parent 5226e84 commit b32cebd

4 files changed

Lines changed: 89 additions & 12 deletions

File tree

config/set/assert.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Assert\Rector\ClassMethod\AddAssertArrayFromClassMethodDocblockRector;
6+
use Rector\Config\RectorConfig;
7+
8+
return static function (RectorConfig $rectorConfig): void {
9+
$rectorConfig->rules([AddAssertArrayFromClassMethodDocblockRector::class]);
10+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Rector\Tests\Assert\Rector\ClassMethod\AddAssertArrayFromClassMethodDocblockRector\Fixture;
4+
5+
final class FloatIntBool
6+
{
7+
/**
8+
* @param int[] $items
9+
* @param float[] $numbers
10+
* @param bool[] $options
11+
*/
12+
public function run(array $items, array $numbers, array $options)
13+
{
14+
}
15+
}
16+
17+
?>
18+
-----
19+
<?php
20+
21+
namespace Rector\Tests\Assert\Rector\ClassMethod\AddAssertArrayFromClassMethodDocblockRector\Fixture;
22+
23+
final class FloatIntBool
24+
{
25+
/**
26+
* @param int[] $items
27+
* @param float[] $numbers
28+
* @param bool[] $options
29+
*/
30+
public function run(array $items, array $numbers, array $options)
31+
{
32+
\Webmozart\Assert\Assert::allInteger($items);
33+
\Webmozart\Assert\Assert::allFloat($numbers);
34+
\Webmozart\Assert\Assert::allBoolean($options);
35+
}
36+
}
37+
38+
?>

rules/Assert/Rector/ClassMethod/AddAssertArrayFromClassMethodDocblockRector.php

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,24 @@
44

55
namespace Rector\Assert\Rector\ClassMethod;
66

7-
use PhpParser\Node\Expr\Variable;
87
use PhpParser\Node;
98
use PhpParser\Node\Arg;
109
use PhpParser\Node\Expr;
1110
use PhpParser\Node\Expr\FuncCall;
1211
use PhpParser\Node\Expr\StaticCall;
12+
use PhpParser\Node\Expr\Variable;
1313
use PhpParser\Node\Identifier;
1414
use PhpParser\Node\Name;
1515
use PhpParser\Node\Name\FullyQualified;
1616
use PhpParser\Node\Stmt\ClassMethod;
1717
use PhpParser\Node\Stmt\Expression;
1818
use PhpParser\PrettyPrinter\Standard;
1919
use PHPStan\Type\ArrayType;
20+
use PHPStan\Type\BooleanType;
21+
use PHPStan\Type\FloatType;
2022
use PHPStan\Type\IntegerType;
2123
use PHPStan\Type\StringType;
24+
use PHPStan\Type\Type;
2225
use Rector\Assert\Enum\AssertClassName;
2326
use Rector\Assert\NodeAnalyzer\ExistingAssertStaticCallResolver;
2427
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
@@ -133,19 +136,17 @@ public function refactor(Node $node): ?ClassMethod
133136
continue;
134137
}
135138

136-
// assert value
137-
if ($paramDocType->getItemType() instanceof IntegerType) {
138-
$assertStaticCallStmts[] = $this->createAssertExpression($param->var, 'allInteger');
139-
} elseif ($paramDocType->getItemType() instanceof StringType) {
140-
$assertStaticCallStmts[] = $this->createAssertExpression($param->var, 'allString');
139+
$valueAssertMethod = $this->matchTypeToAssertMethod($paramDocType->getItemType());
140+
141+
if (is_string($valueAssertMethod)) {
142+
$assertStaticCallStmts[] = $this->createAssertExpression($param->var, $valueAssertMethod);
141143
}
142144

143-
// assert keys
144-
$arrayKeys = new FuncCall(new Name('array_keys'), [new Arg($param->var)]);
145-
if ($paramDocType->getKeyType() instanceof StringType) {
146-
$assertStaticCallStmts[] = $this->createAssertExpression($arrayKeys, 'allString');
147-
} elseif ($paramDocType->getKeyType() instanceof IntegerType) {
148-
$assertStaticCallStmts[] = $this->createAssertExpression($arrayKeys, 'allInteger');
145+
$keyAssertMethod = $this->matchTypeToAssertMethod($paramDocType->getKeyType());
146+
147+
if (is_string($keyAssertMethod)) {
148+
$arrayKeys = new FuncCall(new Name('array_keys'), [new Arg($param->var)]);
149+
$assertStaticCallStmts[] = $this->createAssertExpression($arrayKeys, $keyAssertMethod);
149150
}
150151
}
151152

@@ -192,4 +193,25 @@ private function filterOutExistingStaticCall(array $assertStaticCallStmts, array
192193
return ! in_array($currentStaticCallHash, $existingAssertCallHashes, true);
193194
});
194195
}
196+
197+
private function matchTypeToAssertMethod(Type $type): ?string
198+
{
199+
if ($type instanceof IntegerType) {
200+
return 'allInteger';
201+
}
202+
203+
if ($type instanceof StringType) {
204+
return 'allString';
205+
}
206+
207+
if ($type instanceof FloatType) {
208+
return 'allFloat';
209+
}
210+
211+
if ($type instanceof BooleanType) {
212+
return 'allBoolean';
213+
}
214+
215+
return null;
216+
}
195217
}

src/Set/ValueObject/SetList.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,11 @@ final class SetList
161161
* @var string
162162
*/
163163
public const BEHAT_ANNOTATIONS_TO_ATTRIBUTES = __DIR__ . '/../../../config/set/behat-annotations-to-attributes.php';
164+
165+
/**
166+
* @experimental Check generic types in runtime with assert. Generics for impatient people.
167+
*
168+
* @var string
169+
*/
170+
public const ASSERT = __DIR__ . '/../../../config/set/assert.php';
164171
}

0 commit comments

Comments
 (0)