@@ -618,10 +618,14 @@ protected function parseNativeAttributeParams(string $text): array
618618 */
619619 protected function processORMAnnotation (string $ name , array $ attributes ): void
620620 {
621- $ this ->validateAnnotationDeclaration ($ name , $ attributes );
622-
623621 $ name = preg_replace ('/^ORM \\\\/ ' , '' , $ name );
624622
623+ if ($ this ->memberType !== null ) {
624+ $ attributes = $ this ->inferTypedPropertyAnnotationDefaults ($ name , $ attributes );
625+ }
626+
627+ $ this ->validateAnnotationDeclaration ($ name , $ attributes );
628+
625629 $ tokens = $ this ->phpcsFile ->getTokens ();
626630 $ this ->varName = ltrim ($ tokens [$ this ->memberPtr ]['content ' ], '$ ' );
627631
@@ -646,6 +650,98 @@ protected function processORMAnnotation(string $name, array $attributes): void
646650 }
647651 }
648652
653+ /**
654+ * @param string $name
655+ * @param array $attributes
656+ *
657+ * @return array
658+ *
659+ * @see https://www.doctrine-project.org/2021/05/24/orm2.9.html
660+ */
661+ protected function inferTypedPropertyAnnotationDefaults (string $ name , array $ attributes ): array
662+ {
663+ $ type = ltrim ($ this ->memberType , '? \\' );
664+
665+ switch ($ name ) {
666+ case 'Column ' :
667+ $ attributes = $ this ->inferTypedPropertyColumnAnnotationDefaults ($ attributes , $ type );
668+ break ;
669+
670+ case 'ManyToOne ' :
671+ case 'OneToOne ' :
672+ $ attributes = $ this ->inferTypedPropertyRelationToOneAnnotationDefaults ($ attributes , $ type );
673+ break ;
674+ }
675+
676+ return $ attributes ;
677+ }
678+
679+ /**
680+ * @param array $attributes
681+ * @param string $type
682+ *
683+ * @return array
684+ *
685+ * @see \Doctrine\ORM\Mapping\ClassMetadataInfo::validateAndCompleteTypedFieldMapping()
686+ */
687+ protected function inferTypedPropertyColumnAnnotationDefaults (array $ attributes , string $ type ): array
688+ {
689+ if (!isset ($ attributes ['type ' ])) {
690+ switch ($ type ) {
691+ case 'DateInterval ' :
692+ $ attributes ['type ' ] = 'dateinterval ' ;
693+ break ;
694+
695+ case 'DateTime ' :
696+ $ attributes ['type ' ] = 'datetime ' ;
697+ break ;
698+
699+ case 'DateTimeImmutable ' :
700+ $ attributes ['type ' ] = 'datetime_immutable ' ;
701+ break ;
702+
703+ case 'array ' :
704+ $ attributes ['type ' ] = 'json ' ;
705+ break ;
706+
707+ case 'bool ' :
708+ $ attributes ['type ' ] = 'boolean ' ;
709+ break ;
710+
711+ case 'float ' :
712+ $ attributes ['type ' ] = 'float ' ;
713+ break ;
714+
715+ case 'int ' :
716+ $ attributes ['type ' ] = 'integer ' ;
717+ break ;
718+
719+ case 'string ' :
720+ $ attributes ['type ' ] = 'string ' ;
721+ break ;
722+ }
723+ }
724+
725+ return $ attributes ;
726+ }
727+
728+ /**
729+ * @param array $attributes
730+ * @param string $type
731+ *
732+ * @return array
733+ *
734+ * @see \Doctrine\ORM\Mapping\ClassMetadataInfo::validateAndCompleteTypedAssociationMapping()
735+ */
736+ protected function inferTypedPropertyRelationToOneAnnotationDefaults (array $ attributes , string $ type ): array
737+ {
738+ if (!isset ($ attributes ['targetEntity ' ])) {
739+ $ attributes ['targetEntity ' ] = $ type . self ::CLASS_SUFFIX ;
740+ }
741+
742+ return $ attributes ;
743+ }
744+
649745 /**
650746 * Validates annotation declaration.
651747 *
0 commit comments