Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

review fix: Manage generics from Interface in shadow mode #1914

Merged
merged 46 commits into from
May 23, 2018
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2bead30
test: superInterface on shadow type miss actual type arguments
pvojtechovsky Mar 11, 2018
45f01a5
Provide a first mechanism to manage generic in interfaces even in sha…
surli Mar 15, 2018
9634fe2
improve test
pvojtechovsky Mar 15, 2018
05ad69d
Fix last assert
surli Mar 16, 2018
5a9e5f7
Try to fix TypeParameter resolution
surli Mar 16, 2018
5298e3a
Fix last erroring test
surli Mar 16, 2018
b6f01aa
Fix checkstyle
surli Mar 16, 2018
abee610
improve test
pvojtechovsky Mar 17, 2018
7fe0735
Change the visitor to manage generic interfaces directly
surli Mar 19, 2018
602fb25
Fix some tests
surli Mar 19, 2018
7aebb87
test qualified names of superinterfaces
pvojtechovsky Mar 19, 2018
f154c96
Fix qualified name
surli Mar 20, 2018
2727805
test: parent of CtTypeReference is initialized, check getSuperClass
pvojtechovsky Mar 21, 2018
ab54f46
fix parent of CtTypeReferences.getSuperInterfaces()
pvojtechovsky Mar 21, 2018
e8b0154
Manage superClass: first fix
surli Mar 22, 2018
737569c
Merge remote-tracking branch 'inria/master' into fix-superiface-args
surli Mar 22, 2018
f6c463c
Fix documentation
surli Mar 22, 2018
9a950a6
test bound type of act type args of type references
pvojtechovsky Mar 22, 2018
1f55f22
added comments
pvojtechovsky Mar 22, 2018
674bf52
Improve JavaReflectionVisitor to manage a cache of visited generics p…
surli Mar 23, 2018
ae4154f
Fix checkstyle and fix embarassing Enum<E extends Enum<E>> loops in g…
surli Mar 23, 2018
ab1cc3f
test: shadow CtType equals source based CtType
pvojtechovsky Mar 24, 2018
0774320
Manage the case when <T extends Object> implicitely
surli Mar 26, 2018
5341c64
Fix a bug with annotation
surli Mar 26, 2018
e911fee
Merge remote-tracking branch 'inria/master' into fix-superiface-args
surli Apr 4, 2018
e7a9218
Fix case of annotations
surli Apr 4, 2018
a019d0a
Fix some more errors
surli Apr 4, 2018
ffc691b
support repetitive usage of EqualsChecker
pvojtechovsky Apr 4, 2018
2ae66d8
improve error printing
pvojtechovsky Apr 4, 2018
1e9ed50
fixes
pvojtechovsky Apr 15, 2018
1d69b71
JUST FOR DEBUGGING
pvojtechovsky Apr 15, 2018
1047448
up
pvojtechovsky May 17, 2018
aeab784
Merge remote-tracking branch 'origin/master' into fix-superiface-args
pvojtechovsky May 18, 2018
9f77ac4
up
pvojtechovsky May 19, 2018
b66acca
ignore implicit Enum constructor, ignore synthetic fields
pvojtechovsky May 19, 2018
0f80026
fix: setModifiers(Collections.emptySet()) resets modifiers now
pvojtechovsky May 17, 2018
6a37d65
enum value is always public static final, ignore synthetic typemembers
pvojtechovsky May 19, 2018
e390048
fix handling of upper bound of WildcardType
pvojtechovsky May 19, 2018
a3aa771
fix: actual type arguments on array type reference
pvojtechovsky May 19, 2018
1e47c9f
feat: EqualsVisitor can report which attribute is not equal
pvojtechovsky May 19, 2018
2fc84bb
fix and ignore differences in modifiers
pvojtechovsky May 19, 2018
10c7e4f
fix: visibility of enum values
pvojtechovsky May 20, 2018
9a60870
handle static interface methods with body well
pvojtechovsky May 20, 2018
f48be3b
fixes
pvojtechovsky May 20, 2018
de9a7a4
Merge remote-tracking branch 'origin/master' into fix-superiface-args
May 22, 2018
ce156d5
Merge remote-tracking branch 'origin/master' into fix-superiface-args
May 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions src/main/java/spoon/reflect/factory/TypeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import spoon.support.visitor.java.JavaReflectionTreeBuilder;

import java.lang.annotation.Annotation;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -314,19 +315,31 @@ public <T> CtArrayTypeReference<T> createArrayReference(String qualifiedName) {
return array;
}

public <T> CtTypeReference<T> createReference(Class<T> type) {
return createReference(type, false);
}

