use of spoon.reflect.declaration.CtTypeParameter in project spoon by INRIA.
the class CtTypeImpl method isSameParameter.
private boolean isSameParameter(CtMethod<?> method, CtTypeReference<?> ctParameterType, CtTypeReference<?> expectedType) {
if (expectedType instanceof CtTypeParameterReference) {
/*
* the expectedType is a generic parameter whose declaration should be searched in scope of method
* (not in scope of it's parent, where it can found another/wrong type parameter declaration of same name.
*/
CtTypeParameterReference tpr = (CtTypeParameterReference) expectedType;
expectedType = tpr.clone();
expectedType.setParent(method);
if (expectedType.getDeclaration() == null) {
return false;
}
}
if (expectedType instanceof CtTypeParameterReference && ctParameterType instanceof CtTypeParameterReference) {
// both types are generic
if (!ctParameterType.equals(expectedType)) {
return false;
}
} else if (expectedType instanceof CtTypeParameterReference) {
// expectedType type is generic, ctParameterType is real type
if (!expectedType.getTypeErasure().getQualifiedName().equals(ctParameterType.getQualifiedName())) {
return false;
}
} else if (ctParameterType instanceof CtTypeParameterReference) {
// ctParameterType is generic, expectedType type is real type
CtTypeParameter declaration = (CtTypeParameter) ctParameterType.getDeclaration();
if (declaration != null && declaration.getSuperclass() instanceof CtIntersectionTypeReference) {
for (CtTypeReference<?> ctTypeReference : declaration.getSuperclass().asCtIntersectionTypeReference().getBounds()) {
if (ctTypeReference.equals(expectedType)) {
return true;
}
}
} else if (declaration != null && declaration.getSuperclass() != null) {
return declaration.getSuperclass().equals(expectedType);
} else {
return getFactory().Type().objectType().equals(expectedType);
}
} else if (!expectedType.getQualifiedName().equals(ctParameterType.getQualifiedName())) {
// both are real types
return false;
}
return true;
}
use of spoon.reflect.declaration.CtTypeParameter in project spoon by INRIA.
the class AbstractTypingContext method adaptType.
@Override
public CtTypeReference<?> adaptType(CtTypeInformation type) {
CtTypeReference<?> result;
boolean isCopy = false;
if (type instanceof CtTypeReference<?>) {
if (type instanceof CtTypeParameterReference) {
return adaptTypeParameterReference((CtTypeParameterReference) type);
}
result = (CtTypeReference<?>) type;
} else {
if (type instanceof CtTypeParameter) {
return adaptTypeParameter((CtTypeParameter) type);
}
CtType<?> t = (CtType<?>) type;
result = t.getFactory().Type().createReference(t, true);
isCopy = true;
}
if (result.getActualTypeArguments().size() > 0) {
// we have to adapt actual type arguments recursive too
if (isCopy == false) {
CtElement parent = result.getParent();
result = result.clone();
result.setParent(parent);
List<CtTypeReference<?>> actTypeArgs = new ArrayList<>(result.getActualTypeArguments());
for (int i = 0; i < actTypeArgs.size(); i++) {
CtTypeReference adaptedTypeArgs = adaptType(actTypeArgs.get(i));
// for some type argument we might return null to avoid recursive calls
if (adaptedTypeArgs != null) {
actTypeArgs.set(i, adaptedTypeArgs.clone());
}
}
result.setActualTypeArguments(actTypeArgs);
}
}
return result;
}
use of spoon.reflect.declaration.CtTypeParameter in project spoon by INRIA.
the class ClassTypingContext method resolveActualTypeArgumentsOf.
/**
* resolve actual type argument values of the provided type reference
* @param typeRef the reference to the type
* whose actual type argument values has to be resolved in scope of `scope` type
* @return actual type arguments of `typeRef` in scope of `scope` element or null if typeRef is not a super type of `scope`
*/
public List<CtTypeReference<?>> resolveActualTypeArgumentsOf(CtTypeReference<?> typeRef) {
final String typeQualifiedName = typeRef.getQualifiedName();
List<CtTypeReference<?>> args = typeToArguments.get(typeQualifiedName);
if (args != null) {
// the actual type arguments of `type` are already resolved
return args;
}
// resolve hierarchy of enclosing class first.
CtTypeReference<?> enclosingTypeRef = getEnclosingType(typeRef);
if (enclosingTypeRef != null) {
if (enclosingClassTypingContext == null) {
return null;
}
// `type` is inner class. Resolve it's enclosing class arguments first
if (enclosingClassTypingContext.resolveActualTypeArgumentsOf(enclosingTypeRef) == null) {
return null;
}
}
/*
* detect where to start/continue with resolving of super classes and super interfaces
* to found actual type arguments of input `type`
*/
if (lastResolvedSuperclass == null) {
/*
* whole super inheritance hierarchy was already resolved for this level.
* It means that `type` is not a super type of `scope` on the level `level`
*/
return null;
}
final HierarchyListener listener = new HierarchyListener(getVisitedSet());
/*
* remove last resolved class from the list of visited,
* because it would avoid visiting it's super hierarchy
*/
getVisitedSet().remove(lastResolvedSuperclass.getQualifiedName());
/*
* visit super inheritance class hierarchy of lastResolve type of level of `type` to found it's actual type arguments.
*/
((CtElement) lastResolvedSuperclass).map(new SuperInheritanceHierarchyFunction().includingSelf(false).returnTypeReferences(true).setListener(listener)).forEach(new CtConsumer<CtTypeReference<?>>() {
@Override
public void accept(CtTypeReference<?> typeRef) {
/*
* typeRef is a reference from sub type to super type.
* It contains actual type arguments in scope of sub type,
* which are going to be substituted as arguments to formal type parameters of super type
*/
String superTypeQualifiedName = typeRef.getQualifiedName();
List<CtTypeReference<?>> actualTypeArguments = typeRef.getActualTypeArguments();
if (actualTypeArguments.isEmpty()) {
// may be they are not set - check whether type declares some generic parameters
List<CtTypeParameter> typeParams;
try {
CtType<?> type = typeRef.getTypeDeclaration();
typeParams = type.getFormalCtTypeParameters();
} catch (final SpoonClassNotFoundException e) {
if (typeRef.getFactory().getEnvironment().getNoClasspath()) {
typeParams = Collections.emptyList();
} else {
throw e;
}
}
if (typeParams.size() > 0) {
// yes, there are generic type parameters. Reference should use actualTypeArguments computed from their bounds
actualTypeArguments = new ArrayList<>(typeParams.size());
for (CtTypeParameter typeParam : typeParams) {
actualTypeArguments.add(typeParam.getTypeErasure());
}
}
}
List<CtTypeReference<?>> superTypeActualTypeArgumentsResolvedFromSubType = resolveTypeParameters(actualTypeArguments);
// Remember actual type arguments of `type`
typeToArguments.put(superTypeQualifiedName, superTypeActualTypeArgumentsResolvedFromSubType);
if (typeQualifiedName.equals(superTypeQualifiedName)) {
/*
* we have found actual type arguments of input `type`
* We can finish. But only after all interfaces of last visited class are processed too
*/
listener.foundArguments = superTypeActualTypeArgumentsResolvedFromSubType;
}
}
});
if (listener.foundArguments == null) {
/*
* superclass was not found. We have scanned whole hierarchy
*/
lastResolvedSuperclass = null;
}
return listener.foundArguments;
}
use of spoon.reflect.declaration.CtTypeParameter in project spoon by INRIA.
the class MethodTypingContext method setMethod.
public MethodTypingContext setMethod(CtMethod<?> method) {
actualTypeArguments = getTypeReferences(method.getFormalCtTypeParameters());
if (classTypingContext != null) {
CtType<?> declType = method.getDeclaringType();
if (declType == null) {
throw new SpoonException("Cannot use method without declaring type as scope of method typing context");
}
if (classTypingContext.getAdaptationScope() != declType) {
// the method is declared in different type. We have to adapt it to required classTypingContext
if (classTypingContext.isSubtypeOf(declType.getReference()) == false) {
throw new SpoonException("Cannot create MethodTypingContext for method declared in different ClassTypingContext");
}
/*
* The method is declared in an supertype of classTypingContext.
* Create virtual scope method by adapting generic types of supertype method to required scope
*/
Factory factory = method.getFactory();
// create new scopeMethod, which is directly used during adaptation of it's parameters
CtMethod<?> adaptedMethod = factory.Core().createMethod();
adaptedMethod.setParent(classTypingContext.getAdaptationScope());
adaptedMethod.setModifiers(method.getModifiers());
adaptedMethod.setSimpleName(method.getSimpleName());
for (CtTypeParameter typeParam : method.getFormalCtTypeParameters()) {
CtTypeParameter newTypeParam = typeParam.clone();
newTypeParam.setSuperclass(adaptTypeForNewMethod(typeParam.getSuperclass()));
adaptedMethod.addFormalCtTypeParameter(newTypeParam);
}
// now the formal type parameters of the scopeMethod are defined, so we can use adaptType of this MethodTypingContext
scopeMethod = adaptedMethod;
for (CtTypeReference<? extends Throwable> thrownType : method.getThrownTypes()) {
adaptedMethod.addThrownType((CtTypeReference<Throwable>) adaptType(thrownType.clone()));
}
// adapt return type
adaptedMethod.setType((CtTypeReference) adaptType(method.getType()));
// adapt parameters
List<CtParameter<?>> adaptedParams = new ArrayList<>(method.getParameters().size());
for (CtParameter<?> parameter : method.getParameters()) {
adaptedParams.add(factory.Executable().createParameter(null, adaptType(parameter.getType()), parameter.getSimpleName()));
}
adaptedMethod.setParameters(adaptedParams);
method = adaptedMethod;
}
}
scopeMethod = method;
return this;
}
use of spoon.reflect.declaration.CtTypeParameter in project spoon by INRIA.
the class MethodTypingContext method adaptTypeForNewMethod.
private CtTypeReference<?> adaptTypeForNewMethod(CtTypeReference<?> typeRef) {
if (typeRef == null) {
return null;
}
if (typeRef instanceof CtTypeParameterReference) {
CtTypeParameterReference typeParamRef = (CtTypeParameterReference) typeRef;
CtTypeParameter typeParam = typeParamRef.getDeclaration();
if (typeParam == null) {
throw new SpoonException("Declaration of the CtTypeParameter should not be null.");
}
if (typeParam.getTypeParameterDeclarer() instanceof CtExecutable) {
// the parameter is declared in scope of Method or Constructor
return typeRef.clone();
}
}
// it is not type reference of scopeMethod. Adapt it using classTypingContext
return classTypingContext.adaptType(typeRef);
}
Aggregations