Search in sources :

Example 1 with WildcardType

use of org.robovm.compiler.util.generic.WildcardType in project robovm by robovm.

the class ObjCBlockPlugin method resolveMethodType.

/**
     * 
     */
private static Type resolveMethodType(SootMethod blockMethod, int paramIndex, Type t, Type[] resolvedArgs, TypeVariable<?>[] typeParameters) {
    if (t instanceof SootClassType) {
        return t;
    }
    if (t instanceof SootTypeType) {
        return t;
    }
    if (t instanceof TypeVariable) {
        int idx = indexOf(((TypeVariable<?>) t).getName(), typeParameters);
        if (idx != -1) {
            Type u = resolvedArgs[idx];
            if (u instanceof TypeVariable) {
                if (((TypeVariable<?>) t).getName().equals(((TypeVariable<?>) u).getName())) {
                    return resolveMethodType(blockMethod, paramIndex, ((TypeVariable<?>) t).getBounds()[0], resolvedArgs, typeParameters);
                }
            }
            return resolveMethodType(blockMethod, paramIndex, resolvedArgs[idx], resolvedArgs, typeParameters);
        }
        throw new CompilerException("Unresolved type variable " + t + " in " + (paramIndex == -1 ? "return type" : "parameter " + (paramIndex + 1)) + " of @Block method " + blockMethod);
    }
    if (t instanceof WildcardType) {
        Type[] upperBounds = ((WildcardType) t).getUpperBounds();
        return resolveMethodType(blockMethod, paramIndex, upperBounds[0], resolvedArgs, typeParameters);
    }
    if (t instanceof ParameterizedType) {
        ImplForType pType = (ImplForType) t;
        ListOfTypes types = new ListOfTypes(pType.getActualTypeArguments().length);
        for (Type arg : pType.getActualTypeArguments()) {
            types.add(resolveMethodType(blockMethod, paramIndex, arg, resolvedArgs, typeParameters));
        }
        return new ImplForType((ImplForType) pType.getOwnerType(), pType.getRawType().getSootClass().getName(), types);
    }
    if (t instanceof GenericArrayType) {
        Type componentType = resolveMethodType(blockMethod, paramIndex, ((GenericArrayType) t).getGenericComponentType(), resolvedArgs, typeParameters);
        return new ImplForArray(componentType);
    }
    throw new CompilerException("Unresolved type " + t + " in " + (paramIndex == -1 ? "return type" : "parameter " + (paramIndex + 1)) + " of @Block method " + blockMethod);
}
Also used : SootClassType(org.robovm.compiler.util.generic.SootClassType) GenericArrayType(org.robovm.compiler.util.generic.GenericArrayType) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) ImplForArray(org.robovm.compiler.util.generic.ImplForArray) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) RefType(soot.RefType) ShortType(soot.ShortType) BooleanType(soot.BooleanType) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) WildcardType(org.robovm.compiler.util.generic.WildcardType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) SootClassType(org.robovm.compiler.util.generic.SootClassType) ByteType(soot.ByteType) Type(org.robovm.compiler.util.generic.Type) DoubleType(soot.DoubleType) GenericArrayType(org.robovm.compiler.util.generic.GenericArrayType) FloatType(soot.FloatType) IntType(soot.IntType) ImplForType(org.robovm.compiler.util.generic.ImplForType) CharType(soot.CharType) LongType(soot.LongType) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) PrimType(soot.PrimType) VoidType(soot.VoidType) WildcardType(org.robovm.compiler.util.generic.WildcardType) TypeVariable(org.robovm.compiler.util.generic.TypeVariable) CompilerException(org.robovm.compiler.CompilerException) ListOfTypes(org.robovm.compiler.util.generic.ListOfTypes) ImplForType(org.robovm.compiler.util.generic.ImplForType)

Example 2 with WildcardType

use of org.robovm.compiler.util.generic.WildcardType in project robovm by robovm.

the class ObjCBlockPlugin method resolveActualTypeArgs.

/**
     * Resolves the actual generic type arguments for a base class, as viewed from a subclass or implementation.
     * 
     * @param offspring class or interface subclassing or extending the base type
     * @param base base class
     * @param actualArgs the actual type arguments passed to the offspring class
     * @return actual generic type arguments, must match the type parameters of the offspring class. If omitted, the
     * type parameters will be used instead.
     * 
     * This code was copied from
     * http://stackoverflow.com/questions/17297308/how-do-i-resolve-the-actual-type-for-a-generic-return-type-using-reflection
     * and changed slightly.
     */
