@@ -1057,6 +1057,8 @@ private function resolveArrayShapeNode(ArrayShapeNode $typeNode, NameScope $name
1057
1057
$ offsetType = new ConstantStringType ($ itemNode ->keyName ->name );
1058
1058
} elseif ($ itemNode ->keyName instanceof ConstExprStringNode) {
1059
1059
$ offsetType = new ConstantStringType ($ itemNode ->keyName ->value );
1060
+ } elseif ($ itemNode ->keyName instanceof ConstFetchNode) {
1061
+ $ offsetType = $ this ->resolveConstFetchNode ($ itemNode ->keyName , $ nameScope );
1060
1062
} elseif ($ itemNode ->keyName !== null ) {
1061
1063
throw new ShouldNotHappenException ('Unsupported key node type: ' . get_class ($ itemNode ->keyName ));
1062
1064
}
@@ -1118,107 +1120,112 @@ private function resolveConstTypeNode(ConstTypeNode $typeNode, NameScope $nameSc
1118
1120
}
1119
1121
1120
1122
if ($ constExpr instanceof ConstFetchNode) {
1121
- if ($ constExpr ->className === '' ) {
1122
- throw new ShouldNotHappenException (); // global constant should get parsed as class name in IdentifierTypeNode
1123
- }
1123
+ return $ this ->resolveConstFetchNode ($ constExpr , $ nameScope );
1124
+ }
1124
1125
1125
- if ($ nameScope ->getClassName () !== null ) {
1126
- switch (strtolower ($ constExpr ->className )) {
1127
- case 'static ' :
1128
- case 'self ' :
1129
- $ className = $ nameScope ->getClassName ();
1130
- break ;
1126
+ if ($ constExpr instanceof ConstExprFloatNode) {
1127
+ return new ConstantFloatType ((float ) $ constExpr ->value );
1128
+ }
1131
1129
1132
- case 'parent ' :
1133
- if ($ this ->getReflectionProvider ()->hasClass ($ nameScope ->getClassName ())) {
1134
- $ classReflection = $ this ->getReflectionProvider ()->getClass ($ nameScope ->getClassName ());
1135
- if ($ classReflection ->getParentClass () === null ) {
1136
- return new ErrorType ();
1130
+ if ($ constExpr instanceof ConstExprIntegerNode) {
1131
+ return new ConstantIntegerType ((int ) $ constExpr ->value );
1132
+ }
1137
1133
1138
- }
1134
+ if ($ constExpr instanceof ConstExprStringNode) {
1135
+ return new ConstantStringType ($ constExpr ->value );
1136
+ }
1139
1137
1140
- $ className = $ classReflection ->getParentClass ()->getName ();
1141
- }
1142
- break ;
1143
- }
1144
- }
1138
+ return new ErrorType ();
1139
+ }
1145
1140
1146
- if (!isset ($ className )) {
1147
- $ className = $ nameScope ->resolveStringName ($ constExpr ->className );
1148
- }
1141
+ private function resolveConstFetchNode (ConstFetchNode $ constExpr , NameScope $ nameScope ): Type
1142
+ {
1143
+ if ($ constExpr ->className === '' ) {
1144
+ throw new ShouldNotHappenException (); // global constant should get parsed as class name in IdentifierTypeNode
1145
+ }
1149
1146
1150
- if (!$ this ->getReflectionProvider ()->hasClass ($ className )) {
1151
- return new ErrorType ();
1152
- }
1147
+ if ($ nameScope ->getClassName () !== null ) {
1148
+ switch (strtolower ($ constExpr ->className )) {
1149
+ case 'static ' :
1150
+ case 'self ' :
1151
+ $ className = $ nameScope ->getClassName ();
1152
+ break ;
1153
1153
1154
- $ classReflection = $ this ->getReflectionProvider ()->getClass ($ className );
1154
+ case 'parent ' :
1155
+ if ($ this ->getReflectionProvider ()->hasClass ($ nameScope ->getClassName ())) {
1156
+ $ classReflection = $ this ->getReflectionProvider ()->getClass ($ nameScope ->getClassName ());
1157
+ if ($ classReflection ->getParentClass () === null ) {
1158
+ return new ErrorType ();
1155
1159
1156
- $ constantName = $ constExpr ->name ;
1157
- if (Strings::contains ($ constantName , '* ' )) {
1158
- // convert * into .*? and escape everything else so the constants can be matched against the pattern
1159
- $ pattern = '{^ ' . str_replace ('\\* ' , '.*? ' , preg_quote ($ constantName )) . '$}D ' ;
1160
- $ constantTypes = [];
1161
- foreach ($ classReflection ->getNativeReflection ()->getReflectionConstants () as $ reflectionConstant ) {
1162
- $ classConstantName = $ reflectionConstant ->getName ();
1163
- if (Strings::match ($ classConstantName , $ pattern ) === null ) {
1164
- continue ;
1165
- }
1160
+ }
1166
1161
1167
- if ($ classReflection ->isEnum () && $ classReflection ->hasEnumCase ($ classConstantName )) {
1168
- $ constantTypes [] = new EnumCaseObjectType ($ classReflection ->getName (), $ classConstantName );
1169
- continue ;
1162
+ $ className = $ classReflection ->getParentClass ()->getName ();
1170
1163
}
1164
+ break ;
1165
+ }
1166
+ }
1171
1167
1172
- $ declaringClassName = $ reflectionConstant ->getDeclaringClass ()->getName ();
1173
- if (!$ this ->getReflectionProvider ()->hasClass ($ declaringClassName )) {
1174
- continue ;
1175
- }
1168
+ if (!isset ($ className )) {
1169
+ $ className = $ nameScope ->resolveStringName ($ constExpr ->className );
1170
+ }
1176
1171
1177
- $ constantTypes [] = $ this ->initializerExprTypeResolver ->getType (
1178
- $ reflectionConstant ->getValueExpression (),
1179
- InitializerExprContext::fromClassReflection (
1180
- $ this ->getReflectionProvider ()->getClass ($ declaringClassName ),
1181
- ),
1182
- );
1183
- }
1172
+ if (!$ this ->getReflectionProvider ()->hasClass ($ className )) {
1173
+ return new ErrorType ();
1174
+ }
1184
1175
1185
- if (count ($ constantTypes ) === 0 ) {
1186
- return new ErrorType ();
1176
+ $ classReflection = $ this ->getReflectionProvider ()->getClass ($ className );
1177
+
1178
+ $ constantName = $ constExpr ->name ;
1179
+ if (Strings::contains ($ constantName , '* ' )) {
1180
+ // convert * into .*? and escape everything else so the constants can be matched against the pattern
1181
+ $ pattern = '{^ ' . str_replace ('\\* ' , '.*? ' , preg_quote ($ constantName )) . '$}D ' ;
1182
+ $ constantTypes = [];
1183
+ foreach ($ classReflection ->getNativeReflection ()->getReflectionConstants () as $ reflectionConstant ) {
1184
+ $ classConstantName = $ reflectionConstant ->getName ();
1185
+ if (Strings::match ($ classConstantName , $ pattern ) === null ) {
1186
+ continue ;
1187
1187
}
1188
1188
1189
- return TypeCombinator::union (...$ constantTypes );
1190
- }
1189
+ if ($ classReflection ->isEnum () && $ classReflection ->hasEnumCase ($ classConstantName )) {
1190
+ $ constantTypes [] = new EnumCaseObjectType ($ classReflection ->getName (), $ classConstantName );
1191
+ continue ;
1192
+ }
1191
1193
1192
- if (!$ classReflection ->hasConstant ($ constantName )) {
1193
- return new ErrorType ();
1194
- }
1194
+ $ declaringClassName = $ reflectionConstant ->getDeclaringClass ()->getName ();
1195
+ if (!$ this ->getReflectionProvider ()->hasClass ($ declaringClassName )) {
1196
+ continue ;
1197
+ }
1195
1198
1196
- if ($ classReflection ->isEnum () && $ classReflection ->hasEnumCase ($ constantName )) {
1197
- return new EnumCaseObjectType ($ classReflection ->getName (), $ constantName );
1199
+ $ constantTypes [] = $ this ->initializerExprTypeResolver ->getType (
1200
+ $ reflectionConstant ->getValueExpression (),
1201
+ InitializerExprContext::fromClassReflection (
1202
+ $ this ->getReflectionProvider ()->getClass ($ declaringClassName ),
1203
+ ),
1204
+ );
1198
1205
}
1199
1206
1200
- $ reflectionConstant = $ classReflection ->getNativeReflection ()->getReflectionConstant ($ constantName );
1201
- if ($ reflectionConstant === false ) {
1207
+ if (count ($ constantTypes ) === 0 ) {
1202
1208
return new ErrorType ();
1203
1209
}
1204
- $ declaringClass = $ reflectionConstant ->getDeclaringClass ();
1205
1210
1206
- return $ this -> initializerExprTypeResolver -> getType ( $ reflectionConstant -> getValueExpression (), InitializerExprContext:: fromClass ( $ declaringClass -> getName (), $ declaringClass -> getFileName () ?: null ) );
1211
+ return TypeCombinator:: union (... $ constantTypes );
1207
1212
}
1208
1213
1209
- if ($ constExpr instanceof ConstExprFloatNode ) {
1210
- return new ConstantFloatType (( float ) $ constExpr -> value );
1214
+ if (! $ classReflection -> hasConstant ( $ constantName ) ) {
1215
+ return new ErrorType ( );
1211
1216
}
1212
1217
1213
- if ($ constExpr instanceof ConstExprIntegerNode ) {
1214
- return new ConstantIntegerType (( int ) $ constExpr -> value );
1218
+ if ($ classReflection -> isEnum () && $ classReflection -> hasEnumCase ( $ constantName ) ) {
1219
+ return new EnumCaseObjectType ( $ classReflection -> getName (), $ constantName );
1215
1220
}
1216
1221
1217
- if ($ constExpr instanceof ConstExprStringNode) {
1218
- return new ConstantStringType ($ constExpr ->value );
1222
+ $ reflectionConstant = $ classReflection ->getNativeReflection ()->getReflectionConstant ($ constantName );
1223
+ if ($ reflectionConstant === false ) {
1224
+ return new ErrorType ();
1219
1225
}
1226
+ $ declaringClass = $ reflectionConstant ->getDeclaringClass ();
1220
1227
1221
- return new ErrorType ( );
1228
+ return $ this -> initializerExprTypeResolver -> getType ( $ reflectionConstant -> getValueExpression (), InitializerExprContext:: fromClass ( $ declaringClass -> getName (), $ declaringClass -> getFileName () ?: null ) );
1222
1229
}
1223
1230
1224
1231
private function resolveOffsetAccessNode (OffsetAccessTypeNode $ typeNode , NameScope $ nameScope ): Type
0 commit comments