44
55namespace 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 ;
137use PhpParser \Node ;
8+ use PhpParser \Node \Arg ;
149use PhpParser \Node \Expr \ClassConstFetch ;
10+ use PhpParser \Node \Expr \StaticCall ;
11+ use PhpParser \Node \Name ;
1512use PhpParser \Node \Stmt \Class_ ;
13+ use PhpParser \Node \Stmt \ClassMethod ;
14+ use PhpParser \Node \Stmt \Expression ;
1615use PHPStan \PhpDocParser \Ast \PhpDoc \GenericTagValueNode ;
1716use PHPStan \PhpDocParser \Ast \PhpDoc \PhpDocTagNode ;
1817use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfoFactory ;
1918use Rector \Comments \NodeDocBlock \DocBlockUpdater ;
19+ use Rector \Doctrine \CodeQuality \Enum \DoctrineClass ;
2020use Rector \Rector \AbstractRector ;
2121use Rector \ValueObject \MethodName ;
2222use Symplify \RuleDocGenerator \ValueObject \CodeSample \CodeSample ;
2323use Symplify \RuleDocGenerator \ValueObject \RuleDefinition ;
2424
2525/**
2626 * @see https://github.com/doctrine/DoctrineBundle/commit/2f12b5302bafac39c70b024e1686119be28b79ab
27+ *
28+ * @see \Rector\Doctrine\Tests\Bundle230\Rector\Class_\AddAnnotationToRepositoryRector\AddAnnotationToRepositoryRectorTest
2729 */
2830final class AddAnnotationToRepositoryRector extends AbstractRector
2931{
30- public function __construct (private readonly DocBlockUpdater $ docBlockUpdater , private readonly PhpDocInfoFactory $ phpDocInfoFactory )
31- {
32+ public function __construct (
33+ private readonly DocBlockUpdater $ docBlockUpdater ,
34+ private readonly PhpDocInfoFactory $ phpDocInfoFactory
35+ ) {
3236 }
3337
3438 public function getRuleDefinition (): RuleDefinition
3539 {
3640 return new RuleDefinition ('Add @extends ServiceEntityRepository<T> annotation to repository classes ' , [
3741 new CodeSample (
3842 <<<'CODE_SAMPLE'
43+ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
44+
3945final class SomeRepository extends ServiceEntityRepository
4046{
4147 public function __construct(ManagerRegistry $registry)
@@ -46,7 +52,11 @@ public function __construct(ManagerRegistry $registry)
4652CODE_SAMPLE
4753 ,
4854 <<<'CODE_SAMPLE'
49- /** @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\SomeEntity> */
55+ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
56+
57+ /**
58+ * @extends ServiceEntityRepository<\SomeEntity>
59+ */
5060final class SomeRepository extends ServiceEntityRepository
5161{
5262 public function __construct(ManagerRegistry $registry)
@@ -88,23 +98,21 @@ public function refactor(Node $node): ?Node
8898
8999 private function isRepositoryClass (Class_ $ class ): bool
90100 {
91- if ($ class ->extends instanceof Name) {
92- return $ this ->getName (
93- $ class ->extends
94- ) === 'Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository ' ;
101+ if (! $ class ->extends instanceof Name) {
102+ return false ;
95103 }
96104
97- return false ;
105+ return $ this -> isName ( $ class -> extends , DoctrineClass:: SERVICE_ENTITY_REPOSITORY ) ;
98106 }
99107
100108 private function getEntityClassFromConstructor (Class_ $ class ): ?string
101109 {
102- $ method = $ class ->getMethod (MethodName::CONSTRUCT );
103- if (!$ method instanceof ClassMethod || $ method ->stmts === null ) {
110+ $ classMethod = $ class ->getMethod (MethodName::CONSTRUCT );
111+ if (! $ classMethod instanceof ClassMethod || $ classMethod ->stmts === null ) {
104112 return null ;
105113 }
106114
107- foreach ($ method ->stmts as $ stmt ) {
115+ foreach ($ classMethod ->stmts as $ stmt ) {
108116 if (! $ stmt instanceof Expression) {
109117 continue ;
110118 }
@@ -136,8 +144,9 @@ private function getEntityClassFromConstructor(Class_ $class): ?string
136144 private function addAnnotationToNode (Class_ $ class , string $ entityClass ): void
137145 {
138146 $ phpDocInfo = $ this ->phpDocInfoFactory ->createFromNodeOrEmpty ($ class );
139- $ annotation = sprintf ('\Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\%s> ' , $ entityClass );
140- $ phpDocInfo ->addPhpDocTagNode (new PhpDocTagNode ('@extends ' , new GenericTagValueNode ($ annotation )));
147+
148+ $ genericsAnnotation = sprintf ('\%s<\%s> ' , DoctrineClass::SERVICE_ENTITY_REPOSITORY , $ entityClass );
149+ $ phpDocInfo ->addPhpDocTagNode (new PhpDocTagNode ('@extends ' , new GenericTagValueNode ($ genericsAnnotation )));
141150
142151 $ this ->docBlockUpdater ->updateRefactoredNodeWithPhpDocInfo ($ class );
143152 }
@@ -150,12 +159,10 @@ private function hasExtendsAnnotation(Class_ $class): bool
150159
151160 private function isParentConstructorCall (StaticCall $ staticCall ): bool
152161 {
153- return $ staticCall ->class instanceof Name
154- && $ staticCall ->class ->toString () === 'parent '
155- && $ staticCall ->name instanceof Identifier
156- && $ staticCall ->name ->toString () === '__construct '
162+ return $ this ->isName ($ staticCall ->class , 'parent ' )
163+ && $ this ->isName ($ staticCall ->name , '__construct ' )
157164 && isset ($ staticCall ->args [1 ])
158- && $ staticCall ->args [1 ] instanceof Arg // Controleer of args[1] een Node\Arg is
165+ && $ staticCall ->args [1 ] instanceof Arg // Controller of args[1] een Node\Arg is
159166 && $ staticCall ->args [1 ]->value instanceof ClassConstFetch;
160167 }
161168}
0 commit comments