You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.
First of all, thank you for creating and maintaining JavaPoet, it's a great library 🙂.
I'm the author of Jilt, a Java annotation processor that uses JavaPoet for generating code. It's during work on this library that I've ran into this interesting edge case.
Let me give you a short introduction to Jilt. The purpose of this library is to automatically generate classes that implement the Builder design pattern. One of the important capabilities of the library is generating so-called Staged Builders. The idea there is to generate a separate interface for each required property of the class being built, and forming a chain out of them, and this way enforcing, at compile-time, that each required property is provided before the final instance is built.
A specific example might be helpful. Let's say we have the following simple value class:
If you notice, in the interfaces nested in FullNameBuilders, the return types that JavaPoet generates for the method declarations are not qualified with the name of the outer interface - so, it's LastName firstName(String firstName);, and notFullNameBuilders.LastName firstName(String firstName);. Also, the names of the interfaces nested in FullNameBuilders are (by default) simply the capitalized names of the fields. Both of these will be important in a second 🙂.
So far so good. But things become more interesting when the class being built is generic (has type parameters). When that happens, the per-property interfaces also need to be parametrized, with the same parameters as the built class.
And if the name of the type parameter and the (capitalized) name of the field are the same, the type parameter shadows the next interface in the chain, and the code doesn't compile!
Let me show another example, illustrating the problem:
In the method declaration Second<First, Second> first(First first); in PairBuilders.First, the Second return type unfortunately does not refer to PairBuilders.Second, but to the Second type parameter, which shadows the unqualified name Second in this case. This, of course, fails to compile.
The solution here would be to update the algorithm used by JavaPoet to resolve type names, to make sure it takes potentially shadowing type parameters into account, and generate the first() method with the return type PairBuilders.Second instead, like this:
First of all, thank you for creating and maintaining JavaPoet, it's a great library 🙂.
I'm the author of Jilt, a Java annotation processor that uses JavaPoet for generating code. It's during work on this library that I've ran into this interesting edge case.
Let me give you a short introduction to Jilt. The purpose of this library is to automatically generate classes that implement the Builder design pattern. One of the important capabilities of the library is generating so-called Staged Builders. The idea there is to generate a separate interface for each required property of the class being built, and forming a chain out of them, and this way enforcing, at compile-time, that each required property is provided before the final instance is built.
A specific example might be helpful. Let's say we have the following simple value class:
Jilt would generate the following code (all using JavaPoet, of course) for a Staged Builder for that class:
If you notice, in the interfaces nested in
FullNameBuilders
, the return types that JavaPoet generates for the method declarations are not qualified with the name of the outer interface - so, it'sLastName firstName(String firstName);
, and notFullNameBuilders.LastName firstName(String firstName);
. Also, the names of the interfaces nested inFullNameBuilders
are (by default) simply the capitalized names of the fields. Both of these will be important in a second 🙂.So far so good. But things become more interesting when the class being built is generic (has type parameters). When that happens, the per-property interfaces also need to be parametrized, with the same parameters as the built class.
And if the name of the type parameter and the (capitalized) name of the field are the same, the type parameter shadows the next interface in the chain, and the code doesn't compile!
Let me show another example, illustrating the problem:
The interfaces generated for the properties are (I'll skip the actual Builder class, as it doesn't really matter here):
In the method declaration
Second<First, Second> first(First first);
inPairBuilders.First
, theSecond
return type unfortunately does not refer toPairBuilders.Second
, but to theSecond
type parameter, which shadows the unqualified nameSecond
in this case. This, of course, fails to compile.The solution here would be to update the algorithm used by JavaPoet to resolve type names, to make sure it takes potentially shadowing type parameters into account, and generate the
first()
method with the return typePairBuilders.Second
instead, like this:Let me know if this makes sense, and thanks again for the great library!
The text was updated successfully, but these errors were encountered: