| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
…ces with parameter prefix When a forward mapping uses a source path that includes the source parameter name (e.g. source.client.id), inverse inheritance previously kept that prefix in the inverse target name. Ignore and redefinition matching then failed because the first path segment was the parameter name rather than the property. Strip the source parameter name prefix when building the inverse target name, mirroring SourceReference / TargetReference resolution.
There was a problem hiding this comment.
I ran this locally on 75ad6b9 against 211b2be (JDK 21.0.4, both javac and ecj through @ProcessorTest). The diagnosis and the fix hold for the reported shape. One thing about the guard clause looks worth resolving before it lands.
Control first, to check the test actually defends the change: the four new test files on top of main, with MappingOptions.java reverted to main and nothing else changed.
Issue3997Test.inverseIgnoreShouldRespectNestedSourcesWithParameterPrefix:35 expected: null but was: org.mapstruct.ap.test.bugs._3997.Issue3997Mapper$Client@58168099 Tests run: 4, Failures: 2, Errors: 0, Skipped: 0
Two failures are the same assertion under the two compilers. On the PR head: Tests run: 4, Failures: 0. Full processor module on the PR head: Tests run: 3638, Failures: 0, Errors: 0, Skipped: 0.
I also checked that first( templateMethod.getSourceParameters() ) cannot fail here: SourceMethod#inverses (SourceMethod.java:352) requires exactly one source parameter on both methods, so the template always has one.
stripSourceParameterPrefix keeps the full path when the first segment is a read accessor of the source type. Neither resolver decides it that way.
So when the parameter name collides with a property that does not carry the rest of the path, the forward mapping resolves through the strip path while this PR keeps the prefix, and the fix does not apply. Reproducer: parameter named client, Order has both getClient() and getId(), Client has no id.
@Mapper
public interface M {
@Mapping(target = "dtoId", source = "client.id")
OrderDto toDto(Order client);
@InheritInverseConfiguration
@Mapping(target = "client", ignore = true)
Order toEntity(OrderDto dto);
}The forward side resolves by stripping, so the inverse target should be id:
-- MapStruct: mapping property: client.getId() to: setDtoId(java.lang.Long).
Compiled with the processor built from this branch:
warning: Unmapped target property: "id".
public Probe.Order toEntity(Probe.OrderDto dto) {
if ( dto == null ) {
return null;
}
Probe.Order order = new Probe.Order();
return order;
}
dtoId -> id is dropped: the inverse target name stays client.id, and filterNestedTargetIgnores then removes it under @Mapping(target = "client", ignore = true). That is the same failure #3997 reports.
Two controls around it. The generated file is identical (apart from the date attribute) when compiled with a processor built from main, so this is not a regression introduced here, it is a case the fix declines to cover. And renaming the parameter to order (source = "order.id", everything else unchanged) makes both main and this branch emit order.setId( dto.getDtoId() ), which isolates the guard as the deciding factor rather than anything else in the mapper.
Direction rather than a patch: have the guard ask the question buildFromSingleSourceParameters asks, i.e. whether the full path resolves against the source type's accessors, and strip only when it does not. That would also make the javadoc claim on the new method true of the code that runs.
Smaller notes:
Sorry, something went wrong.
When building the inverse target name, try the full source path as property accessors first and strip the parameter name only if that path does not resolve. Fixes the case where the parameter name collides with a property but the rest of the path is not on that property. Signed-off-by: Kamil Krzywanski <kamilkrzywanski01@gmail.com>
|
@kdelay thanks for the detailed review. Updated the guard to match SourceReference: try the full path as property accessors first, strip the parameter name only when that fails. Added tests for both the strip and keep cases (including the client/id collision you described). |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Summary
Fixes #3997
When a forward mapping uses a source path that includes the source parameter name (e.g. source.client.id), @InheritInverseConfiguration previously kept that prefix in the inverse target name (source.client.id). As a result, @Mapping(target = "client", ignore = true) on the inverse method did not match the nested inherited mapping, and MapStruct still created intermediate objects for ignored properties.
Root cause
Fix
When building the inverse target name, strip the source parameter name prefix (e.g. source.client.id → client.id), mirroring SourceReference / TargetReference resolution. If the first segment is also a property of the source type, the full path is kept (property path takes precedence).
Tests
Checklist