#2445 Improve error reporting when EnumTransformationStrategy throws an error during transformation

This commit is contained in:
Filip Hrisafov 2021-05-15 11:37:27 +02:00
parent fdf3dcc8ef
commit 4576103752
5 changed files with 69 additions and 4 deletions

View File

@ -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<MappingEntry> enumToEnumMapping(Method method, Type sourceType, Type targetType ) {
List<MappingEntry> 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 ) );
}

View File

@ -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;
}

View File

@ -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),

View File

@ -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

View File

@ -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);
}