Randgalt / record-builder

Record builder generator for Java records
Apache License 2.0
756 stars 55 forks source link

useImmutableCollections=true combined with @Nonnull on a record component result in NPE #91

Closed cykl closed 2 years ago

cykl commented 2 years ago

Discussed in https://github.com/Randgalt/record-builder/discussions/90

When useImmutableCollections is set to true, builder populates the record with empty collections rather than a null field. Generated code looks like:

   @Generated("io.soabase.recordbuilder.core.RecordBuilder")
    public Removeme.R build() {
        return new Removeme.R(__list(l));
    }

    @Generated("io.soabase.recordbuilder.core.RecordBuilder")
    private static <T> List<T> __list(List<T> o) {
        return (o != null) ? List.copyOf(o) : List.of();
    }

So far, so good. Now, let's add @Nonnull annotation on the record component. Building the record will result in a NullPointerException because builder check for nullity before __list() is invoked.

    @Generated("io.soabase.recordbuilder.core.RecordBuilder")
    public Removeme.R build() {
        Objects.requireNonNull(l, "l is required");
        return new Removeme.R(__list(l));
    }

Declaring a collection to not be null is likely the most common case (who want to deal with both nullity and emptiness?).

I'm not familiar with record-builder codebase but will submit a tentative PR soon.