@@ -142,9 +142,9 @@ public void addConstructor(CtConstructor<?> ctConstructor) {
142
142
@ Override
143
143
public void addTypeReference (CtRole role , CtTypeReference <?> typeReference ) {
144
144
switch (role ) {
145
- case SUPER_TYPE :
146
- ctClass .setSuperclass (typeReference );
147
- return ;
145
+ case SUPER_TYPE :
146
+ ctClass .setSuperclass (typeReference );
147
+ return ;
148
148
}
149
149
super .addTypeReference (role , typeReference );
150
150
}
@@ -291,8 +291,7 @@ public void visitField(Field field) {
291
291
Set <ModifierKind > modifiers = RtHelper .getModifiers (field .getModifiers ());
292
292
if (modifiers .contains (ModifierKind .STATIC )
293
293
&& modifiers .contains (ModifierKind .PUBLIC )
294
- && (field .getType ().isPrimitive () || String .class .isAssignableFrom (field .getType ()))
295
- ) {
294
+ && (field .getType ().isPrimitive () || String .class .isAssignableFrom (field .getType ()))) {
296
295
CtLiteral <Object > defaultExpression = factory .createLiteral (field .get (null ));
297
296
ctField .setDefaultExpression (defaultExpression );
298
297
}
@@ -356,13 +355,13 @@ public <T extends GenericDeclaration> void visitTypeParameter(TypeVariable<T> pa
356
355
@ Override
357
356
public void addTypeReference (CtRole role , CtTypeReference <?> typeReference ) {
358
357
switch (role ) {
359
- case SUPER_TYPE :
360
- if (typeParameter .getSuperclass () != null ) {
361
- typeParameter .setSuperclass (typeParameter .getFactory ().createIntersectionTypeReferenceWithBounds (Arrays .asList (typeParameter .getSuperclass (), typeReference )));
362
- } else {
363
- typeParameter .setSuperclass (typeReference );
364
- }
365
- return ;
358
+ case SUPER_TYPE :
359
+ if (typeParameter .getSuperclass () != null ) {
360
+ typeParameter .setSuperclass (typeParameter .getFactory ().createIntersectionTypeReferenceWithBounds (Arrays .asList (typeParameter .getSuperclass (), typeReference )));
361
+ } else {
362
+ typeParameter .setSuperclass (typeReference );
363
+ }
364
+ return ;
366
365
}
367
366
super .addTypeReference (role , typeReference );
368
367
}
@@ -379,13 +378,6 @@ public <T extends GenericDeclaration> void visitTypeParameterReference(CtRole ro
379
378
typeParameterReference .setSimpleName (parameter .getName ());
380
379
381
380
RuntimeBuilderContext runtimeBuilderContext = new TypeReferenceRuntimeBuilderContext (parameter , typeParameterReference );
382
- if (contexts .contains (runtimeBuilderContext )) {
383
- // we are in the case of a loop
384
- exit ();
385
- enter (new TypeReferenceRuntimeBuilderContext (Object .class , factory .Type ().OBJECT ));
386
- return ;
387
- }
388
-
389
381
GenericDeclaration genericDeclaration = parameter .getGenericDeclaration ();
390
382
for (RuntimeBuilderContext context : contexts ) {
391
383
CtTypeParameter typeParameter = context .getTypeParameter (genericDeclaration , parameter .getName ());
@@ -404,9 +396,14 @@ public <T extends GenericDeclaration> void visitTypeParameterReference(CtRole ro
404
396
405
397
@ Override
406
398
public void visitTypeReference (CtRole role , ParameterizedType type ) {
399
+ Type [] typeArguments = type .getActualTypeArguments ();
400
+ if (role == CtRole .SUPER_TYPE && typeArguments .length > 0 ) {
401
+ if (hasProcessedRecursiveBound (typeArguments )) {
402
+ return ;
403
+ }
404
+ }
407
405
final CtTypeReference <?> ctTypeReference = factory .Core ().createTypeReference ();
408
406
ctTypeReference .setSimpleName (((Class ) type .getRawType ()).getSimpleName ());
409
-
410
407
RuntimeBuilderContext context = new TypeReferenceRuntimeBuilderContext (type , ctTypeReference ) {
411
408
412
409
@ Override
@@ -418,27 +415,26 @@ public void addType(CtType<?> aType) {
418
415
419
416
enter (context );
420
417
super .visitTypeReference (role , type );
421
-
422
- // in case of a loop we have replaced a context:
423
- // we do not want to addTypeName then
424
- // and we have to rely on the instance reference to check that
425
- boolean contextStillExisting = false ;
426
- for (RuntimeBuilderContext context1 : contexts ) {
427
- contextStillExisting = contextStillExisting || (context1 == context );
428
- }
429
418
exit ();
430
419
431
- if (contextStillExisting ) {
432
- contexts .peek ().addTypeReference (role , ctTypeReference );
433
- }
420
+ contexts .peek ().addTypeReference (role , ctTypeReference );
434
421
}
435
422
436
423
@ Override
437
424
public void visitTypeReference (CtRole role , WildcardType type ) {
438
425
final CtWildcardReference wildcard = factory .Core ().createWildcardReference ();
439
- //looks like type.getUpperBounds() always returns single value array with Object.class
426
+ //type.getUpperBounds() returns at least a single value array with Object.class
440
427
//so we cannot distinguish between <? extends Object> and <?>, which must be upper==true too!
441
- wildcard .setUpper ((type .getLowerBounds () != null && type .getLowerBounds ().length > 0 ) == false );
428
+ wildcard .setUpper ((type .getLowerBounds ().length > 0 ) == false );
429
+
430
+ if (!type .getUpperBounds ()[0 ].equals (Object .class )) {
431
+ if (hasProcessedRecursiveBound (type .getUpperBounds ())) {
432
+ return ;
433
+ }
434
+ }
435
+ if (hasProcessedRecursiveBound (type .getLowerBounds ())) {
436
+ return ;
437
+ }
442
438
443
439
enter (new TypeReferenceRuntimeBuilderContext (type , wildcard ));
444
440
super .visitTypeReference (role , type );
@@ -447,7 +443,21 @@ public void visitTypeReference(CtRole role, WildcardType type) {
447
443
contexts .peek ().addTypeReference (role , wildcard );
448
444
}
449
445
450
-
446
+ // check if a type parameter that is bounded by some expression involving itself has already been processed
447
+ private boolean hasProcessedRecursiveBound (Type [] types ) {
448
+ for (Type type : types ) {
449
+ if (type instanceof TypeVariable ) {
450
+ TypeVariable t = (TypeVariable ) type ;
451
+ final CtTypeParameterReference typeParameterReference = factory .Core ().createTypeParameterReference ();
452
+ typeParameterReference .setSimpleName (t .getName ());
453
+ RuntimeBuilderContext runtimeBuilderContext = new TypeReferenceRuntimeBuilderContext (t , typeParameterReference );
454
+ if (contexts .contains (runtimeBuilderContext )) {
455
+ return true ;
456
+ }
457
+ }
458
+ }
459
+ return false ;
460
+ }
451
461
452
462
@ Override
453
463
public <T > void visitArrayReference (CtRole role , final Type typeArray ) {
@@ -457,9 +467,9 @@ public <T> void visitArrayReference(CtRole role, final Type typeArray) {
457
467
@ Override
458
468
public void addTypeReference (CtRole role , CtTypeReference <?> typeReference ) {
459
469
switch (role ) {
460
- case DECLARING_TYPE :
461
- arrayTypeReference .setDeclaringType (typeReference );
462
- return ;
470
+ case DECLARING_TYPE :
471
+ arrayTypeReference .setDeclaringType (typeReference );
472
+ return ;
463
473
}
464
474
arrayTypeReference .setComponentType (typeReference );
465
475
}
0 commit comments