private GenericMetadataSupport resolveGenericType(Type type, Method method) { if (type instanceof Class) { return new NotGenericReturnTypeSupport(this, type); } if (type instanceof ParameterizedType) { return new ParameterizedReturnType(this, method.getTypeParameters(), (ParameterizedType) type); } if (type instanceof TypeVariable) { return new TypeVariableReturnType(this, method.getTypeParameters(), (TypeVariable<?>) type); } throw new MockitoException("Ouch, it shouldn't happen, type '" + type.getClass().getCanonicalName() + "' on method : '" + method.toGenericString() + "' is not supported : " + type); }
/** * @return Returns an array with the extracted raw types of {@link #extraInterfaces()}. * @see #extractRawTypeOf(java.lang.reflect.Type) */ public Class<?>[] rawExtraInterfaces() { List<Type> extraInterfaces = extraInterfaces(); List<Class<?>> rawExtraInterfaces = new ArrayList<Class<?>>(); for (Type extraInterface : extraInterfaces) { Class<?> rawInterface = extractRawTypeOf(extraInterface); // avoid interface collision with actual raw type (with typevariables, resolution ca be quite aggressive) if(!rawType().equals(rawInterface)) { rawExtraInterfaces.add(rawInterface); } } return rawExtraInterfaces.toArray(new Class[rawExtraInterfaces.size()]); }
@Override public List<Type> extraInterfaces() { Type type = extractActualBoundedTypeOf(typeVariable); if (type instanceof BoundedType) { return Arrays.asList(((BoundedType) type).interfaceBounds()); } if (type instanceof ParameterizedType) { return Collections.singletonList(type); } if (type instanceof Class) { return Collections.emptyList(); } throw new MockitoException("Cannot extract extra-interfaces from '" + typeVariable + "' : '" + type + "'"); }
private Type extractActualBoundedTypeOf(Type type) { if (type instanceof TypeVariable) { /* If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared on the class definition, such as such as List<E>. */ return extractActualBoundedTypeOf(contextualActualTypeParameters.get(type)); } if (type instanceof BoundedType) { Type actualFirstBound = extractActualBoundedTypeOf(((BoundedType) type).firstBound()); if (!(actualFirstBound instanceof BoundedType)) { return type; // avoid going one step further, ie avoid : O(TypeVar) -> K(TypeVar) -> Some ParamType } return actualFirstBound; } return type; // irrelevant, we don't manage other types as they are not bounded. } }
private void readTypeParameters() { registerTypeParametersOn(typeParameters); }
@Override public Class<?> rawType() { if (rawType == null) { rawType = extractRawTypeOf(typeVariable); } return rawType; }
private void readTypeVariables() { for (Type type : typeVariable.getBounds()) { registerTypeVariablesOn(type); } registerTypeParametersOn(new TypeVariable[] { typeVariable }); registerTypeVariablesOn(getActualTypeArgumentFor(typeVariable)); }
public TypeVariableReturnType(GenericMetadataSupport source, TypeVariable<?>[] typeParameters, TypeVariable<?> typeVariable) { this.typeParameters = typeParameters; this.typeVariable = typeVariable; this.contextualActualTypeParameters = source.contextualActualTypeParameters; readTypeParameters(); readTypeVariables(); }