1313
1414namespace phpDocumentor \Reflection ;
1515
16- use Doctrine \Deprecations \Deprecation ;
16+ use phpDocumentor \Reflection \PseudoTypes \ClosedResource ;
17+ use phpDocumentor \Reflection \PseudoTypes \IntMaskOf ;
18+ use phpDocumentor \Reflection \PseudoTypes \KeyOf ;
19+ use phpDocumentor \Reflection \PseudoTypes \OpenResource ;
20+ use phpDocumentor \Reflection \PseudoTypes \PrivatePropertiesOf ;
21+ use phpDocumentor \Reflection \PseudoTypes \PropertiesOf ;
22+ use phpDocumentor \Reflection \PseudoTypes \ProtectedPropertiesOf ;
23+ use phpDocumentor \Reflection \PseudoTypes \PublicPropertiesOf ;
24+ use phpDocumentor \Reflection \PseudoTypes \ValueOf ;
25+ use function trim ;
26+ use function strpos ;
27+ use function sprintf ;
28+ use RuntimeException ;
29+ use function in_array ;
30+ use function array_map ;
31+ use function get_class ;
32+ use function strtolower ;
33+ use function array_filter ;
34+ use function class_exists ;
35+ use function array_reverse ;
1736use InvalidArgumentException ;
18- use phpDocumentor \Reflection \PseudoTypes \ArrayShape ;
19- use phpDocumentor \Reflection \PseudoTypes \ArrayShapeItem ;
20- use phpDocumentor \Reflection \PseudoTypes \CallableString ;
21- use phpDocumentor \Reflection \PseudoTypes \ConstExpression ;
22- use phpDocumentor \Reflection \PseudoTypes \False_ ;
23- use phpDocumentor \Reflection \PseudoTypes \FloatValue ;
24- use phpDocumentor \Reflection \PseudoTypes \HtmlEscapedString ;
25- use phpDocumentor \Reflection \PseudoTypes \IntegerRange ;
26- use phpDocumentor \Reflection \PseudoTypes \IntegerValue ;
27- use phpDocumentor \Reflection \PseudoTypes \List_ ;
28- use phpDocumentor \Reflection \PseudoTypes \ListShape ;
29- use phpDocumentor \Reflection \PseudoTypes \ListShapeItem ;
30- use phpDocumentor \Reflection \PseudoTypes \LiteralString ;
31- use phpDocumentor \Reflection \PseudoTypes \LowercaseString ;
32- use phpDocumentor \Reflection \PseudoTypes \NegativeInteger ;
33- use phpDocumentor \Reflection \PseudoTypes \NonEmptyArray ;
34- use phpDocumentor \Reflection \PseudoTypes \NonEmptyList ;
35- use phpDocumentor \Reflection \PseudoTypes \NonEmptyLowercaseString ;
36- use phpDocumentor \Reflection \PseudoTypes \NonEmptyString ;
37- use phpDocumentor \Reflection \PseudoTypes \Numeric_ ;
38- use phpDocumentor \Reflection \PseudoTypes \NumericString ;
39- use phpDocumentor \Reflection \PseudoTypes \ObjectShape ;
40- use phpDocumentor \Reflection \PseudoTypes \ObjectShapeItem ;
41- use phpDocumentor \Reflection \PseudoTypes \PositiveInteger ;
42- use phpDocumentor \Reflection \PseudoTypes \StringValue ;
43- use phpDocumentor \Reflection \PseudoTypes \TraitString ;
44- use phpDocumentor \Reflection \PseudoTypes \True_ ;
45- use phpDocumentor \Reflection \Types \AggregatedType ;
37+ use function array_key_exists ;
38+ use function class_implements ;
39+ use phpDocumentor \Reflection \Type ;
40+ use PHPStan \PhpDocParser \Lexer \Lexer ;
41+ use Doctrine \Deprecations \Deprecation ;
42+ use phpDocumentor \Reflection \Types \This ;
43+ use phpDocumentor \Reflection \Types \Null_ ;
44+ use phpDocumentor \Reflection \Types \Self_ ;
45+ use phpDocumentor \Reflection \Types \Void_ ;
4646use phpDocumentor \Reflection \Types \Array_ ;
47- use phpDocumentor \Reflection \Types \ArrayKey ;
48- use phpDocumentor \Reflection \Types \Boolean ;
49- use phpDocumentor \Reflection \Types \Callable_ ;
50- use phpDocumentor \Reflection \Types \CallableParameter ;
51- use phpDocumentor \Reflection \Types \ClassString ;
52- use phpDocumentor \Reflection \Types \Collection ;
53- use phpDocumentor \Reflection \Types \Compound ;
54- use phpDocumentor \Reflection \Types \Context ;
55- use phpDocumentor \Reflection \Types \Expression ;
5647use phpDocumentor \Reflection \Types \Float_ ;
57- use phpDocumentor \Reflection \Types \Integer ;
58- use phpDocumentor \Reflection \Types \InterfaceString ;
59- use phpDocumentor \Reflection \Types \Intersection ;
60- use phpDocumentor \Reflection \Types \Iterable_ ;
6148use phpDocumentor \Reflection \Types \Mixed_ ;
6249use phpDocumentor \Reflection \Types \Never_ ;
63- use phpDocumentor \Reflection \Types \Null_ ;
64- use phpDocumentor \Reflection \Types \Nullable ;
50+ use phpDocumentor \Reflection \Types \Scalar ;
51+ use phpDocumentor \Reflection \Types \Boolean ;
52+ use phpDocumentor \Reflection \Types \Context ;
53+ use phpDocumentor \Reflection \Types \Integer ;
6554use phpDocumentor \Reflection \Types \Object_ ;
6655use phpDocumentor \Reflection \Types \Parent_ ;
67- use phpDocumentor \Reflection \Types \Resource_ ;
68- use phpDocumentor \Reflection \Types \Scalar ;
69- use phpDocumentor \Reflection \Types \Self_ ;
7056use phpDocumentor \Reflection \Types \Static_ ;
7157use phpDocumentor \Reflection \Types \String_ ;
72- use phpDocumentor \Reflection \Types \This ;
73- use phpDocumentor \Reflection \Types \Void_ ;
74- use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprFloatNode ;
75- use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprIntegerNode ;
76- use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprStringNode ;
77- use PHPStan \PhpDocParser \Ast \ConstExpr \ConstFetchNode ;
78- use PHPStan \PhpDocParser \Ast \Type \ArrayShapeItemNode ;
79- use PHPStan \PhpDocParser \Ast \Type \ArrayShapeNode ;
58+ use PHPStan \PhpDocParser \Ast \Type \TypeNode ;
59+ use PHPStan \PhpDocParser \Parser \TypeParser ;
60+ use phpDocumentor \Reflection \Types \ArrayKey ;
61+ use phpDocumentor \Reflection \Types \Compound ;
62+ use phpDocumentor \Reflection \Types \Nullable ;
63+ use phpDocumentor \Reflection \Types \Callable_ ;
64+ use phpDocumentor \Reflection \Types \Iterable_ ;
65+ use phpDocumentor \Reflection \Types \Resource_ ;
66+ use phpDocumentor \Reflection \Types \Collection ;
67+ use phpDocumentor \Reflection \Types \Expression ;
68+ use PHPStan \PhpDocParser \Parser \TokenIterator ;
69+ use phpDocumentor \Reflection \PseudoTypes \List_ ;
70+ use phpDocumentor \Reflection \PseudoTypes \True_ ;
71+ use phpDocumentor \Reflection \Types \ClassString ;
72+ use PHPStan \PhpDocParser \Ast \Type \ThisTypeNode ;
73+ use phpDocumentor \Reflection \PseudoTypes \False_ ;
74+ use phpDocumentor \Reflection \Types \Intersection ;
8075use PHPStan \PhpDocParser \Ast \Type \ArrayTypeNode ;
81- use PHPStan \PhpDocParser \Ast \Type \CallableTypeNode ;
82- use PHPStan \PhpDocParser \Ast \Type \CallableTypeParameterNode ;
83- use PHPStan \PhpDocParser \Ast \Type \ConditionalTypeForParameterNode ;
84- use PHPStan \PhpDocParser \Ast \Type \ConditionalTypeNode ;
8576use PHPStan \PhpDocParser \Ast \Type \ConstTypeNode ;
77+ use PHPStan \PhpDocParser \Ast \Type \UnionTypeNode ;
78+ use PHPStan \PhpDocParser \Parser \ConstExprParser ;
79+ use PHPStan \PhpDocParser \Parser \ParserException ;
80+ use phpDocumentor \Reflection \PseudoTypes \IntMask ;
81+ use PHPStan \PhpDocParser \Ast \Type \ArrayShapeNode ;
82+ use phpDocumentor \Reflection \PseudoTypes \Numeric_ ;
83+ use phpDocumentor \Reflection \Types \AggregatedType ;
8684use PHPStan \PhpDocParser \Ast \Type \GenericTypeNode ;
87- use PHPStan \PhpDocParser \Ast \Type \IdentifierTypeNode ;
88- use PHPStan \PhpDocParser \Ast \Type \IntersectionTypeNode ;
85+ use PHPStan \PhpDocParser \Ast \Type \ObjectShapeNode ;
86+ use phpDocumentor \Reflection \PseudoTypes \ListShape ;
87+ use phpDocumentor \Reflection \Types \InterfaceString ;
88+ use PHPStan \PhpDocParser \Ast \Type \CallableTypeNode ;
8989use PHPStan \PhpDocParser \Ast \Type \NullableTypeNode ;
90+ use phpDocumentor \Reflection \PseudoTypes \ArrayShape ;
91+ use phpDocumentor \Reflection \PseudoTypes \FloatValue ;
92+ use phpDocumentor \Reflection \PseudoTypes \Conditional ;
93+ use phpDocumentor \Reflection \PseudoTypes \ObjectShape ;
94+ use phpDocumentor \Reflection \PseudoTypes \StringValue ;
95+ use phpDocumentor \Reflection \PseudoTypes \TraitString ;
96+ use phpDocumentor \Reflection \Types \CallableParameter ;
97+ use PHPStan \PhpDocParser \Ast \Type \ArrayShapeItemNode ;
98+ use PHPStan \PhpDocParser \Ast \Type \IdentifierTypeNode ;
99+ use phpDocumentor \Reflection \PseudoTypes \IntegerRange ;
100+ use phpDocumentor \Reflection \PseudoTypes \IntegerValue ;
101+ use phpDocumentor \Reflection \PseudoTypes \NonEmptyList ;
102+ use phpDocumentor \Reflection \PseudoTypes \OffsetAccess ;
103+ use PHPStan \PhpDocParser \Ast \ConstExpr \ConstFetchNode ;
104+ use PHPStan \PhpDocParser \Ast \Type \ConditionalTypeNode ;
90105use PHPStan \PhpDocParser \Ast \Type \ObjectShapeItemNode ;
91- use PHPStan \PhpDocParser \Ast \Type \ObjectShapeNode ;
106+ use phpDocumentor \Reflection \PseudoTypes \ListShapeItem ;
107+ use phpDocumentor \Reflection \PseudoTypes \LiteralString ;
108+ use phpDocumentor \Reflection \PseudoTypes \NonEmptyArray ;
109+ use phpDocumentor \Reflection \PseudoTypes \NumericString ;
110+ use PHPStan \PhpDocParser \Ast \Type \IntersectionTypeNode ;
92111use PHPStan \PhpDocParser \Ast \Type \OffsetAccessTypeNode ;
93- use PHPStan \PhpDocParser \Ast \Type \ThisTypeNode ;
94- use PHPStan \PhpDocParser \Ast \Type \TypeNode ;
95- use PHPStan \PhpDocParser \Ast \Type \UnionTypeNode ;
96- use PHPStan \PhpDocParser \Lexer \Lexer ;
97- use PHPStan \PhpDocParser \Parser \ConstExprParser ;
98- use PHPStan \PhpDocParser \Parser \ParserException ;
99- use PHPStan \PhpDocParser \Parser \TokenIterator ;
100- use PHPStan \PhpDocParser \Parser \TypeParser ;
101- use RuntimeException ;
112+ use phpDocumentor \Reflection \PseudoTypes \ArrayShapeItem ;
113+ use phpDocumentor \Reflection \PseudoTypes \CallableString ;
114+ use phpDocumentor \Reflection \PseudoTypes \NonEmptyString ;
102115
103- use function array_filter ;
104- use function array_key_exists ;
105- use function array_map ;
106- use function array_reverse ;
107- use function class_exists ;
108- use function class_implements ;
109- use function get_class ;
110- use function in_array ;
111- use function sprintf ;
112- use function strpos ;
113- use function strtolower ;
114- use function trim ;
116+ use phpDocumentor \Reflection \PseudoTypes \ConstExpression ;
117+ use phpDocumentor \Reflection \PseudoTypes \LowercaseString ;
118+ use phpDocumentor \Reflection \PseudoTypes \NegativeInteger ;
119+ use phpDocumentor \Reflection \PseudoTypes \ObjectShapeItem ;
120+ use phpDocumentor \Reflection \PseudoTypes \PositiveInteger ;
121+ use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprFloatNode ;
122+ use phpDocumentor \Reflection \PseudoTypes \HtmlEscapedString ;
123+ use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprStringNode ;
124+ use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprIntegerNode ;
125+ use PHPStan \PhpDocParser \Ast \Type \CallableTypeParameterNode ;
126+ use phpDocumentor \Reflection \PseudoTypes \ConditionalParameter ;
127+ use phpDocumentor \Reflection \PseudoTypes \NonEmptyLowercaseString ;
128+ use PHPStan \PhpDocParser \Ast \Type \ConditionalTypeForParameterNode ;
115129
116130final class TypeResolver
117131{
@@ -148,6 +162,8 @@ final class TypeResolver
148162 'array-key ' => ArrayKey::class,
149163 'non-empty-array ' => NonEmptyArray::class,
150164 'resource ' => Resource_::class,
165+ 'closed-resource ' => ClosedResource::class,
166+ 'open-resource ' => OpenResource::class,
151167 'void ' => Void_::class,
152168 'null ' => Null_::class,
153169 'scalar ' => Scalar::class,
@@ -344,7 +360,22 @@ function (TypeNode $nestedType) use ($context): Type {
344360
345361 case ConditionalTypeNode::class:
346362 case ConditionalTypeForParameterNode::class:
363+ [$ class , $ subject ] = $ type instanceof ConditionalTypeForParameterNode
364+ ? [ConditionalParameter::class, $ type ->parameterName ]
365+ : [Conditional::class, $ this ->createType ($ type ->subjectType , $ context )];
366+
367+ $ target = $ this ->createType ($ type ->targetType , $ context );
368+ $ if = $ this ->createType ($ type ->if , $ context );
369+ $ else = $ this ->createType ($ type ->else , $ context );
370+
371+ return new $ class ($ subject , $ target , $ if , $ else , $ type ->negated );
372+
347373 case OffsetAccessTypeNode::class:
374+ $ offset = $ this ->createType ($ type ->offset , $ context );
375+ $ type = $ this ->createType ($ type ->type , $ context );
376+
377+ return new OffsetAccess ($ type , $ offset );
378+
348379 default :
349380 return new Mixed_ ();
350381 }
@@ -380,6 +411,54 @@ private function createFromGeneric(GenericTypeNode $type, Context $context): Typ
380411 $ subType ->getFqsen ()
381412 );
382413
414+ case 'properties-of ' :
415+ $ subType = $ this ->createType ($ type ->genericTypes [0 ], $ context );
416+ if (!$ subType instanceof Object_ || $ subType ->getFqsen () === null ) {
417+ throw new RuntimeException (
418+ $ subType . ' is not a class '
419+ );
420+ }
421+
422+ return new PropertiesOf (
423+ $ subType ->getFqsen ()
424+ );
425+
426+ case 'public-properties-of ' :
427+ $ subType = $ this ->createType ($ type ->genericTypes [0 ], $ context );
428+ if (!$ subType instanceof Object_ || $ subType ->getFqsen () === null ) {
429+ throw new RuntimeException (
430+ $ subType . ' is not a class '
431+ );
432+ }
433+
434+ return new PublicPropertiesOf (
435+ $ subType ->getFqsen ()
436+ );
437+
438+ case 'protected-properties-of ' :
439+ $ subType = $ this ->createType ($ type ->genericTypes [0 ], $ context );
440+ if (!$ subType instanceof Object_ || $ subType ->getFqsen () === null ) {
441+ throw new RuntimeException (
442+ $ subType . ' is not a class '
443+ );
444+ }
445+
446+ return new ProtectedPropertiesOf (
447+ $ subType ->getFqsen ()
448+ );
449+
450+ case 'private-properties-of ' :
451+ $ subType = $ this ->createType ($ type ->genericTypes [0 ], $ context );
452+ if (!$ subType instanceof Object_ || $ subType ->getFqsen () === null ) {
453+ throw new RuntimeException (
454+ $ subType . ' is not a class '
455+ );
456+ }
457+
458+ return new PrivatePropertiesOf (
459+ $ subType ->getFqsen ()
460+ );
461+
383462 case 'list ' :
384463 return new List_ (
385464 $ this ->createType ($ type ->genericTypes [0 ], $ context )
@@ -389,6 +468,16 @@ private function createFromGeneric(GenericTypeNode $type, Context $context): Typ
389468 return new NonEmptyList (
390469 $ this ->createType ($ type ->genericTypes [0 ], $ context )
391470 );
471+
472+ case 'key-of ' :
473+ return new KeyOf (
474+ $ this ->createType ($ type ->genericTypes [0 ], $ context )
475+ );
476+
477+ case 'value-of ' :
478+ return new ValueOf (
479+ $ this ->createType ($ type ->genericTypes [0 ], $ context )
480+ );
392481
393482 case 'int ' :
394483 if (isset ($ type ->genericTypes [1 ]) === false ) {
@@ -397,6 +486,26 @@ private function createFromGeneric(GenericTypeNode $type, Context $context): Typ
397486
398487 return new IntegerRange ((string ) $ type ->genericTypes [0 ], (string ) $ type ->genericTypes [1 ]);
399488
489+ case 'int-mask ' :
490+ return new IntMask (
491+ array_map (
492+ function (TypeNode $ genericType ) use ($ context ): Type {
493+ return $ this ->createType ($ genericType , $ context );
494+ },
495+ $ type ->genericTypes
496+ )
497+ );
498+
499+ case 'int-mask-of ' :
500+ return new IntMaskOf (
501+ array_map (
502+ function (TypeNode $ genericType ) use ($ context ): Type {
503+ return $ this ->createType ($ genericType , $ context );
504+ },
505+ $ type ->genericTypes
506+ )
507+ );
508+
400509 case 'iterable ' :
401510 return new Iterable_ (
402511 ...array_reverse (
0 commit comments