#304 Detecting unknown properties given via dependsOn()

This commit is contained in:
Gunnar Morling 2015-03-01 19:27:50 +01:00
parent a332533dda
commit 21b89ea5e2
5 changed files with 82 additions and 0 deletions

View File

@ -73,6 +73,7 @@ public class BeanMappingMethod extends MappingMethod {
private MappingBuilderContext ctx;
private SourceMethod method;
private Map<String, ExecutableElement> unprocessedTargetProperties;
private Set<String> targetProperties;
private final List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
private final Set<Parameter> unprocessedSourceParameters = new HashSet<Parameter>();
private List<TypeMirror> qualifiers;
@ -89,6 +90,7 @@ public class BeanMappingMethod extends MappingMethod {
this.method = sourceMethod;
CollectionMappingStrategyPrism cms = sourceMethod.getMapperConfiguration().getCollectionMappingStrategy();
Map<String, ExecutableElement> accessors = method.getResultType().getTargetAccessors( cms );
this.targetProperties = accessors.keySet();
this.unprocessedTargetProperties = new HashMap<String, ExecutableElement>( accessors );
for ( Parameter sourceParameter : method.getSourceParameters() ) {
unprocessedSourceParameters.add( sourceParameter );
@ -168,6 +170,10 @@ public class BeanMappingMethod extends MappingMethod {
);
}
/**
* Sources the given mappings as per the dependency relationships given via {@code dependsOn()}. If a cycle is
* detected, an error is reported.
*/
private void sortPropertyMappingsByDependencies() {
final GraphAnalyzer graphAnalyzer = new GraphAnalyzer();
@ -242,6 +248,20 @@ public class BeanMappingMethod extends MappingMethod {
errorOccurred = true;
}
// unknown properties given via dependsOn()?
for ( String dependency : mapping.getDependsOn() ) {
if ( !targetProperties.contains( dependency ) ) {
ctx.getMessager().printMessage(
method.getExecutable(),
mapping.getMirror(),
mapping.getDependsOnAnnotationValue(),
Message.BEANMAPPING_UNKNOWN_PROPERTY_IN_DEPENDS_ON,
dependency
);
errorOccurred = true;
}
}
// check the mapping options
// its an ignored property mapping
if ( mapping.isIgnored() ) {

View File

@ -62,6 +62,8 @@ public class Mapping {
private final AnnotationMirror mirror;
private final AnnotationValue sourceAnnotationValue;
private final AnnotationValue targetAnnotationValue;
private final AnnotationValue dependsOnAnnotationValue;
private SourceReference sourceReference;
public static Map<String, List<Mapping>> fromMappingsPrism(MappingsPrism mappingsAnnotation,
@ -136,6 +138,7 @@ public class Mapping {
mappingPrism.mirror,
mappingPrism.values.source(),
mappingPrism.values.target(),
mappingPrism.values.dependsOn(),
resultType,
dependsOn
);
@ -146,6 +149,7 @@ public class Mapping {
String dateFormat, List<TypeMirror> qualifiers,
boolean isIgnored, AnnotationMirror mirror,
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
AnnotationValue dependsOnAnnotationValue,
TypeMirror resultType, List<String> dependsOn) {
this.sourceName = sourceName;
this.constant = constant;
@ -157,6 +161,7 @@ public class Mapping {
this.mirror = mirror;
this.sourceAnnotationValue = sourceAnnotationValue;
this.targetAnnotationValue = targetAnnotationValue;
this.dependsOnAnnotationValue = dependsOnAnnotationValue;
this.resultType = resultType;
this.dependsOn = dependsOn;
}
@ -243,6 +248,10 @@ public class Mapping {
return targetAnnotationValue;
}
public AnnotationValue getDependsOnAnnotationValue() {
return dependsOnAnnotationValue;
}
public SourceReference getSourceReference() {
return sourceReference;
}
@ -301,6 +310,7 @@ public class Mapping {
mirror,
sourceAnnotationValue,
targetAnnotationValue,
dependsOnAnnotationValue,
null,
Collections.<String>emptyList()
);
@ -326,6 +336,7 @@ public class Mapping {
mirror,
sourceAnnotationValue,
targetAnnotationValue,
dependsOnAnnotationValue,
resultType,
dependsOn
);

View File

@ -36,6 +36,7 @@ public enum Message {
BEANMAPPING_UNMAPPED_TARGETS_WARNING( "Unmapped target %s.", Diagnostic.Kind.WARNING ),
BEANMAPPING_UNMAPPED_TARGETS_ERROR( "Unmapped target %s." ),
BEANMAPPING_CYCLE_BETWEEN_PROPERTIES( "Cycle(s) between properties given via dependsOn(): %s." ),
BEANMAPPING_UNKNOWN_PROPERTY_IN_DEPENDS_ON( "\"%s\" is no property of the method return type." ),
PROPERTYMAPPING_MAPPING_NOT_FOUND( "Can't map %s to \"%s %s\". Consider to declare/implement a mapping method: \"%s map(%s value)\"." ),
PROPERTYMAPPING_DUPLICATE_TARGETS( "Target property \"%s\" must not be mapped more than once." ),

View File

@ -0,0 +1,34 @@
/**
* Copyright 2012-2015 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.dependency;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper
public interface AddressMapperWithUnknownPropertyInDependsOn {
AddressMapperWithUnknownPropertyInDependsOn INSTANCE = Mappers.getMapper(
AddressMapperWithUnknownPropertyInDependsOn.class
);
@Mapping(target = "lastName", dependsOn = "doesnotexist")
PersonDto personToDto(Person person);
}

View File

@ -83,4 +83,20 @@ public class OrderingTest {
)
public void shouldReportErrorIfDependenciesContainCycle() {
}
@Test
@IssueKey("304")
@WithClasses(AddressMapperWithUnknownPropertyInDependsOn.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = AddressMapperWithUnknownPropertyInDependsOn.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 32,
messageRegExp = "\"doesnotexist\" is no property of the method return type"
)
}
)
public void shouldReportErrorIfPropertiyGivenInDependsOnDoesNotExist() {
}
}