Search in sources :

Example 1 with TypeVariable

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

the class ObjCBlockPlugin method resolveTargetMethodSignature.

protected static Type[] resolveTargetMethodSignature(SootMethod blockMethod, SootMethod targetMethod, Type blockParamType) {
    if (targetMethod.getTag("SignatureTag") == null) {
        // Not a generic method.
        Type[] result = new Type[targetMethod.getParameterCount() + 1];
        result[0] = new SootTypeType(targetMethod.getReturnType());
        for (int i = 1; i < result.length; i++) {
            result[i] = new SootTypeType(targetMethod.getParameterType(i - 1));
        }
        return result;
    }
    SootClassType base = new SootClassType(targetMethod.getDeclaringClass());
    TypeVariable<?>[] typeParameters = base.getTypeParameters();
    SootClassType offspring = null;
    Type[] actualArgs = null;
    if (blockParamType instanceof SootClassType) {
        offspring = (SootClassType) blockParamType;
        actualArgs = new Type[0];
    } else if (blockParamType instanceof ParameterizedType) {
        offspring = (SootClassType) ((ParameterizedType) blockParamType).getRawType();
        actualArgs = ((ParameterizedType) blockParamType).getActualTypeArguments();
    }
    Type[] resolvedArgs = resolveActualTypeArgs(offspring, base, actualArgs);
    Type[] result = new Type[targetMethod.getParameterCount() + 1];
    SootMethodType targetMethodType = new SootMethodType(targetMethod);
    result[0] = resolveMethodType(blockMethod, -1, targetMethodType.getGenericReturnType(), resolvedArgs, typeParameters);
    Type[] genericParameterTypes = targetMethodType.getGenericParameterTypes();
    for (int i = 1; i < result.length; i++) {
        result[i] = resolveMethodType(blockMethod, i - 1, genericParameterTypes[i - 1], resolvedArgs, typeParameters);
    }
    return result;
}
Also used : ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) SootClassType(org.robovm.compiler.util.generic.SootClassType) 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) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) TypeVariable(org.robovm.compiler.util.generic.TypeVariable) SootMethodType(org.robovm.compiler.util.generic.SootMethodType)

Example 2 with TypeVariable

use of org.robovm.compiler.util.generic.TypeVariable 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 3 with TypeVariable

use of org.robovm.compiler.util.generic.TypeVariable 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)

Example 4 with TypeVariable

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

the class ObjCBlockPlugin method resolveParameterizedType.

/**
     * Loops through all type arguments and replaces type variables with the
     * actually known types.
     */
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Map<String, Type> typeVariables) {
    List<Type> resolvedTypes = new LinkedList<Type>();
    for (Type t : parameterizedType.getActualTypeArguments()) {
        if (t instanceof TypeVariable<?>) {
            Type resolvedType = typeVariables.get(((TypeVariable<?>) t).getName());
            if (resolvedType instanceof ParameterizedType) {
                resolvedType = resolveParameterizedType((ParameterizedType) resolvedType, typeVariables);
            }
            resolvedTypes.add(resolvedType != null ? resolvedType : t);
        } else if (t instanceof ParameterizedType) {
            ParameterizedType pType = (ParameterizedType) t;
            resolvedTypes.add(resolveParameterizedType(pType, typeVariables));
        } else {
            resolvedTypes.add(t);
        }
    }
    ListOfTypes types = new ListOfTypes(resolvedTypes.toArray(new Type[resolvedTypes.size()]));
    return new ImplForType(null, parameterizedType.getRawType().toString(), types);
}
Also used : 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) TypeVariable(org.robovm.compiler.util.generic.TypeVariable) ListOfTypes(org.robovm.compiler.util.generic.ListOfTypes) ImplForType(org.robovm.compiler.util.generic.ImplForType) LinkedList(java.util.LinkedList)

Aggregations

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