TypeName.get(...) produces invalid wildcard type names for generic classes
richarddd opened this issue · 3 comments
Hi,
I have a bunch of annotate generic Kotlin classes with Maps as parameters.
The class looks like this:
class ExampleClass : ExampleGenericClass<Map<String, String>, Map<String, Int>>
The TypeMirror looks something like this:
com.example.ExampleClass<java.util.Map<java.lang.String,? extends java.lang.String>,java.util.Map<java.lang.String,? extends java.lang.Integer>>
The problem here is that the wildcards types can not be compiled as-is since they are bounded by boxed primitives and strings. This compiler produces the following error:
incompatible types: Map<String,CAP#1> cannot be converted to Map<String,String>
return HANDLER.handleRequest(input,context);
^
where CAP#1 is a fresh type-variable:
CAP#1 extends String from capture of ? extends String
The workaround I've implemented is to recursively iterate through the Parameterized type and replace the invalid wildcard types:
private fun TypeName.ensureProperWildcards(): TypeName = when (this) {
is ParameterizedTypeName -> {
ParameterizedTypeName.get(this.rawType, *this.typeArguments.map {
it.ensureProperWildcards()
}.toTypedArray())
}
is WildcardTypeName -> {
val firstUpperBound = this.upperBounds.firstOrNull()
val firstLowerBound = this.lowerBounds.firstOrNull()
if (firstUpperBound != null && (firstUpperBound == TypeName.get(String::class.java) || firstUpperBound.isBoxedPrimitive) && firstLowerBound == null) {
firstUpperBound
} else {
this
}
}
else -> {
this
}
}
Could this be avoided when Javapoet parses the TypeMirror and removes the wildcard for boxed primitives and strings?
Hi, happy to look into this issue.
@richarddd not a 100% sure what version you are using, but did some research and it seem that JavaPoet from version 1.10.0 doesn’t support code compilation.