Skip to content

Commit 5b32e12

Browse files
committed
Implement DataProviderDataRule
1 parent c54a269 commit 5b32e12

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
],
88
"require": {
99
"php": "^7.4 || ^8.0",
10-
"phpstan/phpstan": "^2.1.18"
10+
"phpstan/phpstan": "^2.1.32"
1111
},
1212
"conflict": {
1313
"phpunit/phpunit": "<7.0"

rules.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ rules:
88
- PHPStan\Rules\PHPUnit\NoMissingSpaceInClassAnnotationRule
99
- PHPStan\Rules\PHPUnit\NoMissingSpaceInMethodAnnotationRule
1010
- PHPStan\Rules\PHPUnit\ShouldCallParentMethodsRule
11+
- PHPStan\Rules\PHPUnit\DataProviderDataRule
1112

1213
conditionalTags:
1314
PHPStan\Rules\PHPUnit\AssertEqualsIsDiscouragedRule:
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\PHPUnit;
4+
5+
use LogicException;
6+
use PhpParser\Node;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection;
9+
use PHPStan\Rules\Rule;
10+
use PHPUnit\Framework\TestCase;
11+
12+
/**
13+
* @implements Rule<Node\Stmt\Return_>
14+
*/
15+
class DataProviderDataRule implements Rule
16+
{
17+
public function getNodeType(): string
18+
{
19+
return Node\Stmt\Return_::class;
20+
}
21+
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if (!$node->expr instanceof Node\Expr\Array_) {
25+
return [];
26+
}
27+
28+
if ($scope->getFunction() === null) {
29+
return [];
30+
}
31+
32+
if ($scope->isInAnonymousFunction()) {
33+
return [];
34+
}
35+
36+
$method = $scope->getFunction();
37+
if (!$method instanceof PhpMethodFromParserNodeReflection) {
38+
return [];
39+
}
40+
41+
$classReflection = $scope->getClassReflection();
42+
43+
if ($classReflection === null || !$classReflection->is(TestCase::class)) {
44+
return [];
45+
}
46+
47+
// XXX check whether the method is used as a data provider
48+
49+
if (method_exists($scope, 'invokeNodeCallback')) {
50+
foreach($node->expr->items as $item) {
51+
if (!$item->value instanceof Node\Expr\Array_) {
52+
return [];
53+
}
54+
55+
$args = $this->arrayItemsToArgs($item->value);
56+
$var = new Node\Expr\New_(new Node\Name('test'));
57+
$scope->invokeNodeCallback(new Node\Expr\MethodCall($var, 'testTrim', $args));
58+
}
59+
}
60+
61+
return [];
62+
}
63+
64+
/**
65+
* @return array<Node\Arg>
66+
*/
67+
private function arrayItemsToArgs(Node\Expr\Array_ $array): ?array {
68+
$args = [];
69+
70+
foreach($array->items as $item) {
71+
// XXX named args
72+
$value = $item->value;
73+
74+
$arg = new Node\Arg($value);
75+
$args[] = $arg;
76+
}
77+
78+
return $args;
79+
}
80+
81+
}

0 commit comments

Comments
 (0)