#1776 adding a message when no qualifiers are found (#1786)

This commit is contained in:
Sjaak Derksen 2019-05-25 18:14:00 +02:00 committed by GitHub
parent 9c33199a66
commit d50e41cdbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 97 additions and 66 deletions

View File

@ -89,25 +89,15 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
false
);
Assignment assignment = ctx.getMappingResolver().getTargetAssignment(
method,
Assignment assignment = ctx.getMappingResolver().getTargetAssignment( method,
targetElementType,
formattingParameters,
criteria,
sourceRHS,
null
null,
() -> forge( sourceRHS, sourceElementType, targetElementType )
);
if ( assignment == null && !criteria.hasQualfiers() ) {
assignment = forgeMapping( sourceRHS, sourceElementType, targetElementType );
if ( assignment != null ) {
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_CREATE_ELEMENT_NOTE, assignment );
}
}
else {
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_SELECT_ELEMENT_NOTE, assignment );
}
if ( assignment == null ) {
if ( method instanceof ForgedMethod ) {
// leave messaging to calling property mapping
@ -124,6 +114,7 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
}
}
else {
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_SELECT_ELEMENT_NOTE, assignment );
if ( method instanceof ForgedMethod ) {
ForgedMethod forgedMethod = (ForgedMethod) method;
forgedMethod.addThrownTypes( assignment.getThrownTypes() );
@ -171,6 +162,14 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
);
}
private Assignment forge(SourceRHS sourceRHS, Type sourceType, Type targetType) {
Assignment assignment = super.forgeMapping( sourceRHS, sourceType, targetType );
if ( assignment != null ) {
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_CREATE_ELEMENT_NOTE, assignment );
}
return assignment;
}
protected abstract M instantiateMappingMethod(Method method, Collection<String> existingVariables,
Assignment assignment, MethodReference factoryMethod,
boolean mapNullToDefault, String loopVariableName,

View File

@ -97,19 +97,10 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
keyFormattingParameters,
keyCriteria,
keySourceRHS,
null
null,
() -> forge( keySourceRHS, keySourceType, keyTargetType, Message.MAPMAPPING_CREATE_KEY_NOTE )
);
if ( keyAssignment == null && !keyCriteria.hasQualfiers( ) ) {
keyAssignment = forgeMapping( keySourceRHS, keySourceType, keyTargetType );
if ( keyAssignment != null ) {
ctx.getMessager().note( 2, Message.MAPMAPPING_CREATE_KEY_NOTE, keyAssignment );
}
}
else {
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_KEY_NOTE, keyAssignment );
}
if ( keyAssignment == null ) {
if ( method instanceof ForgedMethod ) {
// leave messaging to calling property mapping
@ -129,6 +120,9 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
);
}
}
else {
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_KEY_NOTE, keyAssignment );
}
// find mapping method or conversion for value
Type valueSourceType = sourceTypeParams.get( 1 ).getTypeBound();
@ -146,7 +140,8 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
valueFormattingParameters,
valueCriteria,
valueSourceRHS,
null
null,
() -> forge( valueSourceRHS, valueSourceType, valueTargetType, Message.MAPMAPPING_CREATE_VALUE_NOTE )
);
if ( method instanceof ForgedMethod ) {
@ -159,16 +154,6 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
}
}
if ( valueAssignment == null && !valueCriteria.hasQualfiers( ) ) {
valueAssignment = forgeMapping( valueSourceRHS, valueSourceType, valueTargetType );
if ( valueAssignment != null ) {
ctx.getMessager().note( 2, Message.MAPMAPPING_CREATE_VALUE_NOTE, valueAssignment );
}
}
else {
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_VALUE_NOTE, valueAssignment );
}
if ( valueAssignment == null ) {
if ( method instanceof ForgedMethod ) {
// leave messaging to calling property mapping
@ -188,6 +173,9 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
);
}
}
else {
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_VALUE_NOTE, valueAssignment );
}
// mapNullToDefault
boolean mapNullToDefault = false;
@ -222,6 +210,14 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
);
}
Assignment forge(SourceRHS sourceRHS, Type sourceType, Type targetType, Message message ) {
Assignment assignment = forgeMapping( sourceRHS, sourceType, targetType );
if ( assignment != null ) {
ctx.getMessager().note( 2, message, assignment );
}
return assignment;
}
@Override
protected boolean shouldUsePropertyNamesInHistory() {
return true;

View File

@ -11,6 +11,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
@ -93,7 +94,8 @@ public class MappingBuilderContext {
Assignment getTargetAssignment(Method mappingMethod, Type targetType,
FormattingParameters formattingParameters,
SelectionCriteria criteria, SourceRHS sourceRHS,
AnnotationMirror positionHint);
AnnotationMirror positionHint,
Supplier<Assignment> forger);
Set<SupportingMappingMethod> getUsedSupportedMappings();
}

