diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java index 6e7fe3f0d..0d71ed550 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java @@ -56,6 +56,7 @@ public class ValueMappingMethod extends MappingMethod { private ValueMappings valueMappings; private EnumMappingOptions enumMapping; private EnumTransformationStrategyInvoker enumTransformationInvoker; + private boolean enumTransformationIllegalReported = false; public Builder mappingContext(MappingBuilderContext mappingContext) { this.ctx = mappingContext; @@ -144,6 +145,25 @@ public class ValueMappingMethod extends MappingMethod { } + private String transform(String source) { + try { + return enumTransformationInvoker.transform( source ); + } + catch ( IllegalArgumentException ex ) { + if ( !enumTransformationIllegalReported ) { + enumTransformationIllegalReported = true; + ctx.getMessager().printMessage( + method.getExecutable(), + enumMapping.getMirror(), + Message.ENUMMAPPING_ILLEGAL_TRANSFORMATION, + enumTransformationInvoker.transformationStrategy.getStrategyName(), + ex.getMessage() + ); + } + return source; + } + } + private List enumToEnumMapping(Method method, Type sourceType, Type targetType ) { List mappings = new ArrayList<>(); @@ -175,7 +195,7 @@ public class ValueMappingMethod extends MappingMethod { if ( enumMappingInverse ) { // If the mapping is inverse we have to change the target enum constant targetConstants.put( - enumTransformationInvoker.transform( targetNameEnum ), + transform( targetNameEnum ), targetEnumConstant ); } @@ -189,7 +209,7 @@ public class ValueMappingMethod extends MappingMethod { String sourceNameConstant = getEnumConstant( sourceTypeElement, sourceConstant ); String targetConstant; if ( !enumMappingInverse ) { - targetConstant = enumTransformationInvoker.transform( sourceNameConstant ); + targetConstant = transform( sourceNameConstant ); } else { targetConstant = sourceNameConstant; @@ -251,7 +271,7 @@ public class ValueMappingMethod extends MappingMethod { // all remaining constants are mapped for ( String sourceConstant : unmappedSourceConstants ) { String sourceNameConstant = getEnumConstant( sourceTypeElement, sourceConstant ); - String targetConstant = enumTransformationInvoker.transform( sourceNameConstant ); + String targetConstant = transform( sourceNameConstant ); mappings.add( new MappingEntry( sourceConstant, targetConstant ) ); } } @@ -283,7 +303,7 @@ public class ValueMappingMethod extends MappingMethod { // all remaining constants are mapped for ( String sourceConstant : unmappedSourceConstants ) { String sourceNameConstant = getEnumConstant( targetTypeElement, sourceConstant ); - String stringConstant = enumTransformationInvoker.transform( sourceNameConstant ); + String stringConstant = transform( sourceNameConstant ); if ( !mappedSources.contains( stringConstant ) ) { mappings.add( new MappingEntry( stringConstant, sourceConstant ) ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/EnumMappingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/EnumMappingOptions.java index 86c415a4f..85734c308 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/EnumMappingOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/EnumMappingOptions.java @@ -6,6 +6,8 @@ package org.mapstruct.ap.internal.model.source; import java.util.Map; +import java.util.Optional; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.TypeMirror; @@ -64,6 +66,10 @@ public class EnumMappingOptions extends DelegatingOptions { return next().getUnexpectedValueMappingException(); } + public AnnotationMirror getMirror() { + return Optional.ofNullable( enumMapping ).map( EnumMappingGem::mirror ).orElse( null ); + } + public boolean isInverse() { return inverse; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java index 50aeb701d..cb182af6b 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java @@ -110,6 +110,7 @@ public enum Message { ENUMMAPPING_INCORRECT_TRANSFORMATION_STRATEGY( "There is no registered EnumTransformationStrategy for '%s'. Registered strategies are: %s." ), ENUMMAPPING_MISSING_CONFIGURATION( "Configuration has to be defined when strategy is defined." ), ENUMMAPPING_NO_ELEMENTS( "'nameTransformationStrategy', 'configuration' and 'unexpectedValueMappingException' are undefined in @EnumMapping, define at least one of them." ), + ENUMMAPPING_ILLEGAL_TRANSFORMATION( "Illegal transformation for '%s' EnumTransformationStrategy. Error: '%s'." ), LIFECYCLEMETHOD_AMBIGUOUS_PARAMETERS( "Lifecycle method has multiple matching parameters (e. g. same type), in this case please ensure to name the parameters in the lifecycle and mapping method identical. This lifecycle method will not be used for the mapping method '%s'.", Diagnostic.Kind.WARNING), diff --git a/processor/src/test/java/org/mapstruct/ap/test/value/nametransformation/EnumNameTransformationStrategyTest.java b/processor/src/test/java/org/mapstruct/ap/test/value/nametransformation/EnumNameTransformationStrategyTest.java index d5c74dbe8..7a29ae40a 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/value/nametransformation/EnumNameTransformationStrategyTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/value/nametransformation/EnumNameTransformationStrategyTest.java @@ -101,6 +101,24 @@ public class EnumNameTransformationStrategyTest { public void shouldGiveCompileErrorWhenUsingUnknownNameTransformStrategy() { } + @ProcessorTest + @WithClasses({ + ErroneousCaseTransformStrategyMapper.class + }) + @ExpectedCompilationOutcome(value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( + type = ErroneousCaseTransformStrategyMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 18, + message = "Illegal transformation for 'case' EnumTransformationStrategy." + + " Error: 'Unexpected configuration for enum case transformation: unknown'." + ) + } + ) + public void shouldGiveCompileErrorWhenUsingUnknownConfigurationForCaseTransformStrategy() { + } + @ProcessorTest @WithClasses({ ErroneousNameTransformStrategyMapper.class diff --git a/processor/src/test/java/org/mapstruct/ap/test/value/nametransformation/ErroneousCaseTransformStrategyMapper.java b/processor/src/test/java/org/mapstruct/ap/test/value/nametransformation/ErroneousCaseTransformStrategyMapper.java new file mode 100644 index 000000000..fe8357a8a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/value/nametransformation/ErroneousCaseTransformStrategyMapper.java @@ -0,0 +1,20 @@ +/* + * 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.value.nametransformation; + +import org.mapstruct.EnumMapping; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; + +/** + * @author Filip Hrisafov + */ +@Mapper +public interface ErroneousCaseTransformStrategyMapper { + + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "unknown") + CheeseType map(CheeseType cheese); +}