Randgalt / record-builder

Record builder generator for Java records

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support @NonNull at package-info.java level

cykl opened this issue · comments

Discussed in #89

Originally posted by cykl March 3, 2022
A common way to manage nullability annotations is to put a default @nonnull annotation at method / parameter / field level using package-info.java and then only add @nullable where relevant. Rational being that it is far more common to want something @nonnull than @nullable.

The idiomatic way to do it is to define an annotation like that

@Target( { ElementType.PACKAGE, ElementType.TYPE } )
@Retention( RetentionPolicy.RUNTIME )
@Documented
@Nonnull
@TypeQualifierDefault( ElementType.FIELD )
public @interface NonNullFields {
}

And then apply it to the package-info.java:

@NonNullApi
@NonNullFields
package my.package;

It tried to define a such annotation for record components and apply it. But record-builder seems to not care.

@Target( { ElementType.PACKAGE, ElementType.TYPE } )
@Retention( RetentionPolicy.RUNTIME )
@Documented
@Nonnull
@TypeQualifierDefault( { ElementType.RECORD_COMPONENT } )
public @interface NonNullRecordComponents {
} 

I spent a little time trying to understand how @TypeQualifierDefault works and how it impacts an annotation processor without much success. I set breakpoints in RecordBuilderProcessor#process and tried to figure an expression that would return the @nonnull annotation on the record member or constructor parameter.

If someone has some knowledge on this topic, any help would be appreciated.

I will skim through Findbugs, NullAway and others source code.

@cyki Using Findbug @TypeQualifierDefault is very legacy way of doing it.

The newer way is to use TYPE_USE annotations like JSpecify, Checker or Eclipse (possibly IntelliJ depending on which one you use). It is the correct way to do this.

Thus I recommend you check out the newer/better tools like Checker that support those annotations. It will also be much much easier to support if #106 is fixed. This is because it is part of the type. So wherever the type is it will be annotated correctly.

Thanks for the hint @agentgt .

State of nullness checking was so depressing that I put myself into hibernation a few years ago waiting for some sanity to appear.