From 0495cb7fa77271193cc4e0e774080256cb185b73 Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Sun, 19 Jul 2020 15:26:48 +0200 Subject: [PATCH] #2149 Do not allow using BeanMapping(ignoreByDefault = true) in combination with Mapping(target = ".") This fixes an ArrayIndexOutOfBoundsException when they were used together --- .../model/source/MappingMethodOptions.java | 43 +++++++--- .../processor/MapperCreationProcessor.java | 2 +- .../mapstruct/ap/internal/util/Message.java | 1 + .../test/bugs/_2149/Erroneous2149Mapper.java | 84 +++++++++++++++++++ .../ap/test/bugs/_2149/Issue2149Test.java | 47 +++++++++++ 5 files changed, 166 insertions(+), 11 deletions(-) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_2149/Erroneous2149Mapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_2149/Issue2149Test.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java index e0007949a..b7fd7f00d 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java @@ -11,11 +11,12 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import org.mapstruct.ap.internal.gem.CollectionMappingStrategyGem; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; +import org.mapstruct.ap.internal.util.FormattingMessager; +import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.accessor.Accessor; import static org.mapstruct.ap.internal.model.source.MappingOptions.getMappingTargetNamesBy; @@ -250,7 +251,8 @@ public class MappingMethodOptions { return false; } - public void applyIgnoreAll(SourceMethod method, TypeFactory typeFactory ) { + public void applyIgnoreAll(SourceMethod method, TypeFactory typeFactory, + FormattingMessager messager) { CollectionMappingStrategyGem cms = method.getOptions().getMapper().getCollectionMappingStrategy(); Type writeType = method.getResultType(); if ( !method.isUpdateMethod() ) { @@ -262,15 +264,27 @@ public class MappingMethodOptions { Map writeAccessors = writeType.getPropertyWriteAccessors( cms ); - Set mappedPropertyNames = mappings.stream() - .map( m -> getPropertyEntries( m )[0] ) - .collect( Collectors.toSet() ); - - for ( String targetPropertyName : writeAccessors.keySet() ) { - if ( !mappedPropertyNames.contains( targetPropertyName ) ) { - MappingOptions mapping = MappingOptions.forIgnore( targetPropertyName ); - mappings.add( mapping ); + for ( MappingOptions mapping : mappings ) { + String mappedTargetProperty = getFirstTargetPropertyName( mapping ); + if ( !".".equals( mappedTargetProperty ) ) { + // Remove the mapped target property from the write accessors + writeAccessors.remove( mappedTargetProperty ); } + else { + messager.printMessage( + method.getExecutable(), + getBeanMapping().getMirror(), + Message.BEANMAPPING_IGNORE_BY_DEFAULT_WITH_MAPPING_TARGET_THIS + ); + // Nothing more to do if this is reached + return; + } + } + + // The writeAccessors now contains only the accessors that should be ignored + for ( String targetPropertyName : writeAccessors.keySet() ) { + MappingOptions mapping = MappingOptions.forIgnore( targetPropertyName ); + mappings.add( mapping ); } } @@ -290,4 +304,13 @@ public class MappingMethodOptions { return mapping.getTargetName().split( "\\." ); } + private String getFirstTargetPropertyName(MappingOptions mapping) { + String targetName = mapping.getTargetName(); + if ( ".".equals( targetName ) ) { + return targetName; + } + + return getPropertyEntries( mapping )[0]; + } + } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java index e480eaf7a..25f25c3c3 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java @@ -486,7 +486,7 @@ public class MapperCreationProcessor implements ModelElementProcessor