Support @NonNull at package-info.java level
cykl opened this issue · 3 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.