/**
* Creates a reference to a simple type
*/
public <T> CtTypeReference<T> createReference(Class<T> type) {
public <T> CtTypeReference<T> createReference(Class<T> type, boolean includingFormalTypeParameter) {
if (type == null) {
return null;
}
if (type.isArray()) {
CtArrayTypeReference<T> array = factory.Core().createArrayTypeReference();
array.setComponentType(createReference(type.getComponentType()));
array.setComponentType(createReference(type.getComponentType(), includingFormalTypeParameter));
return array;
}
return createReference(type.getName());
CtTypeReference typeReference = createReference(type.getName());

if (includingFormalTypeParameter) {
for (TypeVariable<Class<T>> generic : type.getTypeParameters()) {
typeReference.addActualTypeArgument(createTypeParameterReference(generic.getName()));
}
}

return typeReference;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,21 @@ public CtTypeParameter getDeclaration() {

CtElement e = this;
CtElement parent = getParent();

if (parent instanceof CtTypeReference) {
if (parent.isParentInitialized() == false) {
return null;
if (!parent.isParentInitialized()) {
// we might enter in that case because of a call
// of getSuperInterfaces() for example
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case should not happen after my change in CtTypeReference#getSuperInterfaces. Let's rollback this change. WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked and I have the following broken test if I remove it: GenericsTest#testTypeParameterReferenceAsActualTypeArgument.

CtTypeReference typeReference = (CtTypeReference) parent;
e = typeReference.getTypeDeclaration();
if (e == null) {
return null;
}
} else {
parent = parent.getParent();
}
parent = parent.getParent();
}

if (parent instanceof CtExecutableReference) {
CtExecutableReference parentExec = (CtExecutableReference) parent;
if (!parentExec.getDeclaringType().equals(e)) {
Expand All @@ -222,9 +231,10 @@ public CtTypeParameter getDeclaration() {
} else {
e = e.getParent(CtFormalTypeDeclarer.class);
}

} else {
e = e.getParent(CtFormalTypeDeclarer.class);
if (!(e instanceof CtFormalTypeDeclarer)) {
e = e.getParent(CtFormalTypeDeclarer.class);
}
}

// case #1: we're a type of a method parameter, a local variable, ...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import spoon.reflect.visitor.CtVisitor;
import spoon.support.SpoonClassNotFoundException;
import spoon.support.reflect.declaration.CtElementImpl;
import spoon.support.util.QualifiedNameBasedSortedSet;
import spoon.support.util.RtHelper;
import spoon.support.visitor.ClassTypingContext;

Expand Down Expand Up @@ -507,21 +506,12 @@ public CtTypeReference<?> getSuperclass() {

@Override
public Set<CtTypeReference<?>> getSuperInterfaces() {
CtType<?> t = getDeclaration();
//we need a interface type references whose parent is connected to CtType, otherwise TypeParameterReferences cannot be resolved well
CtType<?> t = getTypeDeclaration();
if (t != null) {
return t.getSuperInterfaces();
} else {
Class<?> c = getActualClass();
Class<?>[] sis = c.getInterfaces();
if ((sis != null) && (sis.length > 0)) {
Set<CtTypeReference<?>> set = new QualifiedNameBasedSortedSet<CtTypeReference<?>>();
for (Class<?> si : sis) {
set.add(getFactory().Type().createReference(si));
}
return set;
}
}
return Collections.emptySet();
throw new SpoonException("Cannot provide CtType for " + getQualifiedName());
}

@Override
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/spoon/support/visitor/ClassTypingContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,9 @@ private List<CtTypeReference<?>> resolveTypeParameters(List<CtTypeReference<?>>
if (typeRef instanceof CtTypeParameterReference) {
CtTypeParameterReference typeParamRef = (CtTypeParameterReference) typeRef;
CtTypeParameter typeParam = typeParamRef.getDeclaration();
if (typeParam == null) {
throw new SpoonException("The typeParam " + typeRef.getQualifiedName() + " declaration cannot be resolved");
}
CtFormalTypeDeclarer declarer = typeParam.getTypeParameterDeclarer();
typeRef = resolveTypeParameter(declarer, typeParamRef, typeParam, typeRef);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,18 @@ public void addArrayReference(CtArrayTypeReference<?> typeReference) {
contexts.peek().addArrayReference(arrayTypeReference);
}

@Override
public <T> void visitClassReference(ParameterizedType type) {
final CtTypeReference<Object> typeReference = factory.Core().createTypeReference();
typeReference.setSimpleName(((Class) type.getRawType()).getSimpleName());

enter(new TypeReferenceRuntimeBuilderContext(typeReference));
super.visitClassReference(type);
exit();

contexts.peek().addClassReference(typeReference);
}

@Override
public <T> void visitClassReference(Class<T> clazz) {
final CtTypeReference<Object> typeReference = factory.Core().createTypeReference();
Expand All @@ -462,6 +474,18 @@ public <T> void visitInterfaceReference(Class<T> anInterface) {
contexts.peek().addInterfaceReference(typeReference);
}

@Override
public <T> void visitInterfaceReference(ParameterizedType anInterface) {
final CtTypeReference<Object> typeReference = factory.Core().createTypeReference();
typeReference.setSimpleName(((Class) anInterface.getRawType()).getSimpleName());

enter(new TypeReferenceRuntimeBuilderContext(typeReference));
super.visitInterfaceReference(anInterface);
exit();

contexts.peek().addInterfaceReference(typeReference);
}

private void setModifier(CtModifiable ctModifiable, int modifiers) {
if (Modifier.isAbstract(modifiers)) {
ctModifiable.addModifier(ModifierKind.ABSTRACT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,20 @@ interface JavaReflectionVisitor {
/** Visits a class as an array reference */
<T> void visitArrayReference(Class<T> typeArray);

/** Visits a type as a class reference */
<T> void visitClassReference(ParameterizedType type);

/** Visits a class as a class reference */
<T> void visitClassReference(Class<T> clazz);

<T> void visitClassReference(Type type);

/** Visits a class as an interface reference */
<T> void visitInterfaceReference(Class<T> anInterface);

/** Visits a {@link ParameterizedType} representing an interface with a type parameter. */
<T> void visitInterfaceReference(ParameterizedType parameterizedType);

/** Visits a {@link Type} representing an interface. */
<T> void visitInterfaceReference(Type type);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ public <T> void visitClass(Class<T> clazz) {
clazz.getPackage();
}
if (clazz.getSuperclass() != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it ok that the check is not on getGenericSuperclass?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I certainly should change that one for safety.

visitClassReference(clazz.getSuperclass());
visitClassReference(clazz.getGenericSuperclass());
}
for (Class<?> anInterface : clazz.getInterfaces()) {
for (Type anInterface : clazz.getGenericInterfaces()) {
visitInterfaceReference(anInterface);
}
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
Expand Down Expand Up @@ -82,7 +82,7 @@ public <T> void visitInterface(Class<T> clazz) {
if (clazz.getPackage() != null) {
clazz.getPackage();
}
for (Class<?> anInterface : clazz.getInterfaces()) {
for (Type anInterface : clazz.getGenericInterfaces()) {
visitInterfaceReference(anInterface);
}
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
Expand Down Expand Up @@ -338,6 +338,32 @@ public <T> void visitArrayReference(Class<T> typeArray) {
}
}

@Override
public <T> void visitClassReference(ParameterizedType type) {
Type rawType = type.getRawType();

if (!(rawType instanceof Class)) {
throw new UnsupportedOperationException("Rawtype of the parameterized type should be a class.");
}

@SuppressWarnings("unchecked")
Class<T> classRaw = (Class<T>) rawType;
if (classRaw.getPackage() != null) {
visitPackage(classRaw.getPackage());
}
if (classRaw.getEnclosingClass() != null) {
visitClassReference(classRaw.getEnclosingClass());
}

for (Type generic : type.getActualTypeArguments()) {
if (generic instanceof TypeVariable) {
visitTypeParameter((TypeVariable<?>) generic);
} else {
visitType(generic);
}
}
}

@Override
public <T> void visitClassReference(Class<T> clazz) {
if (clazz.getPackage() != null && clazz.getEnclosingClass() == null) {
Expand All @@ -348,6 +374,17 @@ public <T> void visitClassReference(Class<T> clazz) {
}
}

@Override
public <T> void visitClassReference(Type type) {
if (type instanceof Class) {
visitClassReference((Class) type);
} else if (type instanceof ParameterizedType) {
visitClassReference((ParameterizedType) type);
} else {
throw new UnsupportedOperationException("Only type with class or ParameterizedType are supported.");
}
}

@Override
public <T> void visitInterfaceReference(Class<T> type) {
if (type.getPackage() != null) {
Expand All @@ -356,6 +393,48 @@ public <T> void visitInterfaceReference(Class<T> type) {
if (type.getEnclosingClass() != null) {
visitClassReference(type.getEnclosingClass());
}

for (TypeVariable<Class<T>> generic : type.getTypeParameters()) {
visitTypeParameter(generic);
}
}

@Override
public <T> void visitInterfaceReference(ParameterizedType type) {
Type rawType = type.getRawType();

if (!(rawType instanceof Class)) {
throw new UnsupportedOperationException("Rawtype of the parameterized type should be a class.");
}

@SuppressWarnings("unchecked")
Class<T> classRaw = (Class<T>) rawType;

if (classRaw.getPackage() != null) {
visitPackage(classRaw.getPackage());
}
if (classRaw.getEnclosingClass() != null) {
visitClassReference(classRaw.getEnclosingClass());
}

for (Type generic : type.getActualTypeArguments()) {
if (generic instanceof TypeVariable) {
visitTypeParameter((TypeVariable<?>) generic);
} else {
visitType(generic);
}
}
}

@Override
public <T> void visitInterfaceReference(Type type) {
if (type instanceof Class) {
visitInterfaceReference((Class) type);
} else if (type instanceof ParameterizedType) {
visitInterfaceReference((ParameterizedType) type);
} else {
throw new UnsupportedOperationException("Only type with class or ParameterizedType are supported.");
}
}

private <T> List<RtMethod> getDeclaredMethods(Class<T> clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtPackage;
import spoon.reflect.declaration.CtTypeParameter;
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;

Expand Down Expand Up @@ -54,4 +55,9 @@ public void addTypeName(CtTypeReference<?> ctTypeReference) {
public void addAnnotation(CtAnnotation<Annotation> ctAnnotation) {
typeReference.addAnnotation(ctAnnotation);
}

@Override
public void addFormalType(CtTypeParameter parameterRef) {
typeReference.addActualTypeArgument(parameterRef.getReference());
}
}
Loading