View File

@ -280,36 +280,17 @@ public class PropertyMapping extends ModelElement {
formattingParameters,
criteria,
rightHandSide,
positionHint
positionHint,
() -> forge( )
);
}
else {
assignment = forge();
}
Type sourceType = rightHandSide.getSourceType();
// No mapping found. Try to forge a mapping
if ( assignment == null && !criteria.hasQualfiers() ) {
if ( (sourceType.isCollectionType() || sourceType.isArrayType()) && targetType.isIterableType() ) {
assignment = forgeIterableMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
}
else if ( sourceType.isMapType() && targetType.isMapType() ) {
assignment = forgeMapMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
}
else if ( ( sourceType.isIterableType() && targetType.isStreamType() ) ||
( sourceType.isStreamType() && targetType.isStreamType() ) ||
( sourceType.isStreamType() && targetType.isIterableType() ) ) {
assignment = forgeStreamMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
}
else {
assignment = forgeMapping( rightHandSide );
}
if ( assignment != null ) {
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_CREATE_NOTE, assignment );
}
}
else {
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_SELECT_NOTE, assignment );
}
if ( assignment != null ) {
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_SELECT_NOTE, assignment );
if ( targetType.isCollectionOrMapType() ) {
assignment = assignToCollection( targetType, targetWriteAccessorType, assignment );
}
@ -336,6 +317,29 @@ public class PropertyMapping extends ModelElement {
);
}
private Assignment forge( ) {
Assignment assignment;
Type sourceType = rightHandSide.getSourceType();
if ( (sourceType.isCollectionType() || sourceType.isArrayType()) && targetType.isIterableType() ) {
assignment = forgeIterableMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
}
else if ( sourceType.isMapType() && targetType.isMapType() ) {
assignment = forgeMapMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
}
else if ( ( sourceType.isIterableType() && targetType.isStreamType() )
|| ( sourceType.isStreamType() && targetType.isStreamType() )
|| ( sourceType.isStreamType() && targetType.isIterableType() ) ) {
assignment = forgeStreamMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
}
else {
assignment = forgeMapping( rightHandSide );
}
if ( assignment != null ) {
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_CREATE_NOTE, assignment );
}
return assignment;
}
/**
* Report that a mapping could not be created.
*/
@ -844,7 +848,8 @@ public class PropertyMapping extends ModelElement {
formattingParameters,
criteria,
new SourceRHS( constantExpression, sourceType, existingVariableNames, sourceErrorMessagePart ),
positionHint
positionHint,
() -> null
);
}
else {

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
@ -97,7 +98,8 @@ public class MappingResolverImpl implements MappingResolver {
public Assignment getTargetAssignment(Method mappingMethod, Type targetType,
FormattingParameters formattingParameters,
SelectionCriteria criteria, SourceRHS sourceRHS,
AnnotationMirror positionHint) {
AnnotationMirror positionHint,
Supplier<Assignment> forger) {
ResolvingAttempt attempt = new ResolvingAttempt(
sourceModel,
@ -105,7 +107,8 @@ public class MappingResolverImpl implements MappingResolver {
formattingParameters,
sourceRHS,
criteria,
positionHint
positionHint,
forger
);
return attempt.getTargetAssignment( sourceRHS.getSourceTypeForMatching(), targetType );
@ -136,6 +139,7 @@ public class MappingResolverImpl implements MappingResolver {
private final boolean savedPreferUpdateMapping;
private final FormattingParameters formattingParameters;
private final AnnotationMirror positionHint;
private final Supplier<Assignment> forger;
// resolving via 2 steps creates the possibility of wrong matches, first builtin method matches,
// second doesn't. In that case, the first builtin method should not lead to a supported method
@ -145,7 +149,8 @@ public class MappingResolverImpl implements MappingResolver {
private ResolvingAttempt(List<Method> sourceModel, Method mappingMethod,
FormattingParameters formattingParameters, SourceRHS sourceRHS,
SelectionCriteria criteria,
AnnotationMirror positionHint) {
AnnotationMirror positionHint,
Supplier<Assignment> forger) {
this.mappingMethod = mappingMethod;
this.methods = filterPossibleCandidateMethods( sourceModel );
@ -156,6 +161,7 @@ public class MappingResolverImpl implements MappingResolver {
this.selectionCriteria = criteria;
this.savedPreferUpdateMapping = criteria.isPreferUpdateMapping();
this.positionHint = positionHint;
this.forger = forger;
}
private <T extends Method> List<T> filterPossibleCandidateMethods(List<T> candidateMethods) {
@ -243,6 +249,19 @@ public class MappingResolverImpl implements MappingResolver {
return conversion.getAssignment();
}
if ( hasQualfiers() ) {
messager.printMessage(
mappingMethod.getExecutable(),
positionHint,
Message.GENERAL_NO_QUALIFYING_METHOD,
Strings.join( selectionCriteria.getQualifiers(), ", " ),
Strings.join( selectionCriteria.getQualifiedByNames(), ", " )
);
}
else {
return forger.get();
}
// if nothing works, alas, the result is null
return null;
}

View File

@ -113,6 +113,7 @@ public enum Message {
GENERAL_JODA_NOT_ON_CLASSPATH( "Cannot validate Joda dateformat, no Joda on classpath. Consider adding Joda to the annotation processorpath.", Diagnostic.Kind.WARNING ),
GENERAL_NOT_ALL_FORGED_CREATED( "Internal Error in creation of Forged Methods, it was expected all Forged Methods to finished with creation, but %s did not" ),
GENERAL_NO_SUITABLE_CONSTRUCTOR( "%s does not have an accessible parameterless constructor." ),
GENERAL_NO_QUALIFYING_METHOD( "No qualifying method found for qualifiers: %s and / or qualifying names: %s" ),
BUILDER_MORE_THAN_ONE_BUILDER_CREATION_METHOD( "More than one builder creation method for \"%s\". Found methods: \"%s\". Builder will not be used. Consider implementing a custom BuilderProvider SPI.", Diagnostic.Kind.WARNING ),
BUILDER_NO_BUILD_METHOD_FOUND("No build method \"%s\" found in \"%s\" for \"%s\". Found methods: \"%s\".", Diagnostic.Kind.ERROR ),

View File

@ -98,7 +98,16 @@ public class QualifierTest {
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousMapper.class,
@Diagnostic(
type = ErroneousMapper.class,
kind = Kind.ERROR,
line = 28,
messageRegExp =
"No qualifying method found for qualifiers: "
+ "org.mapstruct.ap.test.selection.qualifier.annotation.NonQualifierAnnotated and "
+ "/ or qualifying names: .*"),
@Diagnostic(
type = ErroneousMapper.class,
kind = Kind.ERROR,
line = 28,
messageRegExp =