-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add FixturesAnnotationToAttributeRector Rector rule
- Loading branch information
Ondřej Ešler
committed
Sep 15, 2024
1 parent
fd966a4
commit d7088a0
Showing
2 changed files
with
123 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace IW\PHPUnit\DbFixtures; | ||
|
||
use Nette\Utils\Json; | ||
use PhpParser\Node; | ||
use PhpParser\Node\Stmt\ClassMethod; | ||
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode; | ||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode; | ||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; | ||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; | ||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover; | ||
use Rector\Comments\NodeDocBlock\DocBlockUpdater; | ||
use Rector\PhpAttribute\NodeFactory\PhpAttributeGroupFactory; | ||
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer; | ||
use Rector\Rector\AbstractRector; | ||
use Rector\ValueObject\PhpVersionFeature; | ||
use Rector\VersionBonding\Contract\MinPhpVersionInterface; | ||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; | ||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; | ||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode; | ||
|
||
final class FixturesAnnotationToAttributeRector extends AbstractRector implements MinPhpVersionInterface | ||
{ | ||
public function __construct( | ||
private readonly TestsNodeAnalyzer $testsNodeAnalyzer, | ||
private readonly PhpAttributeGroupFactory $phpAttributeGroupFactory, | ||
private readonly PhpDocTagRemover $phpDocTagRemover, | ||
private readonly DocBlockUpdater $docBlockUpdater, | ||
private readonly PhpDocInfoFactory $phpDocInfoFactory | ||
) { | ||
} | ||
|
||
public function getRuleDefinition(): RuleDefinition | ||
{ | ||
return new RuleDefinition( | ||
'Change @fixtures annotation to #[Fixtures] attribute', | ||
[ | ||
new CodeSample( | ||
<<<'CODE_SAMPLE' | ||
use PHPUnit\Framework\TestCase; | ||
final class SomeFixture extends TestCase | ||
{ | ||
/** | ||
* @fixtures mysql write users.yml jobs.yml | ||
*/ | ||
public function test(): void | ||
{ | ||
} | ||
} | ||
CODE_SAMPLE | ||
, | ||
<<<'CODE_SAMPLE' | ||
use IW\PHPUnit\DbFixtures\Fixtures; | ||
use PHPUnit\Framework\TestCase; | ||
final class SomeFixture extends TestCase | ||
{ | ||
#[Fixtures(['mysql', 'write', 'users.yml', 'jobs.yml'])] | ||
public function test(): void | ||
{ | ||
} | ||
} | ||
CODE_SAMPLE | ||
), | ||
] | ||
); | ||
} | ||
|
||
/** | ||
* @return array<class-string<Node>> | ||
*/ | ||
public function getNodeTypes(): array | ||
{ | ||
return [ClassMethod::class]; | ||
} | ||
|
||
/** | ||
* @param ClassMethod $node | ||
*/ | ||
public function refactor(Node $node): ?Node | ||
{ | ||
if (! $this->testsNodeAnalyzer->isTestClassMethod($node)) { | ||
return null; | ||
} | ||
|
||
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($node); | ||
if (! $phpDocInfo instanceof PhpDocInfo) { | ||
return null; | ||
} | ||
|
||
foreach ($phpDocInfo->getTagsByName('fixtures') as $fixturesPhpDocTagNode) { | ||
/** @var PhpDocTagNode $fixturesPhpDocTagNode */ | ||
if (!$fixturesPhpDocTagNode->value instanceof DoctrineAnnotationTagValueNode) { | ||
continue; // no value | ||
} | ||
|
||
// test from doc blocks | ||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $fixturesPhpDocTagNode); | ||
|
||
// extract attribute params configuration | ||
$fixtures = explode(' ', $fixturesPhpDocTagNode->value->getAttribute('attribute_comment')); | ||
|
||
$attributeGroups[] = $this->phpAttributeGroupFactory | ||
->createFromClassWithItems(Fixtures::class, [$fixtures]); | ||
} | ||
|
||
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); | ||
$node->attrGroups = array_merge($node->attrGroups, $attributeGroups ?? []); | ||
|
||
return $node; | ||
} | ||
|
||
public function provideMinPhpVersion(): int | ||
{ | ||
return PhpVersionFeature::ATTRIBUTES; | ||
} | ||
} |