Randgalt / record-builder

Record builder generator for Java records

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Propagate TYPE_USE annotations

agentgt opened this issue · comments

As discussed on reddit the library does not propagate TYPE_USE annotations.

TYPE_USE annotations are far different than most other annotations in that they are extending the type.

Let us assume @Nullable is a TYPE_USE like it is for JSpecify.

@RecordBuilder
public record MyRecord(@Nullable String name, String required) {}

The record builder should copy the type java.lang. @Nullable String for wherever name is used. Yes that format of putting the annotation at the end of the package plus . is correct and that is why basically every library I have seen mess this up. Furthermore even the JDK mess this up but is now fixed cause ideally you could just toString on the TypeMirror.

Anyway it looks like your using Java Poet which notoriously ignores those annotations through its more or less broken TypeName. Someone posted a workaround here: square/javapoet#685 which you could use.

Also, see #111

I have no experience with these TYPE_USE annotations and have never come across them in any production code. So, it would be nice if you could explain what the need is for them and how Record-Builder can support them. Either here or in #111

@Randgalt I'm sorry I just don't have time anymore. One of the reasons I was "flooding the inbox" was that was my window to work on your project. That was why I was being urgent.

As for production code... you have never seen or used?

Anyway it doesn't really matter because I think the best thing to do is something like what Immutables does and provide your own annotation say @RecordBuilderNullable (and NonNull) (of target type RECORD_COMPONENT. You can also make that annotation TYPE_USE as well as all the other targets like Jetbrains (see link which is why I suspect you think you haven't seen them).

Then wherever you like to do configuration (perhaps package level annotations) users can specify what annotation they would like propagated. This is somewhat how jOOQ works.

For example

record MyRecord( @MyNullable /* the previous annotation will not be read by record builder */ @RecordBuilderNullable String field) {}

Then in configuration you say RecordBuilderNullable = MyNullable.class.

Then when you generate any method you just bring along MyNullable.class.

The only issue at that point is pure TYPE_USE annotations (as in no other @Target) like JSpecify and Eclipses annotations. For those when you make your "withers" you will need print the type different if you print the FQN.

Going back to the example if @MyNullable is TYPE_USE which you can figure out much easier than if a type has that annotation is do this for the wither:

MyRecordBuilder with(java.lang. @MyNullable String field);

instead of

MyRecordBuilder with(@MyNullable java.lang.String field);

I think but am not sure some generators get around this issue by importing instead of FQN but that will eventually fail.

The above practice will avoid the nasty issue of pulling TYPE_USE annotations from fields which I admit is difficult given the bugs of both the JDK and JPoet.

Anyway I don't have anymore time for now for this project but wish you best of luck. I'll try to answer anymore questions you have.