33declare (strict_types=1 );
44namespace Rector \Doctrine \Bundle230 \Rector \Class_ ;
55
6- use PhpParser \Node \Name ;
7- use PhpParser \Node \Stmt \ClassMethod ;
8- use PhpParser \Node \Stmt \Expression ;
9- use PhpParser \Node \Expr \StaticCall ;
10- use PhpParser \Node \Identifier ;
11- use PhpParser \Node \Arg ;
126use PhpParser \Node ;
7+ use PhpParser \Node \Arg ;
138use PhpParser \Node \Expr \ClassConstFetch ;
9+ use PhpParser \Node \Expr \StaticCall ;
10+ use PhpParser \Node \Name ;
1411use PhpParser \Node \Stmt \Class_ ;
12+ use PhpParser \Node \Stmt \ClassMethod ;
13+ use PhpParser \Node \Stmt \Expression ;
1514use PHPStan \PhpDocParser \Ast \PhpDoc \GenericTagValueNode ;
1615use PHPStan \PhpDocParser \Ast \PhpDoc \PhpDocTagNode ;
1716use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfoFactory ;
1817use Rector \Comments \NodeDocBlock \DocBlockUpdater ;
18+ use Rector \Doctrine \CodeQuality \Enum \DoctrineClass ;
1919use Rector \Rector \AbstractRector ;
2020use Rector \ValueObject \MethodName ;
2121use Symplify \RuleDocGenerator \ValueObject \CodeSample \CodeSample ;
2222use Symplify \RuleDocGenerator \ValueObject \RuleDefinition ;
2323/**
2424 * @see https://github.com/doctrine/DoctrineBundle/commit/2f12b5302bafac39c70b024e1686119be28b79ab
25+ *
26+ * @see \Rector\Doctrine\Tests\Bundle230\Rector\Class_\AddAnnotationToRepositoryRector\AddAnnotationToRepositoryRectorTest
2527 */
2628final class AddAnnotationToRepositoryRector extends AbstractRector
2729{
@@ -41,6 +43,8 @@ public function __construct(DocBlockUpdater $docBlockUpdater, PhpDocInfoFactory
4143 public function getRuleDefinition () : RuleDefinition
4244 {
4345 return new RuleDefinition ('Add @extends ServiceEntityRepository<T> annotation to repository classes ' , [new CodeSample (<<<'CODE_SAMPLE'
46+ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
47+
4448final class SomeRepository extends ServiceEntityRepository
4549{
4650 public function __construct(ManagerRegistry $registry)
@@ -50,7 +54,11 @@ public function __construct(ManagerRegistry $registry)
5054}
5155CODE_SAMPLE
5256, <<<'CODE_SAMPLE'
53- /** @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\SomeEntity> */
57+ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
58+
59+ /**
60+ * @extends ServiceEntityRepository<\SomeEntity>
61+ */
5462final class SomeRepository extends ServiceEntityRepository
5563{
5664 public function __construct(ManagerRegistry $registry)
@@ -85,18 +93,18 @@ public function refactor(Node $node) : ?Node
8593 }
8694 private function isRepositoryClass (Class_ $ class ) : bool
8795 {
88- if ($ class ->extends instanceof Name) {
89- return $ this -> getName ( $ class -> extends ) === ' Doctrine \\ Bundle \\ DoctrineBundle \\ Repository \\ ServiceEntityRepository ' ;
96+ if (! $ class ->extends instanceof Name) {
97+ return \false ;
9098 }
91- return \false ;
99+ return $ this -> isName ( $ class -> extends , DoctrineClass:: SERVICE_ENTITY_REPOSITORY ) ;
92100 }
93101 private function getEntityClassFromConstructor (Class_ $ class ) : ?string
94102 {
95- $ method = $ class ->getMethod (MethodName::CONSTRUCT );
96- if (!$ method instanceof ClassMethod || $ method ->stmts === null ) {
103+ $ classMethod = $ class ->getMethod (MethodName::CONSTRUCT );
104+ if (!$ classMethod instanceof ClassMethod || $ classMethod ->stmts === null ) {
97105 return null ;
98106 }
99- foreach ($ method ->stmts as $ stmt ) {
107+ foreach ($ classMethod ->stmts as $ stmt ) {
100108 if (!$ stmt instanceof Expression) {
101109 continue ;
102110 }
@@ -119,8 +127,8 @@ private function getEntityClassFromConstructor(Class_ $class) : ?string
119127 private function addAnnotationToNode (Class_ $ class , string $ entityClass ) : void
120128 {
121129 $ phpDocInfo = $ this ->phpDocInfoFactory ->createFromNodeOrEmpty ($ class );
122- $ annotation = \sprintf ('\\Doctrine \\ Bundle \\ DoctrineBundle \\ Repository \\ ServiceEntityRepository < \\%s> ' , $ entityClass );
123- $ phpDocInfo ->addPhpDocTagNode (new PhpDocTagNode ('@extends ' , new GenericTagValueNode ($ annotation )));
130+ $ genericsAnnotation = \sprintf ('\\%s < \\%s> ' , DoctrineClass:: SERVICE_ENTITY_REPOSITORY , $ entityClass );
131+ $ phpDocInfo ->addPhpDocTagNode (new PhpDocTagNode ('@extends ' , new GenericTagValueNode ($ genericsAnnotation )));
124132 $ this ->docBlockUpdater ->updateRefactoredNodeWithPhpDocInfo ($ class );
125133 }
126134 private function hasExtendsAnnotation (Class_ $ class ) : bool
@@ -129,6 +137,6 @@ private function hasExtendsAnnotation(Class_ $class) : bool
129137 }
130138 private function isParentConstructorCall (StaticCall $ staticCall ) : bool
131139 {
132- return $ staticCall -> class instanceof Name && $ staticCall ->class -> toString () === 'parent ' && $ staticCall -> name instanceof Identifier && $ staticCall ->name -> toString () === '__construct ' && isset ($ staticCall ->args [1 ]) && $ staticCall ->args [1 ] instanceof Arg && $ staticCall ->args [1 ]->value instanceof ClassConstFetch;
140+ return $ this -> isName ( $ staticCall ->class , 'parent ' ) && $ this -> isName ( $ staticCall ->name , '__construct ' ) && isset ($ staticCall ->args [1 ]) && $ staticCall ->args [1 ] instanceof Arg && $ staticCall ->args [1 ]->value instanceof ClassConstFetch;
133141 }
134142}
0 commit comments