@@ -154,6 +154,7 @@ private function listFieldResolvedValueErrors(
154154 $ objectType ,
155155 $ fieldName ,
156156 $ resolverClassType ,
157+ [],
157158 );
158159
159160 foreach ($ errors as $ error ) {
@@ -186,6 +187,7 @@ private function listFieldResolvedValueErrors(
186187
187188
188189 /**
190+ * @param list<string> $alreadyVisitedFields
189191 * @return array{list<PHPStan\Type\Type>, list<string>}
190192 */
191193 private function listFieldResolvedValueTypes (
@@ -194,15 +196,23 @@ private function listFieldResolvedValueTypes(
194196 string $ objectType ,
195197 string $ fieldName ,
196198 PHPStan \Type \ObjectType $ resolverClassType ,
199+ array $ alreadyVisitedFields ,
197200 ): array
198201 {
199202 $ errors = [];
200203 $ types = [];
201204
205+ $ parentTypes = $ this ->listObjectTypeResolvedValueTypes (
206+ $ scope ,
207+ $ schemaServiceOraculum ,
208+ $ objectType ,
209+ [...$ alreadyVisitedFields , "$ objectType. $ fieldName " ],
210+ );
211+
202212 if ($ resolverClassType ->getClassName () === Vojtechdobes \GraphQL \ArrayFieldResolver::class) {
203213 $ offsetType = new PHPStan \Type \Constant \ConstantStringType ($ fieldName );
204214
205- foreach ($ this -> listObjectTypeResolvedValueTypes ( $ scope , $ schemaServiceOraculum , $ objectType ) as $ parentType ) {
215+ foreach ($ parentTypes as $ parentType ) {
206216 if ($ parentType ->isOffsetAccessible ()->yes () === false ) {
207217 $ errors [] = sprintf (
208218 "Resolver %s of field %s expects parent to have array access, but parent is resolved to %s " ,
@@ -225,7 +235,7 @@ private function listFieldResolvedValueTypes(
225235 } elseif ($ resolverClassType ->getClassName () === Vojtechdobes \GraphQL \GetterFieldResolver::class) {
226236 $ methodName = 'get ' . ucfirst ($ fieldName );
227237
228- foreach ($ this -> listObjectTypeResolvedValueTypes ( $ scope , $ schemaServiceOraculum , $ objectType ) as $ parentType ) {
238+ foreach ($ parentTypes as $ parentType ) {
229239 if ($ parentType ->isObject ()->yes () === false ) {
230240 $ errors [] = sprintf (
231241 "Resolver %s of field %s expects parent to be an object, but parent is resolved to %s " ,
@@ -250,7 +260,7 @@ private function listFieldResolvedValueTypes(
250260 }
251261 }
252262 } elseif ($ resolverClassType ->getClassName () === Vojtechdobes \GraphQL \PropertyFieldResolver::class) {
253- foreach ($ this -> listObjectTypeResolvedValueTypes ( $ scope , $ schemaServiceOraculum , $ objectType ) as $ parentType ) {
263+ foreach ($ parentTypes as $ parentType ) {
254264 if ($ parentType ->isObject ()->yes () === false ) {
255265 $ errors [] = sprintf (
256266 "Resolver %s of field %s expects parent to be an object, but parent is resolved to %s " ,
@@ -274,7 +284,7 @@ private function listFieldResolvedValueTypes(
274284 } else {
275285 $ expectedParentType = $ resolverClassType ->getTemplateType (Vojtechdobes \GraphQL \FieldResolver::class, 'TObjectValue ' );
276286
277- foreach ($ this -> listObjectTypeResolvedValueTypes ( $ scope , $ schemaServiceOraculum , $ objectType ) as $ parentType ) {
287+ foreach ($ parentTypes as $ parentType ) {
278288 if ($ expectedParentType ->isSuperTypeOf ($ parentType )->yes () === false ) {
279289 $ errors [] = sprintf (
280290 "Resolver %s of field %s expects parent to be %s, but parent is resolved to %s " ,
@@ -303,12 +313,14 @@ private function listFieldResolvedValueTypes(
303313
304314
305315 /**
316+ * @param list<string> $alreadyVisitedFields
306317 * @return list<PHPStan\Type\Type>
307318 */
308319 private function listObjectTypeResolvedValueTypes (
309320 PHPStan \Analyser \Scope $ scope ,
310321 SchemaServiceOraculum $ schemaServiceOraculum ,
311322 string $ objectType ,
323+ array $ alreadyVisitedFields ,
312324 ): array
313325 {
314326 $ result = [];
@@ -318,12 +330,19 @@ private function listObjectTypeResolvedValueTypes(
318330 }
319331
320332 foreach ($ schemaServiceOraculum ->listFieldsResolvedToObjectType ($ objectType ) as [$ parentObjectType , $ parentFieldName ]) {
333+ $ parentField = "{$ parentObjectType }. {$ parentFieldName }" ;
334+
335+ if (in_array ($ parentField , $ alreadyVisitedFields , true )) {
336+ continue ;
337+ }
338+
321339 [$ parentTypes ] = $ this ->listFieldResolvedValueTypes (
322340 $ scope ,
323341 $ schemaServiceOraculum ,
324342 $ parentObjectType ,
325343 $ parentFieldName ,
326344 $ schemaServiceOraculum ->getFieldResolverType ($ parentObjectType , $ parentFieldName ),
345+ [...$ alreadyVisitedFields , $ parentField ],
327346 );
328347
329348 foreach ($ parentTypes as $ parentType ) {
0 commit comments