geantyref icon indicating copy to clipboard operation
geantyref copied to clipboard

Add a way to resolve bounded types directly

Open leonard84 opened this issue 3 years ago • 2 comments

Coming from https://github.com/coekie/gentyref/issues/5#issuecomment-968368485

I gave it a spin and came up with this:

  public static Type getResolvedReturnType(Method m, Type declaringType) {
    return resolveTypeVariableIfNecessary(GenericTypeReflector.getReturnType(m, declaringType));
  }

  public static Type getResolvedFieldType(Field f, Type declaringType) {
    return resolveTypeVariableIfNecessary(GenericTypeReflector.getFieldType(f, declaringType));
  }

  public static List<Type> getResolvedParameterTypes(Method m, Type declaringType) {
    return Arrays.stream(GenericTypeReflector.getParameterTypes(m, declaringType))
      .map(ReflectionUtil::resolveTypeVariableIfNecessary)
      .collect(Collectors.toList());
  }

  private static Type resolveTypeVariableIfNecessary(Type returnType) {
    if (returnType instanceof TypeVariable) {
      AnnotatedType annotatedType = GenericTypeReflector.annotate(returnType);
      return GenericTypeReflector.reduceBounded(annotatedType).getType();
    }
    return returnType;
  }

it seems to work, but I'm not sure its the best way. You can see the full change here https://github.com/leonard84/spock/tree/replace_gentyref_with_geantyref

I think that it might have value to have something like this in GenericTypeReflector directly, this way it could be optimized as well, the current implementation has to re-annotate the type that was discarded in GenericTypeReflector internally.

leonard84 avatar Nov 22 '21 23:11 leonard84

I'll look into adding an optional leaf transformation step during type resolution, that way an extra descent down the structure wouldn't be needed. But at the very least I'll add methods that avoid re-annotation. I'll notify you here when the next version is out.

Btw, you might want to always call reduceBounded in your current code, not only for variables, because I assume you'd also want wildcards and parameterized types reduced e.g. ? extends Number to Number or List<T extends Number to List<Number> etc.

kaqqao avatar Nov 23 '21 09:11 kaqqao

I just wanted to avoid calling reduceBounded for the cases where it is already a simple type, e.g., String.

Do you have any performance measurements? Is it worth caching results or is it so cheap to calculate that it doesn't really matter?

On a related note, what would you suggest to resolve cases like this one below, where I have access to the parameter array of an invocation and would like to know the return type for that invocation? Of course the class param could be one of multiple parameters at different indexes and with different type variables.

<T> T create(Class<T> clazz)

leonard84 avatar Nov 23 '21 13:11 leonard84