1414use PhpParser \Node \Stmt \ClassMethod ;
1515use PhpParser \Node \Stmt \Expression ;
1616use PhpParser \Node \Stmt \Property ;
17+ use PHPStan \PhpDocParser \Ast \PhpDoc \InvalidTagValueNode ;
1718use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfo ;
1819use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfoFactory ;
20+ use Rector \BetterPhpDocParser \PhpDocParser \ClassAnnotationMatcher ;
1921use Rector \Enum \ClassName ;
2022use Rector \NodeAnalyzer \PropertyFetchAnalyzer ;
2123use Rector \NodeNameResolver \NodeNameResolver ;
@@ -31,7 +33,8 @@ public function __construct(
3133 private NodeComparator $ nodeComparator ,
3234 private PropertyFetchAnalyzer $ propertyFetchAnalyzer ,
3335 private PhpDocInfoFactory $ phpDocInfoFactory ,
34- private PhpAttributeAnalyzer $ phpAttributeAnalyzer
36+ private PhpAttributeAnalyzer $ phpAttributeAnalyzer ,
37+ private ClassAnnotationMatcher $ classAnnotationMatcher
3538 ) {
3639 }
3740
@@ -79,13 +82,33 @@ public function resolveFromClass(
7982 private function hasModelTypeCheck (Class_ |Property $ node , string $ modelType ): bool
8083 {
8184 $ phpDocInfo = $ this ->phpDocInfoFactory ->createFromNode ($ node );
82- if ($ phpDocInfo instanceof PhpDocInfo && $ phpDocInfo ->hasByAnnotationClass ($ modelType )) {
85+ if ($ phpDocInfo instanceof PhpDocInfo && ($ phpDocInfo ->hasByAnnotationClass (
86+ $ modelType
87+ ) || $ this ->hasInvalidAnnotation ($ phpDocInfo , $ node , $ modelType ))) {
8388 return true ;
8489 }
8590
8691 return $ this ->phpAttributeAnalyzer ->hasPhpAttribute ($ node , $ modelType );
8792 }
8893
94+ /**
95+ * An annotation with arguments that are not valid, e.g. @JMS\Type('string)
96+ */
97+ private function hasInvalidAnnotation (PhpDocInfo $ phpDocInfo , Class_ |Property $ node , string $ modelType ): bool
98+ {
99+ foreach ($ phpDocInfo ->getPhpDocNode ()->getTags () as $ phpDocTagNode ) {
100+ if (! $ phpDocTagNode ->value instanceof InvalidTagValueNode) {
101+ continue ;
102+ }
103+
104+ if ($ this ->classAnnotationMatcher ->resolveTagFullyQualifiedName ($ phpDocTagNode ->name , $ node ) === $ modelType ) {
105+ return true ;
106+ }
107+ }
108+
109+ return false ;
110+ }
111+
89112 private function matchPropertyPromotionCandidate (
90113 Property $ property ,
91114 ClassMethod $ constructClassMethod ,
0 commit comments