#2356 Implicitly ignore reverse inherited mappings that do not have read and write methods

This commit is contained in:
Filip Hrisafov 2021-02-21 13:56:08 +01:00
parent 1964c809d8
commit e7f6813d9a
3 changed files with 112 additions and 8 deletions

View File

@ -938,8 +938,10 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
if ( targetWriteAccessor == null ) {
if ( targetReadAccessor == null ) {
if ( mapping.getInheritContext() != null && mapping.getInheritContext().isForwarded() &&
mapping.getInheritContext().getTemplateMethod().isUpdateMethod() != method.isUpdateMethod() ) {
MappingOptions.InheritContext inheritContext = mapping.getInheritContext();
if ( inheritContext != null ) {
if ( inheritContext.isForwarded() &&
inheritContext.getTemplateMethod().isUpdateMethod() != method.isUpdateMethod() ) {
// When a configuration is inherited and the template method is not same type as the current
// method then we can safely ignore this mapping.
// This means that a property which is inherited might be present for a direct mapping
@ -947,6 +949,14 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
// or vice versa
return false;
}
else if ( inheritContext.isReversed() ) {
// When a configuration is reverse inherited and there are no read or write accessor
// then we should ignore this mapping.
// This most likely means that we were mapping the source parameter to the target.
// If the error is due to something else it will be reported on the original mapping
return false;
}
}
Set<String> readAccessors = resultTypeToMap.getPropertyReadAccessors().keySet();
String mostSimilarProperty = Strings.getMostSimilarWord( targetPropertyName, readAccessors );

View File

@ -0,0 +1,49 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2356;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* @author Filip Hrisafov
*/
@Mapper
public interface Issue2356Mapper {
Issue2356Mapper INSTANCE = Mappers.getMapper( Issue2356Mapper.class );
class Car {
//CHECKSTYLE:OFF
public String brand;
public String model;
public String modelInternational;
//CHECKSTYLE:ON
}
class CarDTO {
//CHECKSTYLE:OFF
public String brand;
public String modelName;
//CHECKSTYLE:ON
}
// When using InheritInverseConfiguration the mapping from in to modelName should be ignored
// and shouldn't lead to a compile error.
@Mapping(target = "modelName", source = "in")
CarDTO map(Car in);
default String mapToModel(Car in) {
return in.modelInternational == null ? in.model : in.modelInternational;
}
@InheritInverseConfiguration
@Mapping(target = "model", source = "modelName")
@Mapping(target = "modelInternational", ignore = true)
Car map(CarDTO in);
}

View File

@ -0,0 +1,45 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2356;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Filip Hrisafov
*/
@IssueKey("2356")
@RunWith(AnnotationProcessorTestRunner.class)
@WithClasses({
Issue2356Mapper.class
})
public class Issue2356Test {
@Test
public void shouldCompile() {
Issue2356Mapper.Car car = new Issue2356Mapper.Car();
car.brand = "Tesla";
car.model = "X";
car.modelInternational = "3";
Issue2356Mapper.CarDTO dto = Issue2356Mapper.INSTANCE.map( car );
assertThat( dto ).isNotNull();
assertThat( dto.brand ).isEqualTo( "Tesla" );
assertThat( dto.modelName ).isEqualTo( "3" );
car = Issue2356Mapper.INSTANCE.map( dto );
assertThat( car ).isNotNull();
assertThat( car.brand ).isEqualTo( "Tesla" );
assertThat( car.model ).isEqualTo( "3" );
assertThat( car.modelInternational ).isNull();
}
}