77
88class Runtime
99{
10- private string $ filename ;
1110
12- private string $ typeDescription ;
13-
14-
15- public function __construct (string $ filename , string $ typeDescription )
16- {
17- SupportedTypes::check ($ filename , $ typeDescription );
18-
19- $ this ->filename = $ filename ;
20- $ this ->typeDescription = $ typeDescription ;
21- }
22-
23-
24- public function check (mixed $ value ): bool
11+ /**
12+ * @param callable(): string $filenameCallback
13+ */
14+ public static function check (string $ typeDescription , callable $ filenameCallback , mixed $ value ): bool
2515 {
26- return $ this ->checkTypeNode (PhpDocParser::parseType ($ this ->typeDescription ), $ value );
16+ SupportedTypes::check ($ typeDescription , $ filenameCallback );
17+ return self ::checkTypeNode (PhpDocParser::parseType ($ typeDescription ), $ filenameCallback , $ value );
2718 }
2819
2920
30- private function checkTypeNode (Ast \Type \TypeNode $ typeNode , mixed $ value ): bool
21+ /**
22+ * @param callable(): string $filenameCallback
23+ */
24+ private static function checkTypeNode (Ast \Type \TypeNode $ typeNode , callable $ filenameCallback , mixed $ value ): bool
3125 {
3226 // PHPStan source - src/PhpDoc/TypeNodeResolver.php + https://phpstan.org/writing-php-code/phpdoc-types
3327 if ($ typeNode instanceof Ast \Type \IdentifierTypeNode) {
@@ -83,7 +77,7 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
8377 'interface-string ' => is_string ($ value ) && interface_exists ($ value ),
8478 'trait-string ' => is_string ($ value ) && trait_exists ($ value ),
8579 'enum-string ' => is_string ($ value ) && enum_exists ($ value ),
86- default => $ this -> instanceOf ($ typeNode ->name , $ value ),
80+ default => self :: instanceOf ($ typeNode ->name , $ filenameCallback , $ value ),
8781 };
8882
8983 if (!$ result ) {
@@ -116,7 +110,7 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
116110 return true ;
117111 }
118112
119- return $ this -> checkTypeNode ($ typeNode ->type , $ value );
113+ return self :: checkTypeNode ($ typeNode ->type , $ filenameCallback , $ value );
120114 } else if ($ typeNode instanceof Ast \Type \ConstTypeNode) {
121115 $ constExpr = $ typeNode ->constExpr ;
122116 if ($ constExpr instanceof Ast \ConstExpr \ConstExprIntegerNode) {
@@ -132,7 +126,7 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
132126 }
133127
134128 foreach ($ value as $ item ) {
135- if (!$ this -> checkTypeNode ($ typeNode ->type , $ item )) {
129+ if (!self :: checkTypeNode ($ typeNode ->type , $ filenameCallback , $ item )) {
136130 return false ;
137131 }
138132 }
@@ -158,7 +152,7 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
158152
159153 if (!$ arrayShapeItem ->optional && !array_key_exists ($ key , $ value )) {
160154 return false ;
161- } else if (array_key_exists ($ key , $ value ) && !$ this -> checkTypeNode ($ arrayShapeItem ->valueType , $ value [$ key ])) {
155+ } else if (array_key_exists ($ key , $ value ) && !self :: checkTypeNode ($ arrayShapeItem ->valueType , $ filenameCallback , $ value [$ key ])) {
162156 return false ;
163157 }
164158 }
@@ -179,7 +173,7 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
179173
180174 if (!$ objectShapeItem ->optional && !property_exists ($ value , $ key )) {
181175 return false ;
182- } else if (property_exists ($ value , $ key ) && !$ this -> checkTypeNode ($ objectShapeItem ->valueType , $ value ->{$ key })) {
176+ } else if (property_exists ($ value , $ key ) && !self :: checkTypeNode ($ objectShapeItem ->valueType , $ filenameCallback , $ value ->{$ key })) {
183177 return false ;
184178 }
185179 }
@@ -200,7 +194,7 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
200194 foreach ($ value as $ key => $ item ) {
201195 $ checkItems = count ($ typeNode ->genericTypes ) === 1 ? [$ item ] : [$ key , $ item ];
202196 foreach ($ typeNode ->genericTypes as $ i => $ genericType ) {
203- if (!$ this -> checkTypeNode ($ genericType , $ checkItems [$ i ])) {
197+ if (!self :: checkTypeNode ($ genericType, $ filenameCallback , $ checkItems [$ i ])) {
204198 return false ;
205199 }
206200 }
@@ -215,7 +209,7 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
215209 }
216210
217211 foreach ($ value as $ item ) {
218- if (!$ this -> checkTypeNode ($ typeNode ->genericTypes [0 ], $ item )) {
212+ if (!self :: checkTypeNode ($ typeNode ->genericTypes [0 ], $ filenameCallback , $ item )) {
219213 return false ;
220214 }
221215 }
@@ -270,21 +264,21 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
270264 return false ;
271265 }
272266
273- return $ this -> isClassStringOrInterfaceStringOf ($ typeNode ->genericTypes [0 ], $ value , $ name === 'interface-string ' );
267+ return self :: isClassStringOrInterfaceStringOf ($ typeNode ->genericTypes [0 ], $ filenameCallback , $ value , $ name === 'interface-string ' );
274268 }
275269
276270 return true ;
277271 } else if ($ typeNode instanceof Ast \Type \UnionTypeNode) {
278272 foreach ($ typeNode ->types as $ typeNodeItem ) {
279- if ($ this -> checkTypeNode ($ typeNodeItem , $ value )) {
273+ if (self :: checkTypeNode ($ typeNodeItem, $ filenameCallback , $ value )) {
280274 return true ;
281275 }
282276 }
283277
284278 return false ;
285279 } else if ($ typeNode instanceof Ast \Type \IntersectionTypeNode) {
286280 foreach ($ typeNode ->types as $ typeNodeItem ) {
287- if (!$ this -> checkTypeNode ($ typeNodeItem , $ value )) {
281+ if (!self :: checkTypeNode ($ typeNodeItem, $ filenameCallback , $ value )) {
288282 return false ;
289283 }
290284 }
@@ -296,30 +290,41 @@ private function checkTypeNode(Ast\Type\TypeNode $typeNode, mixed $value): bool
296290 }
297291
298292
299- private function instanceOf (string $ class , mixed $ value ): bool
293+ /**
294+ * @param callable(): string $filenameCallback
295+ */
296+ private static function instanceOf (string $ class , callable $ filenameCallback , mixed $ value ): bool
300297 {
301- $ fullyQualifiedClassName = FullyQualifiedClassNameResolver::resolve ($ this -> filename , $ class );
298+ $ fullyQualifiedClassName = FullyQualifiedClassNameResolver::resolve ($ filenameCallback () , $ class );
302299 return $ value instanceof $ fullyQualifiedClassName ;
303300 }
304301
305302
306- private function isClassStringOrInterfaceStringOf (Ast \Type \TypeNode $ typeNode , string $ value , bool $ interface ): bool
303+ /**
304+ * @param callable(): string $filenameCallback
305+ */
306+ private static function isClassStringOrInterfaceStringOf (
307+ Ast \Type \TypeNode $ typeNode ,
308+ callable $ filenameCallback ,
309+ string $ value ,
310+ bool $ interface ,
311+ ): bool
307312 {
308313 if ($ typeNode instanceof Ast \Type \IdentifierTypeNode) {
309314 return $ interface
310- ? is_subclass_of ($ value , FullyQualifiedClassNameResolver::resolve ($ this -> filename , $ typeNode ->name ))
311- : is_a ($ value , FullyQualifiedClassNameResolver::resolve ($ this -> filename , $ typeNode ->name ), true );
315+ ? is_subclass_of ($ value , FullyQualifiedClassNameResolver::resolve ($ filenameCallback () , $ typeNode ->name ))
316+ : is_a ($ value , FullyQualifiedClassNameResolver::resolve ($ filenameCallback () , $ typeNode ->name ), true );
312317 } else if ($ typeNode instanceof Ast \Type \UnionTypeNode) {
313318 foreach ($ typeNode ->types as $ type ) {
314- if ($ this -> isClassStringOrInterfaceStringOf ($ type , $ value , $ interface )) {
319+ if (self :: isClassStringOrInterfaceStringOf ($ type, $ filenameCallback , $ value , $ interface )) {
315320 return true ;
316321 }
317322 }
318323
319324 return false ;
320325 } else if ($ typeNode instanceof Ast \Type \IntersectionTypeNode) {
321326 foreach ($ typeNode ->types as $ type ) {
322- if (!$ this -> isClassStringOrInterfaceStringOf ($ type , $ value , $ interface )) {
327+ if (!self :: isClassStringOrInterfaceStringOf ($ type, $ filenameCallback , $ value , $ interface )) {
323328 return false ;
324329 }
325330 }
0 commit comments