Skip to content

Commit

Permalink
refactor: getBoundingType returns Object by default (#1672)
Browse files Browse the repository at this point in the history
  • Loading branch information
surli authored and monperrus committed Nov 6, 2017
1 parent 58a65de commit dc6fbc7
Show file tree
Hide file tree
Showing 12 changed files with 56 additions and 34 deletions.
7 changes: 7 additions & 0 deletions src/main/java/spoon/reflect/factory/TypeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -655,4 +655,11 @@ public <T> CtIntersectionTypeReference<T> createIntersectionTypeReferenceWithBou
return intersectionRef;
}

/**
* Returns the default bounding type value
*/
public CtTypeReference getDefaultBoundingType() {
return OBJECT;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,10 @@ public interface CtTypeParameterReference extends CtTypeReference<Object> {
@Override
@UnsettableProperty
<T extends CtActualTypeContainer> T setActualTypeArguments(List<? extends CtTypeReference<?>> actualTypeArguments);

/**
* Returns true if this has the default bounding type that is java.lang.Object (which basically means that there is no bound)
*/
@DerivedProperty
boolean isDefaultBoundingType();
}
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ public void visitCtTypeParameter(CtTypeParameter typeParameter) {
} else {
printer.writeIdentifier(ref.getSimpleName());
}
if (ref.getBoundingType() != null) {
if (!ref.isDefaultBoundingType() || !ref.getBoundingType().isImplicit()) {
if (ref.isUpper()) {
printer.writeSpace().writeKeyword("extends").writeSpace();
} else {
Expand Down Expand Up @@ -1570,7 +1570,8 @@ public void visitCtWildcardReference(CtWildcardReference wildcardReference) {
}
elementPrinterHelper.writeAnnotations(wildcardReference);
printer.writeSeparator("?");
if (wildcardReference.getBoundingType() != null) {
// we ignore printing "extends Object" except if it's explicit
if (!wildcardReference.isDefaultBoundingType() || !wildcardReference.getBoundingType().isImplicit()) {
if (wildcardReference.isUpper()) {
printer.writeSpace().writeKeyword("extends").writeSpace();
} else {
Expand Down
15 changes: 8 additions & 7 deletions src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,12 @@ CtReference getDeclaringReferenceFromImports(char[] expectedName) {
char[][] packageName = CharOperation.subarray(anImport.getImportName(), 0, anImport.getImportName().length - indexDeclaring);
char[][] className = CharOperation.subarray(anImport.getImportName(), anImport.getImportName().length - indexDeclaring, anImport.getImportName().length - (indexDeclaring - 1));
PackageBinding aPackage;
if (packageName.length != 0) {
aPackage = environment.createPackage(packageName);
} else {
aPackage = null;
}
try {
if (packageName.length != 0) {
aPackage = environment.createPackage(packageName);
} else {
aPackage = null;
}
final MissingTypeBinding declaringType = environment.createMissingType(aPackage, className);
this.jdtTreeBuilder.getContextBuilder().ignoreComputeImports = true;
final CtTypeReference<Object> typeReference = getTypeReference(declaringType);
Expand Down Expand Up @@ -765,8 +765,9 @@ <T> CtTypeReference<T> getTypeReference(TypeBinding binding) {
bounds = false;
bindingCache.put(binding, ref);
List<CtTypeReference<?>> bounds = new ArrayList<>();
if (((CtTypeParameterReference) ref).getBoundingType() != null) {
bounds.add(((CtTypeParameterReference) ref).getBoundingType());
CtTypeParameterReference typeParameterReference = (CtTypeParameterReference) ref;
if (!(typeParameterReference.isDefaultBoundingType())) { // if it's object we can ignore it
bounds.add(typeParameterReference.getBoundingType());
}
for (ReferenceBinding superInterface : b.superInterfaces) {
bounds.add(getTypeReference(superInterface));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ public class CtTypeParameterReferenceImpl extends CtTypeReferenceImpl<Object> im

public CtTypeParameterReferenceImpl() {
super();
// calling null will set the default value of boundingType
this.setBoundingType(null);
}

@Override
public boolean isDefaultBoundingType() {
return (getBoundingType().equals(getFactory().Type().getDefaultBoundingType()));
}

@Override
Expand Down Expand Up @@ -97,7 +104,7 @@ public boolean isPrimitive() {
@SuppressWarnings("unchecked")
public Class<Object> getActualClass() {
if (isUpper()) {
if (getBoundingType() == null) {
if (isDefaultBoundingType()) {
return (Class<Object>) getTypeErasure().getActualClass();
}
return (Class<Object>) getBoundingType().getActualClass();
Expand Down Expand Up @@ -134,7 +141,7 @@ public <T extends CtTypeParameterReference> T addBound(CtTypeReference<?> bound)
if (bound == null) {
return (T) this;
}
if (getBoundingType() == null) {
if (isDefaultBoundingType()) {
setBoundingType(bound);
} else if (getBoundingType() instanceof CtIntersectionTypeReference<?>) {
getBoundingType().asCtIntersectionTypeReference().addBound(bound);
Expand All @@ -149,7 +156,7 @@ public <T extends CtTypeParameterReference> T addBound(CtTypeReference<?> bound)

@Override
public boolean removeBound(CtTypeReference<?> bound) {
if (bound == null || getBoundingType() == null) {
if (bound == null || isDefaultBoundingType()) {
return false;
}
if (getBoundingType() instanceof CtIntersectionTypeReference<?>) {
Expand All @@ -162,16 +169,6 @@ public boolean removeBound(CtTypeReference<?> bound) {

@Override
public CtTypeReference<?> getBoundingType() {
if (superType != null) {
/*
* Spoon expects that superType is null on many places.
* But sometime there is Object in it, which has same meaning like null in this case
* But EqualsVisitor returns false that it is not equal
*/
if (Object.class.getName().equals(superType.getQualifiedName())) {
return null;
}
}
return superType;
}

Expand All @@ -180,6 +177,14 @@ public <T extends CtTypeParameterReference> T setBoundingType(CtTypeReference<?>
if (superType != null) {
superType.setParent(this);
}

// ugly but else make testSetterInNodes failed
if (superType == null) { // if null, set bounding type to object
superType = getFactory().Type().objectType();
superType.setImplicit(true);
superType.setParent(this);
}

getFactory().getEnvironment().getModelChangeListener().onObjectUpdate(this, BOUNDING_TYPE, superType, this.superType);
this.superType = superType;
return (T) this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private CtTypeReference<?> adaptTypeParameterReference(CtTypeParameterReference
private CtTypeReference<?> adaptTypeParameterReferenceBoundingType(CtTypeParameterReference typeParamRef, CtTypeReference<?> boundingType) {
CtTypeParameterReference typeParamRefAdapted = typeParamRef.clone();
typeParamRefAdapted.setParent(typeParamRef.getParent());
typeParamRefAdapted.setBoundingType(boundingType == null ? null : adaptType(boundingType));
typeParamRefAdapted.setBoundingType(boundingType.equals(boundingType.getFactory().Type().getDefaultBoundingType()) ? null : adaptType(boundingType));
return typeParamRefAdapted;
}

Expand Down
7 changes: 4 additions & 3 deletions src/main/java/spoon/support/visitor/ClassTypingContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -572,14 +572,14 @@ private boolean isSubTypeArg(CtTypeReference<?> subArg, CtTypeReference<?> super
if (superArg instanceof CtWildcardReference) {
CtWildcardReference wr = (CtWildcardReference) superArg;
CtTypeReference<?> superBound = wr.getBoundingType();
if (superBound == null) {
if (superBound.equals(wr.getFactory().Type().OBJECT)) {
//everything extends from object, nothing is super of Object
return wr.isUpper();
}
if (subArg instanceof CtWildcardReference) {
CtWildcardReference subWr = (CtWildcardReference) subArg;
CtTypeReference<?> subBound = subWr.getBoundingType();
if (subBound == null) {
if (subBound.equals(wr.getFactory().Type().OBJECT)) {
//nothing is super of object
return false;
}
Expand Down Expand Up @@ -690,7 +690,8 @@ private boolean isSameSignatureLikeScopeMethod(CtExecutable<?> thatExecutable, b
if (thisType.getActualTypeArguments().isEmpty() && thatType.getActualTypeArguments().size() == 1) {
CtTypeReference actualTA = thatType.getActualTypeArguments().get(0);
if (actualTA instanceof CtWildcardReference) {
if (((CtWildcardReference) actualTA).getBoundingType() == null) {
CtWildcardReference wildcardReference = (CtWildcardReference) actualTA;
if (wildcardReference.isDefaultBoundingType()) {
thatType.setActualTypeArguments(Collections.EMPTY_LIST);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/spoon/support/visitor/SignaturePrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public <T> void visitCtTypeReference(CtTypeReference<T> reference) {
@Override
public void visitCtTypeParameterReference(CtTypeParameterReference ref) {
write(ref.getQualifiedName());
if (ref.getBoundingType() != null) {
if (!ref.isDefaultBoundingType() || !ref.getBoundingType().isImplicit()) {
if (ref.isUpper()) {
write(" extends ");
} else {
Expand Down
1 change: 0 additions & 1 deletion src/test/java/spoon/test/factory/FactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,5 +200,4 @@ public void specificationCoreFactoryCreate() throws Exception {
assertTrue(itf.getActualClass().isInstance(o));
}
}

}
6 changes: 3 additions & 3 deletions src/test/java/spoon/test/generics/GenericsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.junit.Test;
import spoon.Launcher;
import spoon.MavenLauncher;
import spoon.SpoonModelBuilder;
import spoon.compiler.SpoonResourceHelper;
import spoon.reflect.code.BinaryOperatorKind;
Expand Down Expand Up @@ -502,7 +503,7 @@ public void testGenericWithExtendsInDeclaration() throws Exception {

final CtMethod<?> apply = panini.getMethodsByName("apply").get(0);
assertEquals(1, apply.getType().getActualTypeArguments().size());
assertEquals("?", apply.getType().getActualTypeArguments().get(0).toString());
assertEquals("? super java.lang.Object", apply.getType().getActualTypeArguments().get(0).toString());

assertEquals(1, apply.getParameters().get(0).getType().getActualTypeArguments().size());
assertEquals("? extends java.lang.Long", apply.getParameters().get(0).getType().getActualTypeArguments().get(0).toString());
Expand Down Expand Up @@ -1206,7 +1207,7 @@ public void testDiamondComplexGenericsRxJava() {
CtTypeReference actualTA = call.getType().getActualTypeArguments().get(0);
assertTrue(actualTA instanceof CtWildcardReference);
assertEquals("?", actualTA.getSimpleName());
assertTrue( ((CtWildcardReference)actualTA).getBoundingType() == null );
assertTrue( ((CtWildcardReference)actualTA).isDefaultBoundingType() );
invocationDetected = true;
}
}
Expand Down Expand Up @@ -1402,5 +1403,4 @@ public void testIsGenericTypeEqual() {
MainTest.checkParentConsistency(launcher.getFactory().getModel().getRootPackage());
MainTest.checkParentConsistency(adaptedMethod);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public void testMultiReferenceBetweenMethodsWithGenericInSameClass() throws Exce

//T has more information in the invocation than its declaration because of the argument type
//assertEquals(expectedMethod1, refsMethod2.get(0).getDeclaration());
assertEquals(execRefsMethods2.getSignature(), "method1(T extends java.lang.String)");
assertEquals("method1(T extends java.lang.String)", execRefsMethods2.getSignature());
assertEquals(expectedMethod1, refsMethod2.get(1).getDeclaration());
assertEquals(expectedMethod5, refsMethod2.get(2).getDeclaration());
}
Expand Down
6 changes: 4 additions & 2 deletions src/test/java/spoon/test/reference/TypeReferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -510,15 +510,17 @@ public void testClearBoundsForTypeParameterReference() throws Exception {

reference.setBounds(null);

assertNull(reference.getBoundingType());
assertEquals(factory.Type().OBJECT, reference.getBoundingType());
assertTrue(reference.isDefaultBoundingType());

reference.addBound(factory.Type().createReference(String.class));

assertNotNull(reference.getBoundingType());

reference.setBounds(new ArrayList<>());

assertNull(reference.getBoundingType());
assertEquals(factory.Type().OBJECT, reference.getBoundingType());
assertTrue(reference.isDefaultBoundingType());
}

@Test
Expand Down

0 comments on commit dc6fbc7

Please sign in to comment.