protected static Type[] resolveActualTypeArgs(SootClassType offspring, SootClassType base, Type... actualArgs) {
    TypeVariable<?>[] typeParameters = offspring.getTypeParameters();
    //  If actual types are omitted, the type parameters will be used instead.
    if (actualArgs.length == 0) {
        actualArgs = typeParameters;
    }
    // map type parameters into the actual types
    Map<String, Type> typeVariables = new HashMap<>();
    for (int i = 0; i < actualArgs.length; i++) {
        TypeVariable<?> typeVariable = (TypeVariable<?>) typeParameters[i];
        Type t = actualArgs[i];
        if (t instanceof WildcardType) {
            // If actual arg is ? it will have an upper bound of java.lang.Object but the
            // TypeVariable could specify a more specific type.
            Type upper = ((WildcardType) t).getUpperBounds()[0];
            if (upper instanceof SootClassType) {
                if ("java.lang.Object".equals(((SootClassType) upper).getSootClass().getName())) {
                    actualArgs[i] = typeVariable.getBounds()[0];
                }
            }
        }
        typeVariables.put(typeVariable.getName(), actualArgs[i]);
    }
    // Find direct ancestors (superclass, interfaces)
    List<Type> ancestors = new LinkedList<Type>();
    if (offspring.getGenericSuperclass() != null) {
        ancestors.add(offspring.getGenericSuperclass());
    }
    for (Type t : offspring.getGenericInterfaces()) {
        ancestors.add(t);
    }
    // Recurse into ancestors (superclass, interfaces)
    for (Type type : ancestors) {
        if (type instanceof SootClassType) {
            // ancestor is non-parameterized. Recurse only if it matches the base class.
            SootClassType ancestorClass = (SootClassType) type;
            if (base.isAssignableFrom(ancestorClass)) {
                Type[] result = resolveActualTypeArgs(ancestorClass, base);
                if (result != null) {
                    return result;
                }
            }
        }
        if (type instanceof ParameterizedType) {
            // ancestor is parameterized. Recurse only if the raw type matches the base class.
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type rawType = parameterizedType.getRawType();
            if (rawType instanceof SootClassType) {
                SootClassType rawTypeClass = (SootClassType) rawType;
                if (base.isAssignableFrom(rawTypeClass)) {
                    parameterizedType = resolveParameterizedType(parameterizedType, typeVariables);
                    Type[] result = resolveActualTypeArgs(rawTypeClass, base, parameterizedType.getActualTypeArguments());
                    if (result != null) {
                        return result;
                    }
                }
            }
        }
    }
    // we have a result if we reached the base class.
    return offspring.equals(base) ? actualArgs : null;
}
Also used : SootClassType(org.robovm.compiler.util.generic.SootClassType) HashMap(java.util.HashMap) LinkedList(java.util.LinkedList) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) RefType(soot.RefType) ShortType(soot.ShortType) BooleanType(soot.BooleanType) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) WildcardType(org.robovm.compiler.util.generic.WildcardType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) SootClassType(org.robovm.compiler.util.generic.SootClassType) ByteType(soot.ByteType) Type(org.robovm.compiler.util.generic.Type) DoubleType(soot.DoubleType) GenericArrayType(org.robovm.compiler.util.generic.GenericArrayType) FloatType(soot.FloatType) IntType(soot.IntType) ImplForType(org.robovm.compiler.util.generic.ImplForType) CharType(soot.CharType) LongType(soot.LongType) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) PrimType(soot.PrimType) VoidType(soot.VoidType) WildcardType(org.robovm.compiler.util.generic.WildcardType) TypeVariable(org.robovm.compiler.util.generic.TypeVariable)

Aggregations

GenericArrayType (org.robovm.compiler.util.generic.GenericArrayType)2 ImplForType (org.robovm.compiler.util.generic.ImplForType)2 ParameterizedType (org.robovm.compiler.util.generic.ParameterizedType)2 SootClassType (org.robovm.compiler.util.generic.SootClassType)2 SootMethodType (org.robovm.compiler.util.generic.SootMethodType)2 SootTypeType (org.robovm.compiler.util.generic.SootTypeType)2 Type (org.robovm.compiler.util.generic.Type)2 TypeVariable (org.robovm.compiler.util.generic.TypeVariable)2 WildcardType (org.robovm.compiler.util.generic.WildcardType)2 BooleanType (soot.BooleanType)2 ByteType (soot.ByteType)2 CharType (soot.CharType)2 DoubleType (soot.DoubleType)2 FloatType (soot.FloatType)2 IntType (soot.IntType)2 LongType (soot.LongType)2 PrimType (soot.PrimType)2 RefType (soot.RefType)2 ShortType (soot.ShortType)2 VoidType (soot.VoidType)2