square / javapoet

A Java API for generating .java source files.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TypeName.get(...) produces invalid wildcard type names for generic classes

richarddd opened this issue · 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.