#1135 added test and implementation for overloading#1136
#1135 added test and implementation for overloading#1136quantumlexa wants to merge 1 commit intomapstruct:masterfrom
Conversation
|
(Message from the pull-request-builder): Admins, please verify this patch for it to build in the pull-request-builder. |
|
ok to test |
filiphr
left a comment
There was a problem hiding this comment.
@quantumlexa a really good addition to the framework. Thanks a lot for doing the PR. In general it is good.
I have some comments inline.
Maybe it will be good to add some tests for which MapStruct will generate a forged method (see NestedBeanMappingsTest). You can add fields to those places as well if you want to.
| Map<String, Accessor> accessors = method.getResultType().getPropertyWriteAccessors( cms ); | ||
| Map<String, Accessor> srcReadAccessors = Collections.emptyMap(); | ||
| if (sourceMethod instanceof SourceMethod) { | ||
| srcReadAccessors = ( (SourceMethod) sourceMethod ).getGetSourceReadAccessors(); |
There was a problem hiding this comment.
I don't think that it is entirely correct to use this only for SourceMethod(s). We also have the ForgedMethod(s) that are used for nested target mappings, automatic name based methods creation etc. Maybe you can add a method to the new MappingMethodUtils (you'll have to rebase on top of the latest master).
On the other side, you won't be able to use memoization. You can add the getGetSourceReadAccessors() or even name it getSourceReadAccessors to the Method interface and do memoization where needed (SourceMethod and ForgedMethod, the others can just return empty map`).
| return presenceCheckers; | ||
| } | ||
|
|
||
| public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy ) { |
There was a problem hiding this comment.
Can you copy the previous Javadoc here and add the sourceAccessor(s) parameter to the new method signature?
|
|
||
| private Type determinePreferredType(Accessor readAccessor) { | ||
| private TypeMirror extractTypeMirror( Accessor accessor ) { | ||
| return accessor.getExecutable().getParameters().get( 0 ).asType(); |
There was a problem hiding this comment.
This is wrong it can lead to NPE. The accessor does not always have an executable. MapStruct can also map public field and that is why we have introduced the Accessor. I think that this can be done by only using the MapStruct Type and not the TypeMirror. Maybe you can also use Type in the isBetter check as well.
| */ | ||
| public static List<Accessor> getAllEnclosedAccessors(Elements elementUtils, TypeElement element) { | ||
| public static List<Accessor> getAllEnclosedAccessors( Elements elementUtils, TypeElement element ) { | ||
| if (element == null) { |
There was a problem hiding this comment.
Did you have problems with an NPE here?
|
|
||
| @WithClasses({ | ||
| SourceTargetMapper.class, | ||
| SourceTargetMapperPropertyBean.class, |
There was a problem hiding this comment.
What is the difference between the SourceTargetMapper and the SourceTargetMapperPropertyBean is it only the @Mapping annotation? Btw. when the source and target have the same name you don't need it. If you want to test that it works for different name you can just add new fields :).
| Source.class, | ||
| Target.class | ||
| }) | ||
| public void testShouldGenerateCorrectMapperImplementationJsr() { |
There was a problem hiding this comment.
Why do you need this test method? Also the @WithClasses on the method is not needed, because those classes are already added on the class level. We usually add @WithClasses to methods when we want to test errors within the mappers.
| public void testShouldGenerateCorrectMapperImplementation() { | ||
| Source source = new Source( new Date() ); | ||
| Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source ); | ||
| Assert.assertTrue( target.getUpdatedOn() > 0 ); |
There was a problem hiding this comment.
Can you use assertj Assertions here? I would also add the implementation class as a comparison fixture to the GeneratedSource rule. You can have a look at the ArrayMappingTest and the ScienceMapperImpl.java fixture for how it works.
There was a problem hiding this comment.
As this PR adresses only a behavioral change and doesn't structurally change the generated code, I don't think we need that fixture here - we should try keep the usage of those to a minimum, as we'll always need to keep maintaining them in the future... 🙂
There was a problem hiding this comment.
@agudian is right for the fixture. Just to make sure that we don't miss this in the future, maybe the setUpdateOn(long updateOn) in the Target should throw an exception. That method should not be called.
There was a problem hiding this comment.
removed body of test at all. It should compile ant that's enough.
a29f5ba to
b099446
Compare
filiphr
left a comment
There was a problem hiding this comment.
There are still some issues with the PR:
- I think that by mistake you have reverted the changes you had (the commits that moved the
getGetSourceReadAccessorsto theMethodinterface and it's renaming - This solution only works if the
targetandsourceproperties have the same name. If they are different, but they are matched with@Mappingthen it doesn't work
| return getMappingTargetParameter() != null; | ||
| } | ||
|
|
||
| public Map<String, Accessor> getGetSourceReadAccessors() { |
There was a problem hiding this comment.
It looks like your last version was reverted to before you moved the getSourceReadAccessors to the Method interface.
| * @return an unmodifiable map of all write accessors indexed by property name | ||
| */ | ||
| public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy ) { | ||
| public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy, |
There was a problem hiding this comment.
This will only work when the source and target properties are the same.
If you modify the name in either Source or Target and accordingly use @Mapping then it'll fail.
| } | ||
|
|
||
| private TypeMirror extractTypeMirror( Accessor accessor ) { | ||
| return accessor.getExecutable().getParameters().get( 0 ).asType(); |
There was a problem hiding this comment.
In theory you should not be able to get up to here if your Accessor is field. However, I think that a null check needs to be done on the accessor.getExecutable().
|
@agudian, I had another look at the PR. There are some issues which are addressed in my second review. However, I don't think that there is an issue with the selectors:
@quantumlexa Can you perhaps add more properties and make sure that all the branches in |
|
due to some errors with git branch - recreated it in: #1136 |
|
PR moved to #1167 |
Mapstruct does support overloading of target setters(see: Issue892Test test) but choosing preferred type logic is based on getter type of target - not source, which looks a bit strange.
Here is straightforward implementation of this