…er implementation
Generated mapper implementations dropped the JSpecify `@Nullable`
annotations declared on the mapper method they implement, so IDEs
reported "Overriding method parameters are not annotated" on the
generated `@Override` methods.
The nullability information was already resolved for null-check
decisions (NullabilityResolver), but was never emitted into the
generated signature. This propagates it:
* `Parameter` and `MappingMethod` now carry the type of the `@Nullable`
annotation to emit, and include it in their import types so the
annotation is imported rather than fully qualified.
* `AbstractMappingMethodBuilder#propagateNullability` resolves the
nullability of the overridden method's return type and parameters via
the existing `MappingBuilderContext#getNullabilityInMapperScope`, and
is called from `BeanMappingMethod.Builder` and
`ContainerMappingMethodBuilder` (covering bean, iterable, map and
stream mapping methods).
* The corresponding FTL templates emit the annotation inline, directly
in front of the return type / parameter type.
Since JSpecify's `@Nullable` and `@NonNull` are `TYPE_USE`-only
annotations, they are not valid in method-declaration position and
therefore cannot go through the existing declaration-level
`annotations` list.
Only an explicit `@Nullable` is reproduced. `@NonNull` is deliberately
left out: inside a `@NullMarked` scope it is the implied default, so
emitting it would add noise to every generated signature without
changing the contract. Nothing is propagated for forged methods, which
do not override a mapper method. All of this stays gated behind the
existing `mapstruct.disableJSpecify` option through the resolver.
Fixes #4076
Generated mapper implementations dropped the JSpecify @Nullable annotations declared on the mapper method they implement, so IDEs reported "Overriding method parameters are not annotated" on the generated @Override methods.
The nullability information was already resolved for null-check decisions (NullabilityResolver), but was never emitted into the generated signature. This propagates it:
Since JSpecify's @Nullable and @NonNull are TYPE_USE-only annotations, they are not valid in method-declaration position and therefore cannot go through the existing declaration-level annotations list.
Design note
Only an explicit @Nullable is reproduced. @NonNull is deliberately left out: inside a @NullMarked scope it is the implied default, so emitting it would add noise to every generated signature without changing the contract. Happy to change this if you'd prefer @NonNull to be explicit as well.
Nothing is propagated for forged methods, which do not override a mapper method. All behaviour stays gated behind the existing mapstruct.disableJSpecify option through the resolver.
Testing