Search in sources :

Example 36 with CtTypeParameter

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;
}
Also used : CtTypeParameterReference(spoon.reflect.reference.CtTypeParameterReference) CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) CtIntersectionTypeReference(spoon.reflect.reference.CtIntersectionTypeReference)

Example 37 with CtTypeParameter

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;
}
Also used : CtTypeParameterReference(spoon.reflect.reference.CtTypeParameterReference) CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) CtType(spoon.reflect.declaration.CtType) CtTypeReference(spoon.reflect.reference.CtTypeReference) CtElement(spoon.reflect.declaration.CtElement) ArrayList(java.util.ArrayList)

Example 38 with CtTypeParameter

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;
}
Also used : SuperInheritanceHierarchyFunction(spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction) CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) ArrayList(java.util.ArrayList) CtType(spoon.reflect.declaration.CtType) CtTypeReference(spoon.reflect.reference.CtTypeReference) SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException) ArrayList(java.util.ArrayList) List(java.util.List)

Example 39 with CtTypeParameter

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;
}
Also used : CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) SpoonException(spoon.SpoonException) ArrayList(java.util.ArrayList) Factory(spoon.reflect.factory.Factory) CtParameter(spoon.reflect.declaration.CtParameter)

Example 40 with CtTypeParameter

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);
}
Also used : CtTypeParameterReference(spoon.reflect.reference.CtTypeParameterReference) CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) SpoonException(spoon.SpoonException) CtExecutable(spoon.reflect.declaration.CtExecutable)

Aggregations

CtTypeParameter (spoon.reflect.declaration.CtTypeParameter)43 Test (org.junit.Test)25 MainTest (spoon.test.main.MainTest)12 Factory (spoon.reflect.factory.Factory)10 CtTypeParameterReference (spoon.reflect.reference.CtTypeParameterReference)10 Launcher (spoon.Launcher)9 CtClass (spoon.reflect.declaration.CtClass)9 CtTypeReference (spoon.reflect.reference.CtTypeReference)8 NamedElementFilter (spoon.reflect.visitor.filter.NamedElementFilter)7 ModelUtils.createFactory (spoon.testing.utils.ModelUtils.createFactory)7 ArrayList (java.util.ArrayList)6 CtMethod (spoon.reflect.declaration.CtMethod)6 CtType (spoon.reflect.declaration.CtType)5 LikeCtClass (spoon.test.generics.testclasses2.LikeCtClass)4 SpoonException (spoon.SpoonException)3 CtFormalTypeDeclarer (spoon.reflect.declaration.CtFormalTypeDeclarer)3 CtLambda (spoon.reflect.code.CtLambda)2 CtElement (spoon.reflect.declaration.CtElement)2 CtExecutable (spoon.reflect.declaration.CtExecutable)2 CtInterface (spoon.reflect.declaration.CtInterface)2