diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java index 4e05ad5d6..c46d2a1a9 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java @@ -396,23 +396,30 @@ public class BeanMappingMethod extends NormalTypeMappingMethod { for ( Mapping mapping : entry.getValue() ) { TargetReference targetReference = mapping.getTargetReference(); if ( targetReference.isValid() ) { - if ( !handledTargets.contains( first( targetReference.getPropertyEntries() ).getFullName() ) ) { + String target = first( targetReference.getPropertyEntries() ).getFullName(); + if ( !handledTargets.contains( target ) ) { if ( handleDefinedMapping( mapping, handledTargets ) ) { errorOccurred = true; } } + if ( mapping.getSourceReference() != null && mapping.getSourceReference().isValid() ) { + List sourceEntries = mapping.getSourceReference().getPropertyEntries(); + if ( !sourceEntries.isEmpty() ) { + String source = first( sourceEntries ).getFullName(); + unprocessedSourceProperties.remove( source ); + } + } } else { errorOccurred = true; } } } + + // remove the remaining name based properties for ( String handledTarget : handledTargets ) { - // In order to avoid: "Unknown property foo in return type" in case of duplicate - // target mappings unprocessedTargetProperties.remove( handledTarget ); unprocessedDefinedTargets.remove( handledTarget ); - unprocessedSourceProperties.remove( handledTarget ); } return errorOccurred; @@ -497,7 +504,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod { .nullValuePropertyMappingStrategy( mapping.getNullValuePropertyMappingStrategy() ) .build(); handledTargets.add( propertyName ); - unprocessedSourceProperties.remove( mapping.getSourceName() ); unprocessedSourceParameters.remove( sourceRef.getParameter() ); } else { diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Issue1772Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Issue1772Mapper.java new file mode 100644 index 000000000..867385ce2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Issue1772Mapper.java @@ -0,0 +1,23 @@ +/* + * 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._1772; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.ReportingPolicy; +import org.mapstruct.factory.Mappers; + +/** + * @author Sjaak Derksen + */ +@Mapper(unmappedSourcePolicy = ReportingPolicy.ERROR) +public interface Issue1772Mapper { + + Issue1772Mapper INSTANCE = Mappers.getMapper( Issue1772Mapper.class ); + + @Mapping(target = "nestedTarget.doubleNestedTarget", source = "nestedSource.doublyNestedSourceField" ) + Target map(Source source); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Issue1772Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Issue1772Test.java new file mode 100644 index 000000000..b77eb34ec --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Issue1772Test.java @@ -0,0 +1,39 @@ +/* + * 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._1772; + +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 Sjaak Derksen + */ +@IssueKey("1772") +@RunWith(AnnotationProcessorTestRunner.class) +@WithClasses({ + Issue1772Mapper.class, + Source.class, + Target.class, +}) +public class Issue1772Test { + + @Test + public void shouldCorrectlyMarkSourceAsUsed() { + + Source source = new Source(); + source.setNestedSource( new Source.NestedSource() ); + source.getNestedSource().setDoublyNestedSourceField( 5d ); + + Target target = Issue1772Mapper.INSTANCE.map( source ); + + assertThat( target.getNestedTarget().getDoubleNestedTarget() ).isEqualTo( 5d ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Source.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Source.java new file mode 100644 index 000000000..076ae8a41 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Source.java @@ -0,0 +1,35 @@ +/* + * 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._1772; + +/** + * @author Sjaak Derksen + */ +public class Source { + + private NestedSource nestedSource; + + public NestedSource getNestedSource() { + return nestedSource; + } + + public void setNestedSource(NestedSource nestedSource) { + this.nestedSource = nestedSource; + } + + public static class NestedSource { + + private double doublyNestedSourceField; + + public double getDoublyNestedSourceField() { + return doublyNestedSourceField; + } + + public void setDoublyNestedSourceField(double doublyNestedSourceField) { + this.doublyNestedSourceField = doublyNestedSourceField; + } + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Target.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Target.java new file mode 100644 index 000000000..6ad876acd --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1772/Target.java @@ -0,0 +1,35 @@ +/* + * 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._1772; + +/** + * @author Sjaak Derksen + */ +public class Target { + + private NestedTarget nestedTarget; + + public NestedTarget getNestedTarget() { + return nestedTarget; + } + + public void setNestedTarget(NestedTarget nestedTarget) { + this.nestedTarget = nestedTarget; + } + + public static class NestedTarget { + + private double doubleNestedTarget; + + public double getDoubleNestedTarget() { + return doubleNestedTarget; + } + + public void setDoubleNestedTarget(double doubleNestedTarget) { + this.doubleNestedTarget = doubleNestedTarget; + } + } +}