diff --git a/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java b/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java index 58a1beaa9..c36d6efee 100644 --- a/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java +++ b/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java @@ -141,7 +141,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { //2.) build up aggregated "target" model List mappings = getMappings( methods, - ReportingPolicy.valueOf( MapperPrism.getInstanceOn( element ).unmappedTargetPolicy() ) + getEffectiveUnmappedTargetPolicy( element ) ); List usedMapperTypes = getUsedMapperTypes( element ); @@ -157,6 +157,31 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { return mapper; } + /** + * Returns the effective policy for reporting unmapped target properties. If + * explicitly set via {@code Mapper}, this value will be returned. Otherwise + * the value from the corresponding processor option will be returned. If + * that is not set either, the default value from + * {@code Mapper#unmappedTargetPolicy()} will be returned. + * + * @param element The type declaring the generated mapper type + * + * @return The effective policy for reporting unmapped target properties. + */ + private ReportingPolicy getEffectiveUnmappedTargetPolicy(TypeElement element) { + MapperPrism mapperPrism = MapperPrism.getInstanceOn( element ); + boolean setViaAnnotation = mapperPrism.values.unmappedTargetPolicy() != null; + ReportingPolicy annotationValue = ReportingPolicy.valueOf( mapperPrism.unmappedTargetPolicy() ); + + if ( setViaAnnotation || + options.getUnmappedTargetPolicy() == null ) { + return annotationValue; + } + else { + return options.getUnmappedTargetPolicy(); + } + } + private List getMappings(List methods, ReportingPolicy unmappedTargetPolicy) { Conversions conversions = new Conversions( elementUtils, typeUtils, typeUtil ); diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java index d9608abbf..60715995e 100644 --- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java @@ -35,6 +35,7 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.ap.model.Options; +import org.mapstruct.ap.model.ReportingPolicy; @SupportedAnnotationTypes("org.mapstruct.Mapper") @GeneratePrisms({ @@ -42,7 +43,7 @@ import org.mapstruct.ap.model.Options; @GeneratePrism(value = Mapping.class, publicAccess = true), @GeneratePrism(value = Mappings.class, publicAccess = true) }) -@SupportedOptions(MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP) +@SupportedOptions({ MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP, MappingProcessor.UNMAPPED_TARGET_POLICY }) public class MappingProcessor extends AbstractProcessor { /** @@ -51,6 +52,7 @@ public class MappingProcessor extends AbstractProcessor { private static final boolean ANNOTATIONS_CLAIMED_EXCLUSIVELY = false; protected static final String SUPPRESS_GENERATOR_TIMESTAMP = "suppressGeneratorTimestamp"; + protected static final String UNMAPPED_TARGET_POLICY = "unmappedTargetPolicy"; private Options options; @@ -88,6 +90,11 @@ public class MappingProcessor extends AbstractProcessor { } private Options createOptions() { - return new Options( Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_TIMESTAMP ) ) ); + String unmappedTargetPolicy = processingEnv.getOptions().get( UNMAPPED_TARGET_POLICY ); + + return new Options( + Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_TIMESTAMP ) ), + unmappedTargetPolicy != null ? ReportingPolicy.valueOf( unmappedTargetPolicy ) : null + ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/Options.java b/processor/src/main/java/org/mapstruct/ap/model/Options.java index 02c673ed1..12b3ad205 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Options.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Options.java @@ -22,15 +22,22 @@ package org.mapstruct.ap.model; * The options passed to the code generator. * * @author Andreas Gudian + * @autor Gunnar Morling */ public class Options { private final boolean suppressGeneratorTimestamp; + private final ReportingPolicy unmappedTargetPolicy; - public Options(boolean suppressGeneratorTimestamp) { + public Options(boolean suppressGeneratorTimestamp, ReportingPolicy unmappedTargetPolicy) { this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; + this.unmappedTargetPolicy = unmappedTargetPolicy; } public boolean isSuppressGeneratorTimestamp() { return suppressGeneratorTimestamp; } + + public ReportingPolicy getUnmappedTargetPolicy() { + return unmappedTargetPolicy; + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/unmappedtarget/UnmappedTargetTest.java b/processor/src/test/java/org/mapstruct/ap/test/unmappedtarget/UnmappedTargetTest.java index 2cc4051d6..6a54a27a8 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/unmappedtarget/UnmappedTargetTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/unmappedtarget/UnmappedTargetTest.java @@ -26,6 +26,7 @@ import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic; import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; +import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption; import org.testng.annotations.Test; import static org.fest.assertions.Assertions.assertThat; @@ -81,4 +82,23 @@ public class UnmappedTargetTest extends MapperTestBase { ) public void shouldRaiseErrorDueToUnsetTargetProperty() { } + + @Test + @WithClasses({ Source.class, Target.class, SourceTargetMapper.class }) + @ProcessorOption(name = "unmappedTargetPolicy", value = "ERROR") + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic(type = SourceTargetMapper.class, + kind = Kind.ERROR, + line = 29, + messageRegExp = "Unmapped target property: \"bar\""), + @Diagnostic(type = SourceTargetMapper.class, + kind = Kind.ERROR, + line = 31, + messageRegExp = "Unmapped target property: \"qux\"") + } + ) + public void shouldRaiseErrorDueToUnsetTargetPropertyWithPolicySetViaProcessorOption() { + } }