mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#304 Detecting unknown properties given via dependsOn()
This commit is contained in:
parent
a332533dda
commit
21b89ea5e2
@ -73,6 +73,7 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
private MappingBuilderContext ctx;
|
private MappingBuilderContext ctx;
|
||||||
private SourceMethod method;
|
private SourceMethod method;
|
||||||
private Map<String, ExecutableElement> unprocessedTargetProperties;
|
private Map<String, ExecutableElement> unprocessedTargetProperties;
|
||||||
|
private Set<String> targetProperties;
|
||||||
private final List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
private final List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
||||||
private final Set<Parameter> unprocessedSourceParameters = new HashSet<Parameter>();
|
private final Set<Parameter> unprocessedSourceParameters = new HashSet<Parameter>();
|
||||||
private List<TypeMirror> qualifiers;
|
private List<TypeMirror> qualifiers;
|
||||||
@ -89,6 +90,7 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
this.method = sourceMethod;
|
this.method = sourceMethod;
|
||||||
CollectionMappingStrategyPrism cms = sourceMethod.getMapperConfiguration().getCollectionMappingStrategy();
|
CollectionMappingStrategyPrism cms = sourceMethod.getMapperConfiguration().getCollectionMappingStrategy();
|
||||||
Map<String, ExecutableElement> accessors = method.getResultType().getTargetAccessors( cms );
|
Map<String, ExecutableElement> accessors = method.getResultType().getTargetAccessors( cms );
|
||||||
|
this.targetProperties = accessors.keySet();
|
||||||
this.unprocessedTargetProperties = new HashMap<String, ExecutableElement>( accessors );
|
this.unprocessedTargetProperties = new HashMap<String, ExecutableElement>( accessors );
|
||||||
for ( Parameter sourceParameter : method.getSourceParameters() ) {
|
for ( Parameter sourceParameter : method.getSourceParameters() ) {
|
||||||
unprocessedSourceParameters.add( sourceParameter );
|
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() {
|
private void sortPropertyMappingsByDependencies() {
|
||||||
final GraphAnalyzer graphAnalyzer = new GraphAnalyzer();
|
final GraphAnalyzer graphAnalyzer = new GraphAnalyzer();
|
||||||
|
|
||||||
@ -242,6 +248,20 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
errorOccurred = true;
|
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
|
// check the mapping options
|
||||||
// its an ignored property mapping
|
// its an ignored property mapping
|
||||||
if ( mapping.isIgnored() ) {
|
if ( mapping.isIgnored() ) {
|
||||||
|
@ -62,6 +62,8 @@ public class Mapping {
|
|||||||
private final AnnotationMirror mirror;
|
private final AnnotationMirror mirror;
|
||||||
private final AnnotationValue sourceAnnotationValue;
|
private final AnnotationValue sourceAnnotationValue;
|
||||||
private final AnnotationValue targetAnnotationValue;
|
private final AnnotationValue targetAnnotationValue;
|
||||||
|
private final AnnotationValue dependsOnAnnotationValue;
|
||||||
|
|
||||||
private SourceReference sourceReference;
|
private SourceReference sourceReference;
|
||||||
|
|
||||||
public static Map<String, List<Mapping>> fromMappingsPrism(MappingsPrism mappingsAnnotation,
|
public static Map<String, List<Mapping>> fromMappingsPrism(MappingsPrism mappingsAnnotation,
|
||||||
@ -136,6 +138,7 @@ public class Mapping {
|
|||||||
mappingPrism.mirror,
|
mappingPrism.mirror,
|
||||||
mappingPrism.values.source(),
|
mappingPrism.values.source(),
|
||||||
mappingPrism.values.target(),
|
mappingPrism.values.target(),
|
||||||
|
mappingPrism.values.dependsOn(),
|
||||||
resultType,
|
resultType,
|
||||||
dependsOn
|
dependsOn
|
||||||
);
|
);
|
||||||
@ -146,6 +149,7 @@ public class Mapping {
|
|||||||
String dateFormat, List<TypeMirror> qualifiers,
|
String dateFormat, List<TypeMirror> qualifiers,
|
||||||
boolean isIgnored, AnnotationMirror mirror,
|
boolean isIgnored, AnnotationMirror mirror,
|
||||||
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
|
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
|
||||||
|
AnnotationValue dependsOnAnnotationValue,
|
||||||
TypeMirror resultType, List<String> dependsOn) {
|
TypeMirror resultType, List<String> dependsOn) {
|
||||||
this.sourceName = sourceName;
|
this.sourceName = sourceName;
|
||||||
this.constant = constant;
|
this.constant = constant;
|
||||||
@ -157,6 +161,7 @@ public class Mapping {
|
|||||||
this.mirror = mirror;
|
this.mirror = mirror;
|
||||||
this.sourceAnnotationValue = sourceAnnotationValue;
|
this.sourceAnnotationValue = sourceAnnotationValue;
|
||||||
this.targetAnnotationValue = targetAnnotationValue;
|
this.targetAnnotationValue = targetAnnotationValue;
|
||||||
|
this.dependsOnAnnotationValue = dependsOnAnnotationValue;
|
||||||
this.resultType = resultType;
|
this.resultType = resultType;
|
||||||
this.dependsOn = dependsOn;
|
this.dependsOn = dependsOn;
|
||||||
}
|
}
|
||||||
@ -243,6 +248,10 @@ public class Mapping {
|
|||||||
return targetAnnotationValue;
|
return targetAnnotationValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AnnotationValue getDependsOnAnnotationValue() {
|
||||||
|
return dependsOnAnnotationValue;
|
||||||
|
}
|
||||||
|
|
||||||
public SourceReference getSourceReference() {
|
public SourceReference getSourceReference() {
|
||||||
return sourceReference;
|
return sourceReference;
|
||||||
}
|
}
|
||||||
@ -301,6 +310,7 @@ public class Mapping {
|
|||||||
mirror,
|
mirror,
|
||||||
sourceAnnotationValue,
|
sourceAnnotationValue,
|
||||||
targetAnnotationValue,
|
targetAnnotationValue,
|
||||||
|
dependsOnAnnotationValue,
|
||||||
null,
|
null,
|
||||||
Collections.<String>emptyList()
|
Collections.<String>emptyList()
|
||||||
);
|
);
|
||||||
@ -326,6 +336,7 @@ public class Mapping {
|
|||||||
mirror,
|
mirror,
|
||||||
sourceAnnotationValue,
|
sourceAnnotationValue,
|
||||||
targetAnnotationValue,
|
targetAnnotationValue,
|
||||||
|
dependsOnAnnotationValue,
|
||||||
resultType,
|
resultType,
|
||||||
dependsOn
|
dependsOn
|
||||||
);
|
);
|
||||||
|
@ -36,6 +36,7 @@ public enum Message {
|
|||||||
BEANMAPPING_UNMAPPED_TARGETS_WARNING( "Unmapped target %s.", Diagnostic.Kind.WARNING ),
|
BEANMAPPING_UNMAPPED_TARGETS_WARNING( "Unmapped target %s.", Diagnostic.Kind.WARNING ),
|
||||||
BEANMAPPING_UNMAPPED_TARGETS_ERROR( "Unmapped target %s." ),
|
BEANMAPPING_UNMAPPED_TARGETS_ERROR( "Unmapped target %s." ),
|
||||||
BEANMAPPING_CYCLE_BETWEEN_PROPERTIES( "Cycle(s) between properties given via dependsOn(): %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_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." ),
|
PROPERTYMAPPING_DUPLICATE_TARGETS( "Target property \"%s\" must not be mapped more than once." ),
|
||||||
|
@ -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);
|
||||||
|
}
|
@ -83,4 +83,20 @@ public class OrderingTest {
|
|||||||
)
|
)
|
||||||
public void shouldReportErrorIfDependenciesContainCycle() {
|
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() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user