Skip to content

Commit fa4551c

Browse files
committed
improve add generics annotation to repository to code quality doctrine set
1 parent 105ae61 commit fa4551c

File tree

3 files changed

+33
-25
lines changed

3 files changed

+33
-25
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"phpunit/phpunit": "^11.5",
1818
"rector/rector-src": "dev-main",
1919
"rector/type-perfect": "^2.0",
20-
"symplify/easy-coding-standard": "^12.5",
20+
"phpecs/phpecs": "^2.1",
2121
"symplify/phpstan-rules": "^14.0",
2222
"symplify/vendor-patches": "^11.3",
2323
"tomasvotruba/class-leak": "^2.0",

config/sets/doctrine-code-quality.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
TypedPropertyFromColumnTypeRector::class,
2929
TypedPropertyFromToOneRelationTypeRector::class,
3030
TypedPropertyFromToManyRelationTypeRector::class,
31+
32+
// annotations generics
33+
\Rector\Doctrine\Bundle230\Rector\Class_\AddAnnotationToRepositoryRector::class,
3134
]);
3235

3336
$rectorConfig->ruleWithConfiguration(AttributeKeyToClassConstFetchRector::class, [

rules/Bundle230/Rector/Class_/AddAnnotationToRepositoryRector.php

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44

55
namespace Rector\Doctrine\Bundle230\Rector\Class_;
66

7-
use PhpParser\Node\Name;
8-
use PhpParser\Node\Stmt\ClassMethod;
9-
use PhpParser\Node\Stmt\Expression;
10-
use PhpParser\Node\Expr\StaticCall;
11-
use PhpParser\Node\Identifier;
12-
use PhpParser\Node\Arg;
137
use PhpParser\Node;
8+
use PhpParser\Node\Arg;
149
use PhpParser\Node\Expr\ClassConstFetch;
10+
use PhpParser\Node\Expr\StaticCall;
11+
use PhpParser\Node\Name;
1512
use PhpParser\Node\Stmt\Class_;
13+
use PhpParser\Node\Stmt\ClassMethod;
14+
use PhpParser\Node\Stmt\Expression;
1615
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
1716
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
1817
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
1918
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
19+
use Rector\Doctrine\CodeQuality\Enum\DoctrineClass;
2020
use Rector\Rector\AbstractRector;
2121
use Rector\ValueObject\MethodName;
2222
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
@@ -27,15 +27,19 @@
2727
*/
2828
final class AddAnnotationToRepositoryRector extends AbstractRector
2929
{
30-
public function __construct(private readonly DocBlockUpdater $docBlockUpdater, private readonly PhpDocInfoFactory $phpDocInfoFactory)
31-
{
30+
public function __construct(
31+
private readonly DocBlockUpdater $docBlockUpdater,
32+
private readonly PhpDocInfoFactory $phpDocInfoFactory
33+
) {
3234
}
3335

3436
public function getRuleDefinition(): RuleDefinition
3537
{
3638
return new RuleDefinition('Add @extends ServiceEntityRepository<T> annotation to repository classes', [
3739
new CodeSample(
3840
<<<'CODE_SAMPLE'
41+
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
42+
3943
final class SomeRepository extends ServiceEntityRepository
4044
{
4145
public function __construct(ManagerRegistry $registry)
@@ -46,7 +50,11 @@ public function __construct(ManagerRegistry $registry)
4650
CODE_SAMPLE
4751
,
4852
<<<'CODE_SAMPLE'
49-
/** @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\SomeEntity> */
53+
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
54+
55+
/**
56+
* @extends ServiceEntityRepository<\SomeEntity>
57+
*/
5058
final class SomeRepository extends ServiceEntityRepository
5159
{
5260
public function __construct(ManagerRegistry $registry)
@@ -88,23 +96,21 @@ public function refactor(Node $node): ?Node
8896

8997
private function isRepositoryClass(Class_ $class): bool
9098
{
91-
if ($class->extends instanceof Name) {
92-
return $this->getName(
93-
$class->extends
94-
) === 'Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository';
99+
if (! $class->extends instanceof Name) {
100+
return false;
95101
}
96102

97-
return false;
103+
return $this->isName($class->extends, DoctrineClass::SERVICE_ENTITY_REPOSITORY);
98104
}
99105

100106
private function getEntityClassFromConstructor(Class_ $class): ?string
101107
{
102-
$method = $class->getMethod(MethodName::CONSTRUCT);
103-
if (!$method instanceof ClassMethod || $method->stmts === null) {
108+
$classMethod = $class->getMethod(MethodName::CONSTRUCT);
109+
if (! $classMethod instanceof ClassMethod || $classMethod->stmts === null) {
104110
return null;
105111
}
106112

107-
foreach ($method->stmts as $stmt) {
113+
foreach ($classMethod->stmts as $stmt) {
108114
if (! $stmt instanceof Expression) {
109115
continue;
110116
}
@@ -136,8 +142,9 @@ private function getEntityClassFromConstructor(Class_ $class): ?string
136142
private function addAnnotationToNode(Class_ $class, string $entityClass): void
137143
{
138144
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($class);
139-
$annotation = sprintf('\Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\%s>', $entityClass);
140-
$phpDocInfo->addPhpDocTagNode(new PhpDocTagNode('@extends', new GenericTagValueNode($annotation)));
145+
146+
$genericsAnnotation = sprintf('\%s<\%s>', DoctrineClass::SERVICE_ENTITY_REPOSITORY, $entityClass);
147+
$phpDocInfo->addPhpDocTagNode(new PhpDocTagNode('@extends', new GenericTagValueNode($genericsAnnotation)));
141148

142149
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($class);
143150
}
@@ -150,12 +157,10 @@ private function hasExtendsAnnotation(Class_ $class): bool
150157

151158
private function isParentConstructorCall(StaticCall $staticCall): bool
152159
{
153-
return $staticCall->class instanceof Name
154-
&& $staticCall->class->toString() === 'parent'
155-
&& $staticCall->name instanceof Identifier
156-
&& $staticCall->name->toString() === '__construct'
160+
return $this->isName($staticCall->class, 'parent')
161+
&& $this->isName($staticCall->name, '__construct')
157162
&& isset($staticCall->args[1])
158-
&& $staticCall->args[1] instanceof Arg // Controleer of args[1] een Node\Arg is
163+
&& $staticCall->args[1] instanceof Arg // Controller of args[1] een Node\Arg is
159164
&& $staticCall->args[1]->value instanceof ClassConstFetch;
160165
}
161166
}

0 commit comments

Comments
 (0)