Skip to content

Instantly share code, notes, and snippets.

@FroMage
Created December 13, 2019 09:16
Show Gist options
  • Save FroMage/95510ae3dc8c388bf90d1245ee3abdd6 to your computer and use it in GitHub Desktop.
Save FroMage/95510ae3dc8c388bf90d1245ee3abdd6 to your computer and use it in GitHub Desktop.
private List<org.jboss.jandex.Type> findArgumentsToSuperType(DotName currentClass, List<org.jboss.jandex.Type> args,
DotName soughtSuperType) {
// stop if we didn't find it
if (currentClass.equals(OBJECT_DOT_NAME)) {
return null;
}
final ClassInfo classByName = indexView.getClassByName(currentClass);
// build a map of this classe's type params to their arguments
Map<TypeVariable, org.jboss.jandex.Type> typeArgs = new HashMap<>();
List<TypeVariable> typeParameters = classByName.typeParameters();
for (int i = 0; i < typeParameters.size(); i++) {
TypeVariable typeVariable = typeParameters.get(i);
// default to first bound instead?
org.jboss.jandex.Type arg;
if (i < args.size())
arg = args.get(i);
else
arg = typeVariable;
typeArgs.put(typeVariable, arg);
}
// look at the interfaces for a direct implementation
for (org.jboss.jandex.Type type : classByName.interfaceTypes()) {
if (type.name().equals(soughtSuperType)) {
// found the type args
return substitute(type.asParameterizedType().arguments(), typeArgs);
}
// look at super-interfaces
// FIXME: add cache to avoid visiting the same interface more than once
List<org.jboss.jandex.Type> superArgs = findSuperArgs(type, typeArgs);
List<org.jboss.jandex.Type> ret = findArgumentsToSuperType(type.name(), superArgs, soughtSuperType);
if(ret != null)
return ret;
}
// look at super-type
List<org.jboss.jandex.Type> superArgs = findSuperArgs(classByName.superClassType(), typeArgs);
return findArgumentsToSuperType(classByName.superName(), superArgs, soughtSuperType);
}
private List<org.jboss.jandex.Type> findSuperArgs(org.jboss.jandex.Type superClassType,
Map<TypeVariable, org.jboss.jandex.Type> typeArgs) {
switch (superClassType.kind()) {
case CLASS:
return Collections.emptyList();
case PARAMETERIZED_TYPE:
return substitute(superClassType.asParameterizedType().arguments(), typeArgs);
default:
throw new RuntimeException("Invalid supertype kind: " + superClassType);
}
}
private List<org.jboss.jandex.Type> substitute(List<org.jboss.jandex.Type> types,
Map<TypeVariable, org.jboss.jandex.Type> typeArgs){
List<org.jboss.jandex.Type> substitutedArgs = new ArrayList<>(types);
for (int i = 0; i < substitutedArgs.size(); i++) {
substitutedArgs.set(i, substitute(substitutedArgs.get(i), typeArgs));
}
return substitutedArgs;
}
private org.jboss.jandex.Type substitute(org.jboss.jandex.Type type,
Map<TypeVariable, org.jboss.jandex.Type> typeArgs) {
switch (type.kind()) {
case ARRAY:
ArrayType arrayType = type.asArrayType();
org.jboss.jandex.Type substitutedComponent = substitute(arrayType.component(), typeArgs);
return ArrayType.create(substitutedComponent, arrayType.dimensions());
case TYPE_VARIABLE:
org.jboss.jandex.Type substitutedArgument = typeArgs.get(type.asTypeVariable());
return substitutedArgument != null ? substitutedArgument : type;
case VOID:
case PRIMITIVE:
case CLASS:
return type;
case PARAMETERIZED_TYPE:
ParameterizedType parameterizedType = type.asParameterizedType();
org.jboss.jandex.Type substitutedOwner = parameterizedType.owner() != null
? substitute(parameterizedType.owner(), typeArgs)
: null;
List<org.jboss.jandex.Type> arguments = parameterizedType.arguments();
org.jboss.jandex.Type[] substitutedArguments = new org.jboss.jandex.Type[arguments.size()];
for (int i = 0; i < arguments.size(); i++) {
org.jboss.jandex.Type argument = arguments.get(i);
substitutedArguments[i] = substitute(argument, typeArgs);
}
return ParameterizedType.create(parameterizedType.name(), substitutedArguments, substitutedOwner);
case UNRESOLVED_TYPE_VARIABLE:
return type;
case WILDCARD_TYPE:
WildcardType wildcardType = type.asWildcardType();
org.jboss.jandex.Type superBound = wildcardType.superBound();
// do erasure to bounds
if (superBound != null)
return substitute(superBound, typeArgs);
return substitute(wildcardType.extendsBound(), typeArgs);
default:
throw new RuntimeException("Invalid supertype kind: " + type);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment