diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractMappingMethodBuilder.java b/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractMappingMethodBuilder.java index 019f94174..91b842763 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractMappingMethodBuilder.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractMappingMethodBuilder.java @@ -27,6 +27,8 @@ public abstract class AbstractMappingMethodBuildernull, no assignment found * */ - Assignment getTargetAssignment(Method mappingMethod, Type targetType, + Assignment getTargetAssignment(Method mappingMethod, ForgedMethodHistory description, Type targetType, FormattingParameters formattingParameters, SelectionCriteria criteria, SourceRHS sourceRHS, AnnotationMirror positionHint, diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/ObjectFactoryMethodResolver.java b/processor/src/main/java/org/mapstruct/ap/internal/model/ObjectFactoryMethodResolver.java index 34d294427..34fba406e 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/ObjectFactoryMethodResolver.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/ObjectFactoryMethodResolver.java @@ -81,7 +81,7 @@ public class ObjectFactoryMethodResolver { if ( matchingFactoryMethods.size() > 1 ) { ctx.getMessager().printMessage( method.getExecutable(), - Message.GENERAL_AMBIGIOUS_FACTORY_METHOD, + Message.GENERAL_AMBIGUOUS_FACTORY_METHOD, alternativeTarget, Strings.join( matchingFactoryMethods, ", " ) ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java index 571c3530f..4e0050e56 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java @@ -242,6 +242,7 @@ public class PropertyMapping extends ModelElement { if ( forgeMethodWithMappingReferences == null ) { assignment = ctx.getMappingResolver().getTargetAssignment( method, + getForgedMethodHistory( rightHandSide ), targetType, formattingParameters, criteria, @@ -791,6 +792,7 @@ public class PropertyMapping extends ModelElement { if ( !targetType.isEnumType() ) { assignment = ctx.getMappingResolver().getTargetAssignment( method, + null, // TODO description for constant targetType, formattingParameters, criteria, diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java index 5edd79294..8fa20f079 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java @@ -39,6 +39,7 @@ import org.mapstruct.ap.internal.conversion.ConversionProvider; import org.mapstruct.ap.internal.conversion.Conversions; import org.mapstruct.ap.internal.gem.ReportingPolicyGem; import org.mapstruct.ap.internal.model.Field; +import org.mapstruct.ap.internal.model.ForgedMethodHistory; import org.mapstruct.ap.internal.model.HelperMethod; import org.mapstruct.ap.internal.model.MapperReference; import org.mapstruct.ap.internal.model.MappingBuilderContext.MappingResolver; @@ -74,6 +75,8 @@ import org.mapstruct.ap.internal.util.Strings; */ public class MappingResolverImpl implements MappingResolver { + private static final int MAX_REPORTING_AMBIGUOUS = 5; + private final FormattingMessager messager; private final Types typeUtils; private final TypeFactory typeFactory; @@ -109,7 +112,7 @@ public class MappingResolverImpl implements MappingResolver { } @Override - public Assignment getTargetAssignment(Method mappingMethod, Type targetType, + public Assignment getTargetAssignment(Method mappingMethod, ForgedMethodHistory description, Type targetType, FormattingParameters formattingParameters, SelectionCriteria criteria, SourceRHS sourceRHS, AnnotationMirror positionHint, @@ -118,6 +121,7 @@ public class MappingResolverImpl implements MappingResolver { ResolvingAttempt attempt = new ResolvingAttempt( sourceModel, mappingMethod, + description, formattingParameters, sourceRHS, criteria, @@ -149,6 +153,7 @@ public class MappingResolverImpl implements MappingResolver { private class ResolvingAttempt { private final Method mappingMethod; + private final ForgedMethodHistory description; private final List methods; private final SelectionCriteria selectionCriteria; private final SourceRHS sourceRHS; @@ -163,7 +168,7 @@ public class MappingResolverImpl implements MappingResolver { // so this set must be cleared. private final Set supportingMethodCandidates; - private ResolvingAttempt(List sourceModel, Method mappingMethod, + private ResolvingAttempt(List sourceModel, Method mappingMethod, ForgedMethodHistory description, FormattingParameters formattingParameters, SourceRHS sourceRHS, SelectionCriteria criteria, AnnotationMirror positionHint, @@ -172,6 +177,7 @@ public class MappingResolverImpl implements MappingResolver { FormattingMessager messager) { this.mappingMethod = mappingMethod; + this.description = description; this.methods = filterPossibleCandidateMethods( sourceModel ); this.formattingParameters = formattingParameters == null ? FormattingParameters.EMPTY : formattingParameters; @@ -202,7 +208,7 @@ public class MappingResolverImpl implements MappingResolver { // first simple mapping method if ( allowMappingMethod() ) { List> matches = getBestMatch( methods, sourceType, targetType ); - reportErrorWhenAmbigious( matches, targetType ); + reportErrorWhenAmbiguous( matches, targetType ); if ( !matches.isEmpty() ) { assignment = toMethodRef( first( matches ) ); assignment.setAssignment( sourceRHS ); @@ -246,7 +252,7 @@ public class MappingResolverImpl implements MappingResolver { // check for a built-in method if ( !hasQualfiers() ) { List> matches = getBestMatch( builtIns, sourceType, targetType ); - reportErrorWhenAmbigious( matches, targetType ); + reportErrorWhenAmbiguous( matches, targetType ); if ( !matches.isEmpty() ) { assignment = toBuildInRef( first( matches ) ); assignment.setAssignment( sourceRHS ); @@ -443,29 +449,37 @@ public class MappingResolverImpl implements MappingResolver { ); } - private void reportErrorWhenAmbigious(List> candidates, Type target) { + private void reportErrorWhenAmbiguous(List> candidates, Type target) { // raise an error if more than one mapping method is suitable to map the given source type // into the target type if ( candidates.size() > 1 ) { + String descriptionStr = ""; + if ( description != null ) { + descriptionStr = description.createSourcePropertyErrorMessage(); + } + else { + descriptionStr = sourceRHS.getSourceErrorMessagePart(); + } + if ( sourceRHS.getSourceErrorMessagePart() != null ) { messager.printMessage( mappingMethod.getExecutable(), positionHint, - Message.GENERAL_AMBIGIOUS_MAPPING_METHOD, - sourceRHS.getSourceErrorMessagePart(), + Message.GENERAL_AMBIGUOUS_MAPPING_METHOD, + descriptionStr, target, - Strings.join( candidates, ", " ) + join( candidates ) ); } else { messager.printMessage( mappingMethod.getExecutable(), positionHint, - Message.GENERAL_AMBIGIOUS_FACTORY_METHOD, + Message.GENERAL_AMBIGUOUS_FACTORY_METHOD, target, - Strings.join( candidates, ", " ) + join( candidates ) ); } } @@ -578,6 +592,18 @@ public class MappingResolverImpl implements MappingResolver { return false; } + private String join( List> candidates ) { + + String candidateStr = candidates.stream() + .limit( MAX_REPORTING_AMBIGUOUS ) + .map( m -> m.getMethod().shortName() ) + .collect( Collectors.joining( ", " ) ); + + if ( candidates.size() > MAX_REPORTING_AMBIGUOUS ) { + candidateStr += String.format( "... and %s more", candidates.size() - MAX_REPORTING_AMBIGUOUS ); + } + return candidateStr; + } } private static class ConversionAssignment { @@ -762,28 +788,26 @@ public class MappingResolverImpl implements MappingResolver { result = methodRefY; } else { - reportAmbigiousError( xCandidates, targetType ); + reportAmbiguousError( xCandidates, targetType ); } return this; } - void reportAmbigiousError(Map, List>> xCandidates, Type target) { + void reportAmbiguousError(Map, List>> xCandidates, Type target) { StringBuilder result = new StringBuilder(); xCandidates.entrySet() .stream() + .limit( MAX_REPORTING_AMBIGUOUS ) .forEach( e -> result.append( "method(s)Y: " ) - .append( e.getValue() - .stream() - .map( v -> v.getMethod().shortName() ) - .collect( Collectors.joining( ", " ) ) ) + .append( attempt.join( e.getValue() ) ) .append( ", methodX: " ) .append( e.getKey().getMethod().shortName() ) .append( "; " ) ); attempt.messager.printMessage( attempt.mappingMethod.getExecutable(), attempt.positionHint, - Message.GENERAL_AMBIGIOUS_MAPPING_METHODY_METHODX, + Message.GENERAL_AMBIGUOUS_MAPPING_METHODY_METHODX, attempt.sourceRHS.getSourceType().getName() + " " + attempt.sourceRHS.getSourceParameterName(), target.getName(), result.toString() ); @@ -878,28 +902,26 @@ public class MappingResolverImpl implements MappingResolver { result = methodRefY; } else { - reportAmbigiousError( xRefCandidates, targetType ); + reportAmbiguousError( xRefCandidates, targetType ); } return this; } - void reportAmbigiousError(Map>> xRefCandidates, Type target) { + void reportAmbiguousError(Map>> xRefCandidates, Type target) { StringBuilder result = new StringBuilder(); xRefCandidates.entrySet() .stream() + .limit( MAX_REPORTING_AMBIGUOUS ) .forEach( e -> result.append( "method(s)Y: " ) - .append( e.getValue() - .stream() - .map( v -> v.getMethod().shortName() ) - .collect( Collectors.joining( ", " ) ) ) + .append( attempt.join( e.getValue() ) ) .append( ", conversionX: " ) .append( e.getKey().shortName() ) .append( "; " ) ); attempt.messager.printMessage( attempt.mappingMethod.getExecutable(), attempt.positionHint, - Message.GENERAL_AMBIGIOUS_MAPPING_METHODY_CONVERSIONX, + Message.GENERAL_AMBIGUOUS_MAPPING_METHODY_CONVERSIONX, attempt.sourceRHS.getSourceType().getName() + " " + attempt.sourceRHS.getSourceParameterName(), target.getName(), result.toString() ); @@ -997,28 +1019,26 @@ public class MappingResolverImpl implements MappingResolver { result = conversionRefY.assignment; } else { - reportAmbigiousError( yRefCandidates, targetType ); + reportAmbiguousError( yRefCandidates, targetType ); } return this; } - void reportAmbigiousError(Map>> yRefCandidates, Type target) { + void reportAmbiguousError(Map>> yRefCandidates, Type target) { StringBuilder result = new StringBuilder(); yRefCandidates.entrySet() .stream() + .limit( MAX_REPORTING_AMBIGUOUS ) .forEach( e -> result.append( "conversionY: " ) .append( e.getKey().shortName() ) .append( ", method(s)X: " ) - .append( e.getValue() - .stream() - .map( v -> v.getMethod().shortName() ) - .collect( Collectors.joining( ", " ) ) ) + .append( attempt.join( e.getValue() ) ) .append( "; " ) ); attempt.messager.printMessage( attempt.mappingMethod.getExecutable(), attempt.positionHint, - Message.GENERAL_AMBIGIOUS_MAPPING_CONVERSIONY_METHODX, + Message.GENERAL_AMBIGUOUS_MAPPING_CONVERSIONY_METHODX, attempt.sourceRHS.getSourceType().getName() + " " + attempt.sourceRHS.getSourceParameterName(), target.getName(), result.toString() ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java index d10faf64b..e2a476ec9 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java @@ -7,6 +7,7 @@ package org.mapstruct.ap.internal.util; import javax.tools.Diagnostic; +import static org.mapstruct.ap.internal.util.MessageConstants.FAQ_AMBIGUOUS_URL; import static org.mapstruct.ap.internal.util.MessageConstants.FAQ_QUALIFIER_URL; /** @@ -111,9 +112,9 @@ public enum Message { GENERAL_NO_IMPLEMENTATION( "No implementation type is registered for return type %s." ), GENERAL_ABSTRACT_RETURN_TYPE( "The return type %s is an abstract class or interface. Provide a non abstract / non interface result type or a factory method." ), - GENERAL_AMBIGIOUS_MAPPING_METHOD( "Ambiguous mapping methods found for mapping %s to %s: %s." ), - GENERAL_AMBIGIOUS_FACTORY_METHOD( "Ambiguous factory methods found for creating %s: %s." ), - GENERAL_AMBIGIOUS_CONSTRUCTORS( "Ambiguous constructors found for creating %s. Either declare parameterless constructor or annotate the default constructor with an annotation named @Default." ), + GENERAL_AMBIGUOUS_MAPPING_METHOD( "Ambiguous mapping methods found for mapping %s to %s: %s. See " + FAQ_AMBIGUOUS_URL + " for more info." ), + GENERAL_AMBIGUOUS_FACTORY_METHOD( "Ambiguous factory methods found for creating %s: %s. See " + FAQ_AMBIGUOUS_URL + " for more info." ), + GENERAL_AMBIGUOUS_CONSTRUCTORS( "Ambiguous constructors found for creating %s. Either declare parameterless constructor or annotate the default constructor with an annotation named @Default." ), GENERAL_CONSTRUCTOR_PROPERTIES_NOT_MATCHING_PARAMETERS( "Incorrect @ConstructorProperties for %s. The size of the @ConstructorProperties does not match the number of constructor parameters" ), GENERAL_UNSUPPORTED_DATE_FORMAT_CHECK( "No dateFormat check is supported for types %s, %s" ), GENERAL_VALID_DATE( "Given date format \"%s\" is valid.", Diagnostic.Kind.NOTE ), @@ -125,9 +126,9 @@ public enum Message { GENERAL_NO_QUALIFYING_METHOD_NAMED( "Qualifier error. No method found annotated with @Named#value: [ %s ]. See " + FAQ_QUALIFIER_URL + " for more info." ), GENERAL_NO_QUALIFYING_METHOD_COMBINED( "Qualifier error. No method found annotated with @Named#value: [ %s ], annotated with [ %s ]. See " + FAQ_QUALIFIER_URL + " for more info." ), - GENERAL_AMBIGIOUS_MAPPING_METHODY_METHODX( "Ambiguous 2step methods found, mapping %s to %s. Found methodY( methodX ( parameter ) ): %s." ), - GENERAL_AMBIGIOUS_MAPPING_CONVERSIONY_METHODX( "Ambiguous 2step methods found, mapping %s to %s. Found conversionY( methodX ( parameter ) ): %s." ), - GENERAL_AMBIGIOUS_MAPPING_METHODY_CONVERSIONX( "Ambiguous 2step methods found, mapping %s to %s. Found methodY( conversionX ( parameter ) ): %s." ), + GENERAL_AMBIGUOUS_MAPPING_METHODY_METHODX( "Ambiguous 2step methods found, mapping %s to %s. Found methodY( methodX ( parameter ) ): %s." ), + GENERAL_AMBIGUOUS_MAPPING_CONVERSIONY_METHODX( "Ambiguous 2step methods found, mapping %s to %s. Found conversionY( methodX ( parameter ) ): %s." ), + GENERAL_AMBIGUOUS_MAPPING_METHODY_CONVERSIONX( "Ambiguous 2step methods found, mapping %s to %s. Found methodY( conversionX ( parameter ) ): %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 ), diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/MessageConstants.java b/processor/src/main/java/org/mapstruct/ap/internal/util/MessageConstants.java index d3dabdb2d..6b4603af1 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/MessageConstants.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/MessageConstants.java @@ -9,6 +9,7 @@ public final class MessageConstants { public static final String AND = " and "; public static final String FAQ_QUALIFIER_URL = "https://mapstruct.org/faq/#qualifier"; + public static final String FAQ_AMBIGUOUS_URL = "https://mapstruct.org/faq/#ambiguous"; private MessageConstants() { } diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1242/Issue1242Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1242/Issue1242Test.java index 0cf59e726..80e103812 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1242/Issue1242Test.java +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1242/Issue1242Test.java @@ -65,7 +65,8 @@ public class Issue1242Test { ".lang.Class clazz), org.mapstruct.ap.test.bugs._1242" + ".TargetB org.mapstruct.ap.test.bugs._1242.TargetFactories.createTargetB(@TargetType java.lang" + ".Class clazz), org.mapstruct.ap.test.bugs._1242" + - ".TargetB org.mapstruct.ap.test.bugs._1242.TargetFactories.createTargetB().") + ".TargetB org.mapstruct.ap.test.bugs._1242.TargetFactories.createTargetB()." + + " See https://mapstruct.org/faq/#ambiguous for more info." ) }) public void ambiguousMethodErrorForTwoFactoryMethodsWithSourceParam() { } diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousannotatedfactorymethod/AmbiguousAnnotatedFactoryTest.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousannotatedfactorymethod/AmbiguousAnnotatedFactoryTest.java index 94993e4a6..24cdbe3a5 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousannotatedfactorymethod/AmbiguousAnnotatedFactoryTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousannotatedfactorymethod/AmbiguousAnnotatedFactoryTest.java @@ -36,7 +36,8 @@ public class AmbiguousAnnotatedFactoryTest { ".ambiguousannotatedfactorymethod.Foo foo), org.mapstruct.ap.test.erroneous" + ".ambiguousannotatedfactorymethod.Bar org.mapstruct.ap.test.erroneous" + ".ambiguousannotatedfactorymethod.AmbiguousBarFactory.createBar(org.mapstruct.ap.test.erroneous" + - ".ambiguousannotatedfactorymethod.Foo foo).") + ".ambiguousannotatedfactorymethod.Foo foo)." + + " See https://mapstruct.org/faq/#ambiguous for more info.") } ) diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java index e4e9ff81c..682c46d03 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java @@ -37,8 +37,8 @@ public class FactoryTest { message = "Ambiguous factory methods found for creating org.mapstruct.ap.test.erroneous" + ".ambiguousfactorymethod.Bar: org.mapstruct.ap.test.erroneous.ambiguousfactorymethod.Bar " + "createBar(), org.mapstruct.ap.test.erroneous.ambiguousfactorymethod.Bar org.mapstruct.ap.test" + - ".erroneous.ambiguousfactorymethod.a.BarFactory.createBar().") - + ".erroneous.ambiguousfactorymethod.a.BarFactory.createBar()." + + " See https://mapstruct.org/faq/#ambiguous for more info.") } ) public void shouldUseTwoFactoryMethods() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/AmbigiousMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/AmbigiousMapperTest.java new file mode 100644 index 000000000..a04373b13 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/AmbigiousMapperTest.java @@ -0,0 +1,67 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.erroneous.ambiguousmapping; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +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.runner.AnnotationProcessorTestRunner; + +@IssueKey("2156") +@RunWith(AnnotationProcessorTestRunner.class) +public class AmbigiousMapperTest { + + @Test + @WithClasses( ErroneousWithAmbiguousMethodsMapper.class) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic(type = ErroneousWithAmbiguousMethodsMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 16, + message = "Ambiguous mapping methods found for mapping property " + + "\"org.mapstruct.ap.test.erroneous.ambiguousmapping." + + "ErroneousWithAmbiguousMethodsMapper.LeafDTO branch.leaf\" to " + + "org.mapstruct.ap.test.erroneous.ambiguousmapping." + + "ErroneousWithAmbiguousMethodsMapper.LeafEntity: " + + "LeafEntity:map1(LeafDTO), LeafEntity:map2(LeafDTO). " + + "See https://mapstruct.org/faq/#ambiguous for more info.") + } + ) + + public void testErrorMessageForAmbiguous() { + } + + @Test + @WithClasses( ErroneousWithMoreThanFiveAmbiguousMethodsMapper.class) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic(type = ErroneousWithMoreThanFiveAmbiguousMethodsMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 17, + message = "Ambiguous mapping methods found for mapping property " + + "\"org.mapstruct.ap.test.erroneous.ambiguousmapping." + + "ErroneousWithMoreThanFiveAmbiguousMethodsMapper.LeafDTO branch.leaf\" to " + + "org.mapstruct.ap.test.erroneous.ambiguousmapping." + + "ErroneousWithMoreThanFiveAmbiguousMethodsMapper.LeafEntity: " + + "LeafEntity:map1(LeafDTO), " + + "LeafEntity:map2(LeafDTO), " + + "LeafEntity:map3(LeafDTO), " + + "LeafEntity:map4(LeafDTO), " + + "LeafEntity:map5(LeafDTO)" + + "... and 1 more. " + + "See https://mapstruct.org/faq/#ambiguous for more info.") + } + ) + public void testErrorMessageForManyAmbiguous() { + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/ErroneousWithAmbiguousMethodsMapper.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/ErroneousWithAmbiguousMethodsMapper.java new file mode 100644 index 000000000..7ebce015d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/ErroneousWithAmbiguousMethodsMapper.java @@ -0,0 +1,52 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.erroneous.ambiguousmapping; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface ErroneousWithAmbiguousMethodsMapper { + + ErroneousWithAmbiguousMethodsMapper INSTANCE = Mappers.getMapper( ErroneousWithAmbiguousMethodsMapper.class ); + + TrunkEntity map(TrunkDTO dto); + + default LeafEntity map1(LeafDTO dto) { + return new LeafEntity(); + } + + // duplicated method, triggering ambigious mapping method + default LeafEntity map2(LeafDTO dto) { + return new LeafEntity(); + } + + // CHECKSTYLE:OFF + class TrunkDTO { + public BranchDTO branch; + } + + class BranchDTO { + public LeafDTO leaf; + } + + class LeafDTO { + public int numberOfVeigns; + } + + class TrunkEntity { + public BranchEntity branch; + } + + class BranchEntity { + public LeafEntity leaf; + } + + class LeafEntity { + public int numberOfVeigns; + } + // CHECKSTYLE ON +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/ErroneousWithMoreThanFiveAmbiguousMethodsMapper.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/ErroneousWithMoreThanFiveAmbiguousMethodsMapper.java new file mode 100644 index 000000000..1e050cea7 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousmapping/ErroneousWithMoreThanFiveAmbiguousMethodsMapper.java @@ -0,0 +1,74 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.erroneous.ambiguousmapping; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface ErroneousWithMoreThanFiveAmbiguousMethodsMapper { + + ErroneousWithMoreThanFiveAmbiguousMethodsMapper + INSTANCE = Mappers.getMapper( ErroneousWithMoreThanFiveAmbiguousMethodsMapper.class ); + + TrunkEntity map(TrunkDTO dto); + + default LeafEntity map1(LeafDTO dto) { + return new LeafEntity(); + } + + // duplicated method, triggering ambigious mapping method + default LeafEntity map2(LeafDTO dto) { + return new LeafEntity(); + } + + // duplicated method, triggering ambigious mapping method + default LeafEntity map3(LeafDTO dto) { + return new LeafEntity(); + } + + // duplicated method, triggering ambigious mapping method + default LeafEntity map4(LeafDTO dto) { + return new LeafEntity(); + } + + // duplicated method, triggering ambigious mapping method + + default LeafEntity map5(LeafDTO dto) { + return new LeafEntity(); + } + + // duplicated method, triggering ambigious mapping method + default LeafEntity map6(LeafDTO dto) { + return new LeafEntity(); + } + + // CHECKSTYLE:OFF + class TrunkDTO { + public BranchDTO branch; + } + + class BranchDTO { + public LeafDTO leaf; + } + + class LeafDTO { + public int numberOfVeigns; + } + + class TrunkEntity { + public BranchEntity branch; + } + + class BranchEntity { + public LeafEntity leaf; + } + + class LeafEntity { + public int numberOfVeigns; + } + // CHECKSTYLE ON +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/inheritance/complex/ComplexInheritanceTest.java b/processor/src/test/java/org/mapstruct/ap/test/inheritance/complex/ComplexInheritanceTest.java index dc37b5f79..7c2459b11 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/inheritance/complex/ComplexInheritanceTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/inheritance/complex/ComplexInheritanceTest.java @@ -69,13 +69,12 @@ public class ComplexInheritanceTest { kind = Kind.ERROR, type = ErroneousSourceCompositeTargetCompositeMapper.class, line = 19, - message = "Ambiguous mapping methods found for mapping property \"org.mapstruct.ap.test.inheritance" + - ".complex.SourceExt prop1\" to org.mapstruct.ap.test.inheritance.complex.Reference: org.mapstruct.ap" + - ".test.inheritance.complex.Reference org.mapstruct.ap.test.inheritance.complex" + - ".AdditionalMappingHelper.asReference(org.mapstruct.ap.test.inheritance.complex.SourceBase source), " + - "org.mapstruct.ap.test.inheritance.complex.Reference org.mapstruct.ap.test.inheritance.complex" + - ".AdditionalMappingHelper.asReference(org.mapstruct.ap.test.inheritance.complex.AdditionalFooSource " + - "source).")) + message = "Ambiguous mapping methods found for mapping property " + + "\"org.mapstruct.ap.test.inheritance.complex.SourceExt prop1\" " + + "to org.mapstruct.ap.test.inheritance.complex.Reference: " + + "Reference:asReference(SourceBase), Reference:asReference(AdditionalFooSource). " + + "See https://mapstruct.org/faq/#ambiguous for more info.") + ) public void ambiguousMappingMethodsReportError() { } diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/resulttype/InheritanceSelectionTest.java b/processor/src/test/java/org/mapstruct/ap/test/selection/resulttype/InheritanceSelectionTest.java index 5cd415e56..9db58ec20 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/selection/resulttype/InheritanceSelectionTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/resulttype/InheritanceSelectionTest.java @@ -48,7 +48,9 @@ public class InheritanceSelectionTest { message = "Ambiguous factory methods found for creating org.mapstruct.ap.test.selection.resulttype" + ".Fruit: org.mapstruct.ap.test.selection.resulttype.Apple org.mapstruct.ap.test.selection" + ".resulttype.ConflictingFruitFactory.createApple(), org.mapstruct.ap.test.selection.resulttype" + - ".Banana org.mapstruct.ap.test.selection.resulttype.ConflictingFruitFactory.createBanana().") + ".Banana org.mapstruct.ap.test.selection.resulttype.ConflictingFruitFactory.createBanana()." + + " See https://mapstruct.org/faq/#ambiguous for more info." + ) } ) public void testForkedInheritanceHierarchyShouldResultInAmbigousMappingMethod() {