|
2 | 2 |
|
3 | 3 | namespace PHPStan\Rules\PHPUnit; |
4 | 4 |
|
| 5 | +use PhpParser\Modifiers; |
5 | 6 | use PhpParser\Node\Attribute; |
6 | 7 | use PhpParser\Node\Expr\ClassConstFetch; |
7 | 8 | use PhpParser\Node\Name; |
8 | 9 | use PhpParser\Node\Scalar\String_; |
9 | 10 | use PhpParser\Node\Stmt\ClassMethod; |
| 11 | +use PhpParser\NodeFinder; |
10 | 12 | use PHPStan\Analyser\Scope; |
| 13 | +use PHPStan\Parser\Parser; |
11 | 14 | use PHPStan\PhpDoc\ResolvedPhpDocBlock; |
12 | 15 | use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode; |
13 | 16 | use PHPStan\Reflection\ClassReflection; |
@@ -37,16 +40,20 @@ class DataProviderHelper |
37 | 40 | */ |
38 | 41 | private FileTypeMapper $fileTypeMapper; |
39 | 42 |
|
| 43 | + private Parser $parser; |
| 44 | + |
40 | 45 | private bool $phpunit10OrNewer; |
41 | 46 |
|
42 | 47 | public function __construct( |
43 | 48 | ReflectionProvider $reflectionProvider, |
44 | 49 | FileTypeMapper $fileTypeMapper, |
| 50 | + Parser $parser, |
45 | 51 | bool $phpunit10OrNewer |
46 | 52 | ) |
47 | 53 | { |
48 | 54 | $this->reflectionProvider = $reflectionProvider; |
49 | 55 | $this->fileTypeMapper = $fileTypeMapper; |
| 56 | + $this->parser = $parser; |
50 | 57 | $this->phpunit10OrNewer = $phpunit10OrNewer; |
51 | 58 | } |
52 | 59 |
|
@@ -188,13 +195,28 @@ public function processDataProvider( |
188 | 195 | } |
189 | 196 |
|
190 | 197 | if ($deprecationRulesInstalled && $this->phpunit10OrNewer && !$dataProviderMethodReflection->isStatic()) { |
191 | | - $errors[] = RuleErrorBuilder::message(sprintf( |
| 198 | + $errorBuilder = RuleErrorBuilder::message(sprintf( |
192 | 199 | '@dataProvider %s related method must be static in PHPUnit 10 and newer.', |
193 | 200 | $dataProviderValue, |
194 | 201 | )) |
195 | 202 | ->line($lineNumber) |
196 | | - ->identifier('phpunit.dataProviderStatic') |
197 | | - ->build(); |
| 203 | + ->identifier('phpunit.dataProviderStatic'); |
| 204 | + |
| 205 | + $dataProviderMethodReflectionDeclaringClass = $dataProviderMethodReflection->getDeclaringClass(); |
| 206 | + if ($dataProviderMethodReflectionDeclaringClass->getFileName() !== null) { |
| 207 | + $stmts = $this->parser->parseFile($dataProviderMethodReflectionDeclaringClass->getFileName()); |
| 208 | + $nodeFinder = new NodeFinder(); |
| 209 | + /** @var ClassMethod|null $methodNode */ |
| 210 | + $methodNode = $nodeFinder->findFirst($stmts, static fn ($node) => $node instanceof ClassMethod && $node->name->toString() === $dataProviderMethodReflection->getName()); |
| 211 | + if ($methodNode !== null) { |
| 212 | + $errorBuilder->fixNode($methodNode, static function (ClassMethod $methodNode) { |
| 213 | + $methodNode->flags |= Modifiers::STATIC; |
| 214 | + |
| 215 | + return $methodNode; |
| 216 | + }); |
| 217 | + } |
| 218 | + } |
| 219 | + $errors[] = $errorBuilder->build(); |
198 | 220 | } |
199 | 221 |
|
200 | 222 | return $errors; |
|
0 commit comments