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;
}
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);
}
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;
}
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);
}
Aggregations