#4076 Propagate JSpecify nullability annotations to the mapper implementation - #4112
Open
arjun2075 wants to merge 1 commit into
Open
#4076 Propagate JSpecify nullability annotations to the mapper implementation#4112arjun2075 wants to merge 1 commit into
arjun2075 wants to merge 1 commit into
Conversation
…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.
arjun2075
force-pushed
the
issue-4076-propagate-jspecify-nullability
branch
from
August 14, 2026 15:15
cf162e3 to
9e41476
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4076
Generated mapper implementations dropped the JSpecify
@Nullableannotations declared on the mapper method they implement, so IDEs reported "Overriding method parameters are not annotated" on the generated@Overridemethods.The nullability information was already resolved for null-check decisions (
NullabilityResolver), but was never emitted into the generated signature. This propagates it:ParameterandMappingMethodnow carry the type of the@Nullableannotation to emit, and include it in their import types so the annotation is imported rather than fully qualified.AbstractMappingMethodBuilder#propagateNullabilityresolves the nullability of the overridden method's return type and parameters via the existingMappingBuilderContext#getNullabilityInMapperScope, and is called fromBeanMappingMethod.BuilderandContainerMappingMethodBuilder(covering bean, iterable, map and stream mapping methods).Since JSpecify's
@Nullableand@NonNullareTYPE_USE-only annotations, they are not valid in method-declaration position and therefore cannot go through the existing declaration-levelannotationslist.Design note
Only an explicit
@Nullableis reproduced.@NonNullis deliberately left out: inside a@NullMarkedscope 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@NonNullto 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.disableJSpecifyoption through the resolver.Testing
org.mapstruct.ap.test.bugs._4076covering@Nullableon parameters and return types, the generated import, and the container/update method paths (which route throughContainerMappingMethodBuilderrather thanBeanMappingMethod.Builder).@Nullableon the affected parameter, so the added annotation is the corrected output.