1717import org .apache .commons .collections .CollectionUtils ;
1818import org .jetbrains .annotations .NotNull ;
1919
20+ import java .util .HashSet ;
2021import java .util .List ;
2122import java .util .Objects ;
23+ import java .util .Set ;
2224import java .util .concurrent .ConcurrentHashMap ;
2325
2426/**
@@ -41,7 +43,7 @@ public StructureAndCommentInfo resolveFromClass(PsiClassReferenceType psiClassRe
4143 if (psiClassReferenceType == null ) {
4244 return null ;
4345 }
44- StructureAndCommentInfo root = resolveFromClass0 (psiClassReferenceType , "" , 1 );
46+ StructureAndCommentInfo root = resolveFromClass0 (null , psiClassReferenceType , "" , 1 );
4547 psiClassCache .clear ();
4648 earlyCache .clear ();
4749 return root ;
@@ -134,7 +136,7 @@ public StructureAndCommentInfo resolveFromReturnVal(PsiTypeElement returnTypeEle
134136 return structureAndCommentInfo ;
135137 }
136138
137- private StructureAndCommentInfo resolveFromClass0 (PsiClassReferenceType psiClassReferenceType , String fieldPrefix , int level ) {
139+ private StructureAndCommentInfo resolveFromClass0 (StructureAndCommentInfo parent , PsiClassReferenceType psiClassReferenceType , String fieldPrefix , int level ) {
138140 if (psiClassReferenceType == null ) {
139141 return null ;
140142 }
@@ -146,14 +148,14 @@ private StructureAndCommentInfo resolveFromClass0(PsiClassReferenceType psiClass
146148 psiClass = replacePsiClassIfFromJar (psiClass );
147149 String qualifiedName = psiClass .getQualifiedName ();
148150 PsiTypeUtil .resolvePsiClassParameter (psiClassReferenceType );
149- if (qualifiedName != null ) {
150- if (psiClassCache .containsKey (qualifiedName )) {
151- return null ;
152- }
153- if (earlyCache .containsKey (qualifiedName )) {
154- return null ;
155- }
156- }
151+ // if (qualifiedName != null) {
152+ // if (psiClassCache.containsKey(qualifiedName)) {
153+ // return null;
154+ // }
155+ // if (earlyCache.containsKey(qualifiedName)) {
156+ // return null;
157+ // }
158+ // }
157159 String clazzTypeName = psiClass .getName ();
158160 if (BaseTypeUtil .isBaseTypeOrObject (psiClass )) {
159161 return null ;
@@ -165,6 +167,7 @@ private StructureAndCommentInfo resolveFromClass0(PsiClassReferenceType psiClass
165167 return null ;
166168 }
167169 StructureAndCommentInfo root = new StructureAndCommentInfo ();
170+ root .setParent (parent );
168171 root .setFieldType (clazzTypeName );
169172 root .setOriginalFieldType (clazzTypeName );
170173 root .setFieldTypeCode (FieldType .POJO .getType ());
@@ -241,18 +244,12 @@ private StructureAndCommentInfo resolveByPsiType(StructureAndCommentInfo parent,
241244 if (parentPsiClass == null ) {
242245 ExceptionUtil .handleSyntaxError (parentPsiClassReferenceType .getCanonicalText ());
243246 }
244- String qualifiedName = parentPsiClass .getQualifiedName ();
245- String canonicalText = psiFieldType .getCanonicalText ();
246- if (Objects .equals (qualifiedName , canonicalText )) {
247- // 自己依赖自己
248- return null ;
249- }
250247 }
251- return resolveByPsiType0 (FieldType .BASE .getType (), fieldName , psiFieldType , commentInfo , "%s" , fieldPrefix , level );
248+ return resolveByPsiType0 (parent , FieldType .BASE .getType (), fieldName , psiFieldType , commentInfo , "%s" , fieldPrefix , level );
252249 }
253250
254251 @ SuppressWarnings ("AlibabaMethodTooLong" )
255- private StructureAndCommentInfo resolveByPsiType0 (int fieldTypeCode , String fieldName , PsiType psiFieldType , CommentInfo commentInfo , String typeNameFormat , String fieldPrefix , int level ) {
252+ private StructureAndCommentInfo resolveByPsiType0 (StructureAndCommentInfo parent , int fieldTypeCode , String fieldName , PsiType psiFieldType , CommentInfo commentInfo , String typeNameFormat , String fieldPrefix , int level ) {
256253 boolean hidden = commentInfo .isHidden (false );
257254 fieldName = commentInfo .getName (fieldName );
258255 hidden = handleHidden (fieldName , psiFieldType , hidden );
@@ -283,7 +280,7 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
283280 PsiArrayType psiArrayType = (PsiArrayType ) psiFieldType ;
284281 PsiType componentType = psiArrayType .getComponentType ();
285282 String newTypeNameFormat = String .format (typeNameFormat , "%s[]" );
286- return resolveByPsiType0 (FieldType .ARRAY .getType (), fieldName , componentType , commentInfo , newTypeNameFormat , fieldPrefix , level );
283+ return resolveByPsiType0 (parent , FieldType .ARRAY .getType (), fieldName , componentType , commentInfo , newTypeNameFormat , fieldPrefix , level );
287284 }
288285
289286 boolean isReferenceType = psiFieldType instanceof PsiClassReferenceType ;
@@ -315,7 +312,7 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
315312 PsiType realPsiType = PsiTypeUtil .getRealPsiType (psiFieldType , project , null );
316313 if (realPsiType != null ) {
317314 String newTypeNameFormat = String .format (typeNameFormat , "%s" );
318- return resolveByPsiType0 (fieldTypeCode , fieldName , realPsiType , commentInfo , newTypeNameFormat , fieldPrefix , level );
315+ return resolveByPsiType0 (parent , fieldTypeCode , fieldName , realPsiType , commentInfo , newTypeNameFormat , fieldPrefix , level );
319316 }
320317
321318 // 枚举
@@ -325,19 +322,19 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
325322
326323 // List
327324 if (PsiTypeUtil .isPsiTypeFromList (psiFieldType , project )) {
328- return getStructureAndCommentInfoByCollection (fieldName , commentInfo , typeNameFormat , fieldPrefix , level ,
325+ return getStructureAndCommentInfoByCollection (parent , fieldName , commentInfo , typeNameFormat , fieldPrefix , level ,
329326 structureAndCommentInfo , parameters , "List<%s>" , FieldType .LIST );
330327 }
331328
332329 // Set
333330 if (PsiTypeUtil .isPsiTypeFromSet (psiFieldType , project )) {
334- return getStructureAndCommentInfoByCollection (fieldName , commentInfo , typeNameFormat , fieldPrefix , level ,
331+ return getStructureAndCommentInfoByCollection (parent , fieldName , commentInfo , typeNameFormat , fieldPrefix , level ,
335332 structureAndCommentInfo , parameters , "Set<%s>" , FieldType .SET );
336333 }
337334
338335 // Collection 放在后面判断, 优先级低一些
339336 if (PsiTypeUtil .isPsiTypeFromCollection (psiFieldType , project )) {
340- return getStructureAndCommentInfoByCollection (fieldName , commentInfo , typeNameFormat , fieldPrefix , level ,
337+ return getStructureAndCommentInfoByCollection (parent , fieldName , commentInfo , typeNameFormat , fieldPrefix , level ,
341338 structureAndCommentInfo , parameters , "Collection<%s>" , FieldType .COLLECTION );
342339 }
343340
@@ -358,7 +355,7 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
358355 }
359356 keyTypeName = keyType .getPresentableText ();
360357 String newTypeNameFormat = String .format (typeNameFormat , "Map<" + keyTypeName + ", %s>" );
361- return resolveByPsiType0 (FieldType .MAP .getType (), fieldName , valueType , commentInfo , newTypeNameFormat , fieldPrefix , level );
358+ return resolveByPsiType0 (parent , FieldType .MAP .getType (), fieldName , valueType , commentInfo , newTypeNameFormat , fieldPrefix , level );
362359 } else {
363360 return structureAndCommentInfo ;
364361 }
@@ -371,7 +368,15 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
371368 if (MapKeyConstant .FIELD_PREFIX_INIT .equals (fieldPrefix )) {
372369 fieldPrefix0 = "" ;
373370 }
374- StructureAndCommentInfo structureAndCommentInfoChild = resolveFromClass0 (psiClassReferenceType , fieldPrefix0 , level + 1 );
371+
372+ boolean hasRecursion = checkRecursion (parent );
373+ if (hasRecursion ) {
374+ return null ;
375+ }
376+
377+ structureAndCommentInfo .setPsiClass (resolveClass );
378+ structureAndCommentInfo .setParent (parent );
379+ StructureAndCommentInfo structureAndCommentInfoChild = resolveFromClass0 (structureAndCommentInfo , psiClassReferenceType , fieldPrefix0 , level + 1 );
375380 if (structureAndCommentInfoChild != null && structureAndCommentInfoChild .getChildren ().size () > 0 ) {
376381 structureAndCommentInfo .setLeaf (false );
377382 structureAndCommentInfo .copyChild (structureAndCommentInfoChild .getChildren ());
@@ -388,27 +393,49 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
388393 return structureAndCommentInfo ;
389394 }
390395
391- private boolean handleHidden (String fieldName , PsiType psiFieldType , boolean oldVal ) {
392- if (FieldJumpUtil .isFieldNameNeedJump (fieldName )) {
393- return true ;
394- }
395- String typeQname = psiFieldType .getCanonicalText ();
396- if (FieldJumpUtil .isFieldTypeNeedJump (typeQname )) {
397- return true ;
396+ private boolean checkRecursion (StructureAndCommentInfo parent ) {
397+ if (parent == null ) {
398+ return false ;
398399 }
399- return oldVal ;
400+ Set <String > uniqueNodeSet = new HashSet <>(32 );
401+ StructureAndCommentInfo current = parent ;
402+ do {
403+ if (current .getFieldTypeCode ().equals (FieldType .POJO .getType ())) {
404+ PsiClass psiClass = current .getPsiClass ();
405+ if (psiClass != null ) {
406+ String qualifiedName = psiClass .getQualifiedName ();
407+ if (uniqueNodeSet .contains (qualifiedName )) {
408+ return true ;
409+ }
410+ uniqueNodeSet .add (qualifiedName );
411+ }
412+ }
413+ current = current .getParent ();
414+ } while (current != null );
415+ return false ;
400416 }
401417
402- private StructureAndCommentInfo getStructureAndCommentInfoByCollection (String fieldName , CommentInfo commentInfo , String typeNameFormat , String fieldPrefix , int level , StructureAndCommentInfo structureAndCommentInfo , PsiType [] parameters , String format , FieldType fieldType ) {
418+ private StructureAndCommentInfo getStructureAndCommentInfoByCollection (StructureAndCommentInfo parent , String fieldName , CommentInfo commentInfo , String typeNameFormat , String fieldPrefix , int level , StructureAndCommentInfo structureAndCommentInfo , PsiType [] parameters , String format , FieldType fieldType ) {
403419 if (parameters .length > 0 ) {
404420 PsiType elementType = parameters [0 ];
405421 String newTypeNameFormat = String .format (typeNameFormat , format );
406- return resolveByPsiType0 (fieldType .getType (), fieldName , elementType , commentInfo , newTypeNameFormat , fieldPrefix , level );
422+ return resolveByPsiType0 (parent , fieldType .getType (), fieldName , elementType , commentInfo , newTypeNameFormat , fieldPrefix , level );
407423 } else {
408424 return structureAndCommentInfo ;
409425 }
410426 }
411427
428+ private boolean handleHidden (String fieldName , PsiType psiFieldType , boolean oldVal ) {
429+ if (FieldJumpUtil .isFieldNameNeedJump (fieldName )) {
430+ return true ;
431+ }
432+ String typeQname = psiFieldType .getCanonicalText ();
433+ if (FieldJumpUtil .isFieldTypeNeedJump (typeQname )) {
434+ return true ;
435+ }
436+ return oldVal ;
437+ }
438+
412439 private boolean checkHiddenRequest (String fieldPrefix , String fieldName ) {
413440 String fieldKey = fieldPrefix + fieldName ;
414441 List <String > hiddenKeys = ResolverContextHolder .getData (ResolverContextHolder .HIDDEN_KEYS );
0 commit comments