#128 Raising an error in case source enum constant without corresponding constant in target is not mapped

This commit is contained in:
Gunnar Morling 2014-02-23 17:22:48 +01:00
parent d8df52dbc0
commit 76783edc1c
4 changed files with 88 additions and 4 deletions

View File

@ -26,6 +26,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.annotation.processing.Messager; import javax.annotation.processing.Messager;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
@ -755,7 +756,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
} }
private EnumMappingMethod getEnumMappingMethod(SourceMethod method) { private EnumMappingMethod getEnumMappingMethod(SourceMethod method) {
if ( !reportErrorIfMappedEnumConstantsDontExist( method ) ) { if ( !reportErrorIfMappedEnumConstantsDontExist( method ) ||
!reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped( method ) ) {
return null; return null;
} }
@ -859,6 +861,36 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
return !foundIncorrectMapping; return !foundIncorrectMapping;
} }
private boolean reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped(
SourceMethod method) {
List<String> sourceEnumConstants = method.getSourceParameters().iterator().next().getType().getEnumConstants();
List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
Set<String> mappedSourceEnumConstants = method.getMappings().keySet();
List<String> unmappedSourceEnumConstants = new ArrayList<String>();
for ( String sourceEnumConstant : sourceEnumConstants ) {
if ( !targetEnumConstants.contains( sourceEnumConstant ) &&
!mappedSourceEnumConstants.contains( sourceEnumConstant ) ) {
unmappedSourceEnumConstants.add( sourceEnumConstant );
}
}
if ( !unmappedSourceEnumConstants.isEmpty() ) {
messager.printMessage(
Kind.ERROR,
String.format(
"The following constants from the source enum have no corresponding constant in the target enum " +
"and must be be mapped via @Mapping: %s",
Strings.join( unmappedSourceEnumConstants, ", " )
),
method.getExecutable()
);
}
return unmappedSourceEnumConstants.isEmpty();
}
private TypeConversion getConversion(Type sourceType, Type targetType, String dateFormat, String sourceReference) { private TypeConversion getConversion(Type sourceType, Type targetType, String dateFormat, String sourceReference) {
ConversionProvider conversionProvider = conversions.getConversion( sourceType, targetType ); ConversionProvider conversionProvider = conversions.getConversion( sourceType, targetType );

View File

@ -77,7 +77,7 @@ public class EnumMappingTest extends MapperTestBase {
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousOrderMapperMappingSameConstantTwice.class, @Diagnostic(type = ErroneousOrderMapperMappingSameConstantTwice.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 39, line = 42,
messageRegExp = "One enum constant must not be mapped to more than one target constant, but " + messageRegExp = "One enum constant must not be mapped to more than one target constant, but " +
"constant EXTRA is mapped to SPECIAL, DEFAULT\\.") "constant EXTRA is mapped to SPECIAL, DEFAULT\\.")
} }
@ -92,15 +92,30 @@ public class EnumMappingTest extends MapperTestBase {
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class, @Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 35, line = 37,
messageRegExp = "Constant FOO doesn't exist in enum type org.mapstruct.ap.test.enums.OrderType\\."), messageRegExp = "Constant FOO doesn't exist in enum type org.mapstruct.ap.test.enums.OrderType\\."),
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class, @Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 36, line = 38,
messageRegExp = "Constant BAR doesn't exist in enum type org.mapstruct.ap.test.enums." + messageRegExp = "Constant BAR doesn't exist in enum type org.mapstruct.ap.test.enums." +
"ExternalOrderType\\.") "ExternalOrderType\\.")
} }
) )
public void shouldRaiseErrorIfUnknownEnumConstantsAreSpecifiedInMapping() { public void shouldRaiseErrorIfUnknownEnumConstantsAreSpecifiedInMapping() {
} }
@Test
@WithClasses(ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType.class,
kind = Kind.ERROR,
line = 34,
messageRegExp = "The following constants from the source enum have no corresponding constant in the " +
"target enum and must be be mapped via @Mapping: EXTRA, STANDARD, NORMAL"),
}
)
public void shouldRaiseErrorIfSourceConstantWithoutMatchingConstantInTargetTypeIsNotMapped() {
}
} }

View File

@ -36,6 +36,8 @@ public interface ErroneousOrderMapperMappingSameConstantTwice {
@Mappings({ @Mappings({
@Mapping(source = "EXTRA", target = "SPECIAL"), @Mapping(source = "EXTRA", target = "SPECIAL"),
@Mapping(source = "EXTRA", target = "DEFAULT"), @Mapping(source = "EXTRA", target = "DEFAULT"),
@Mapping(source = "STANDARD", target = "DEFAULT"),
@Mapping(source = "NORMAL", target = "DEFAULT")
}) })
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType); ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
} }

View File

@ -0,0 +1,35 @@
/**
* Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.enums;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* @author Gunnar Morling
*/
@Mapper
public interface ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType {
ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType INSTANCE = Mappers.getMapper(
ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType.class
);
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}