@@ -17,74 +17,105 @@ public function load(PropertyInfo $info, \ReflectionProperty $property): void
1717 $ this ->loadWriteType ($ property , $ info );
1818 }
1919
20- private function findSourceMap (\ReflectionProperty $ property ): ?SourceInfo
21- {
22- $ class = $ property ->getDeclaringClass ();
23-
24- if ($ class ->isInternal ()) {
25- return null ;
26- }
27-
28- $ file = $ class ->getFileName ();
29- $ line = $ class ->getStartLine ();
30-
31- if ($ file === false || $ line < 1 ) {
32- return null ;
33- }
34-
35- return new SourceInfo ($ file , $ line );
36- }
37-
3820 private function loadReadType (\ReflectionProperty $ property , PropertyInfo $ info ): void
3921 {
40- $ definition = $ this ->getReadTypeDefinition ($ property );
22+ $ definition = $ this ->getReadTypeInfo ($ property );
4123
42- $ info ->read = $ info ->write = new TypeInfo ( $ definition, $ this -> findSourceMap ( $ property )) ;
24+ $ info ->read = $ info ->write = $ definition ;
4325 }
4426
4527 private function loadWriteType (\ReflectionProperty $ property , PropertyInfo $ info ): void
4628 {
47- $ definition = $ this ->findWriteTypeDefinition ($ property );
29+ $ definition = $ this ->findWriteTypeInfo ($ property );
4830
4931 if ($ definition === null ) {
5032 return ;
5133 }
5234
53- $ info ->write = new TypeInfo ( $ definition, $ this -> findSourceMap ( $ property )) ;
35+ $ info ->write = $ definition ;
5436 }
5537
5638 /**
57- * @return non-empty-string
5839 * @throws \InvalidArgumentException
5940 */
60- private function findWriteTypeDefinition (\ReflectionProperty $ property ): ?string
41+ private function findWriteTypeInfo (\ReflectionProperty $ property ): ?TypeInfo
6142 {
6243 if (\PHP_VERSION_ID < 80400 ) {
6344 return null ;
6445 }
6546
47+ // Force skip in case of setter is not defined
48+ if ($ property ->getHook (\PropertyHookType::Set) === null ) {
49+ return null ;
50+ }
51+
52+ $ definition = $ this ->createMixedTypeDefinition ();
6653 $ type = $ property ->getSettableType ();
6754
68- if ($ type === null ) {
69- return $ this ->createMixedTypeDefinition ();
55+ if ($ type !== null ) {
56+ $ definition = $ this ->createTypeDefinition ($ type );
57+ }
58+
59+ return new TypeInfo (
60+ definition: $ definition ,
61+ source: $ this ->getWriteHookSourceInfo ($ property ),
62+ );
63+ }
64+
65+ private function getWriteHookSourceInfo (\ReflectionProperty $ property ): ?SourceInfo
66+ {
67+ if (\PHP_VERSION_ID < 80400 ) {
68+ return null ;
7069 }
7170
72- return $ this ->createTypeDefinition ($ type );
71+ return $ this ->getHookSourceInfo (
72+ hook: $ property ->getHook (\PropertyHookType::Set),
73+ );
7374 }
7475
7576 /**
76- * @return non-empty-string
7777 * @throws \InvalidArgumentException
7878 */
79- private function getReadTypeDefinition (\ReflectionProperty $ property ): string
79+ private function getReadTypeInfo (\ReflectionProperty $ property ): TypeInfo
8080 {
81+ $ definition = $ this ->createMixedTypeDefinition ();
8182 $ type = $ property ->getType ();
8283
83- if ($ type = == null ) {
84- return $ this ->createMixedTypeDefinition ( );
84+ if ($ type ! == null ) {
85+ $ definition = $ this ->createTypeDefinition ( $ type );
8586 }
8687
87- return $ this ->createTypeDefinition ($ type );
88+ return new TypeInfo (
89+ definition: $ definition ,
90+ source: $ this ->getReadHookSourceInfo ($ property ),
91+ );
92+ }
93+
94+ private function getReadHookSourceInfo (\ReflectionProperty $ property ): ?SourceInfo
95+ {
96+ if (\PHP_VERSION_ID < 80400 ) {
97+ return null ;
98+ }
99+
100+ return $ this ->getHookSourceInfo (
101+ hook: $ property ->getHook (\PropertyHookType::Get),
102+ );
103+ }
104+
105+ private function getHookSourceInfo (?\ReflectionMethod $ hook ): ?SourceInfo
106+ {
107+ if ($ hook === null ) {
108+ return null ;
109+ }
110+
111+ $ file = $ hook ->getFileName ();
112+ $ line = $ hook ->getStartLine ();
113+
114+ if (\is_string ($ file ) && $ file !== '' && $ line > 0 ) {
115+ return new SourceInfo ($ file , $ line );
116+ }
117+
118+ return null ;
88119 }
89120
90121 /**
@@ -131,9 +162,15 @@ private function createNamedTypeDefinition(\ReflectionNamedType $type): string
131162 */
132163 private function createNonNullNamedTypeDefinition (\ReflectionNamedType $ type ): string
133164 {
165+ $ literal = $ type ->getName ();
166+
167+ // PHP 8.4 Setter's type bug
168+ if (\str_starts_with ($ literal , '? ' )) {
169+ $ literal = \substr ($ literal , 1 );
170+ }
171+
134172 /** @phpstan-ignore-next-line : Type's name cannot be empty */
135173 $ name = new Name ($ type ->getName ());
136- $ literal = $ name ->toString ();
137174
138175 if ($ type ->isBuiltin () || $ name ->isSpecial () || $ name ->isBuiltin ()) {
139176 return $ literal ;
0 commit comments