#1140 Add warning when target has no properties

This commit is contained in:
zral 2025-05-11 19:59:59 +02:00 committed by GitHub
parent 2c84d04463
commit 602e29083f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
71 changed files with 657 additions and 85 deletions

View File

@ -235,9 +235,10 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
this.unprocessedTargetProperties = new LinkedHashMap<>( accessors );
boolean constructorAccessorHadError = false;
if ( !method.isUpdateMethod() && !hasFactoryMethod ) {
ConstructorAccessor constructorAccessor = getConstructorAccessor( resultTypeToMap );
if ( constructorAccessor != null ) {
if ( constructorAccessor != null && !constructorAccessor.hasError ) {
this.unprocessedConstructorProperties = constructorAccessor.constructorAccessors;
@ -250,8 +251,10 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
else {
this.unprocessedConstructorProperties = new LinkedHashMap<>();
}
constructorAccessorHadError = constructorAccessor != null && constructorAccessor.hasError;
this.targetProperties.addAll( this.unprocessedConstructorProperties.keySet() );
this.unprocessedTargetProperties.putAll( this.unprocessedConstructorProperties );
}
else {
@ -322,7 +325,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
// report errors on unmapped properties
if ( shouldHandledDefinedMappings ) {
reportErrorForUnmappedTargetPropertiesIfRequired();
reportErrorForUnmappedTargetPropertiesIfRequired( resultTypeToMap, constructorAccessorHadError );
reportErrorForUnmappedSourcePropertiesIfRequired();
}
reportErrorForMissingIgnoredSourceProperties();
@ -964,7 +967,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
)
.collect( Collectors.joining( ", " ) )
);
return null;
return new ConstructorAccessor( true, Collections.emptyList(), Collections.emptyMap() );
}
else {
return getConstructorAccessor( type, accessibleConstructors.get( 0 ) );
@ -1023,7 +1026,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
GENERAL_CONSTRUCTOR_PROPERTIES_NOT_MATCHING_PARAMETERS,
type
);
return null;
return new ConstructorAccessor( true, Collections.emptyList(), Collections.emptyMap() );
}
else {
Map<String, Accessor> constructorAccessors = new LinkedHashMap<>();
@ -1731,36 +1734,45 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
return method.getOptions().getMapper().unmappedTargetPolicy();
}
private void reportErrorForUnmappedTargetPropertiesIfRequired() {
private void reportErrorForUnmappedTargetPropertiesIfRequired(Type resultType,
boolean constructorAccessorHadError) {
// fetch settings from element to implement
ReportingPolicyGem unmappedTargetPolicy = getUnmappedTargetPolicy();
if ( method instanceof ForgedMethod && targetProperties.isEmpty() ) {
//TODO until we solve 1140 we report this error when the target properties are empty
ForgedMethod forgedMethod = (ForgedMethod) method;
if ( forgedMethod.getHistory() == null ) {
Type sourceType = this.method.getParameters().get( 0 ).getType();
Type targetType = this.method.getReturnType();
ctx.getMessager().printMessage(
this.method.getExecutable(),
Message.PROPERTYMAPPING_FORGED_MAPPING_NOT_FOUND,
sourceType.describe(),
targetType.describe(),
targetType.describe(),
sourceType.describe()
);
if ( targetProperties.isEmpty() ) {
if ( method instanceof ForgedMethod ) {
ForgedMethod forgedMethod = (ForgedMethod) method;
if ( forgedMethod.getHistory() == null ) {
Type sourceType = this.method.getParameters().get( 0 ).getType();
Type targetType = this.method.getReturnType();
ctx.getMessager().printMessage(
this.method.getExecutable(),
Message.PROPERTYMAPPING_FORGED_MAPPING_NOT_FOUND,
sourceType.describe(),
targetType.describe(),
targetType.describe(),
sourceType.describe()
);
}
else {
ForgedMethodHistory history = forgedMethod.getHistory();
ctx.getMessager().printMessage(
this.method.getExecutable(),
Message.PROPERTYMAPPING_FORGED_MAPPING_WITH_HISTORY_NOT_FOUND,
history.createSourcePropertyErrorMessage(),
history.getTargetType().describe(),
history.createTargetPropertyName(),
history.getTargetType().describe(),
history.getSourceType().describe()
);
}
}
else {
ForgedMethodHistory history = forgedMethod.getHistory();
else if ( !constructorAccessorHadError ) {
ctx.getMessager().printMessage(
this.method.getExecutable(),
Message.PROPERTYMAPPING_FORGED_MAPPING_WITH_HISTORY_NOT_FOUND,
history.createSourcePropertyErrorMessage(),
history.getTargetType().describe(),
history.createTargetPropertyName(),
history.getTargetType().describe(),
history.getSourceType().describe()
method.getExecutable(),
Message.PROPERTYMAPPING_TARGET_HAS_NO_TARGET_PROPERTIES,
resultType.describe()
);
}
}
@ -1780,7 +1792,8 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
reportErrorForUnmappedProperties(
unprocessedTargetProperties,
unmappedPropertiesMsg,
unmappedForgedPropertiesMsg );
unmappedForgedPropertiesMsg
);
}
}
@ -1907,12 +1920,19 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
}
private static class ConstructorAccessor {
private final boolean hasError;
private final List<ParameterBinding> parameterBindings;
private final Map<String, Accessor> constructorAccessors;
private ConstructorAccessor(
List<ParameterBinding> parameterBindings,
Map<String, Accessor> constructorAccessors) {
this( false, parameterBindings, constructorAccessors );
}
private ConstructorAccessor(boolean hasError, List<ParameterBinding> parameterBindings,
Map<String, Accessor> constructorAccessors) {
this.hasError = hasError;
this.parameterBindings = parameterBindings;
this.constructorAccessors = constructorAccessors;
}

View File

@ -92,6 +92,7 @@ public enum Message {
PROPERTYMAPPING_CANNOT_DETERMINE_SOURCE_PARAMETER_FROM_TARGET("No property named \"%s\" exists in source parameter(s). Please define the source explicitly."),
PROPERTYMAPPING_NO_SUITABLE_COLLECTION_OR_MAP_CONSTRUCTOR( "%s does not have an accessible copy or no-args constructor." ),
PROPERTYMAPPING_EXPRESSION_AND_CONDITION_QUALIFIED_BY_NAME_BOTH_DEFINED( "Expression and condition qualified by name are both defined in @Mapping, either define an expression or a condition qualified by name." ),
PROPERTYMAPPING_TARGET_HAS_NO_TARGET_PROPERTIES( "No target property found for target \"%s\".", Diagnostic.Kind.WARNING ),
CONVERSION_LOSSY_WARNING( "%s has a possibly lossy conversion from %s to %s.", Diagnostic.Kind.WARNING ),
CONVERSION_LOSSY_ERROR( "Can't map %s. It has a possibly lossy conversion from %s to %s." ),

View File

@ -7,6 +7,7 @@ package org.mapstruct.ap.test.annotatewith;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mapstruct.Mapper;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
import org.mapstruct.ap.testutil.WithClasses;
@ -176,12 +177,12 @@ public class AnnotateWithTest {
@Diagnostic(
kind = javax.tools.Diagnostic.Kind.ERROR,
type = ErroneousMapperWithClassOnMethod.class,
line = 17,
line = 18,
message = "Annotation \"CustomClassOnlyAnnotation\" is not allowed on methods."
)
}
)
@WithClasses({ ErroneousMapperWithClassOnMethod.class, CustomClassOnlyAnnotation.class })
@WithClasses({ ErroneousMapperWithClassOnMethod.class, CustomClassOnlyAnnotation.class, WithProperties.class })
public void erroneousMapperWithClassOnMethod() {
}

View File

@ -7,6 +7,7 @@ package org.mapstruct.ap.test.annotatewith;
import org.mapstruct.AnnotateWith;
import org.mapstruct.Mapper;
import org.mapstruct.ap.test.WithProperties;
/**
* @author Ben Zegveld
@ -15,13 +16,6 @@ import org.mapstruct.Mapper;
public interface ErroneousMapperWithClassOnMethod {
@AnnotateWith( value = CustomClassOnlyAnnotation.class )
Target toString(Source value);
WithProperties toString(String string);
class Source {
}
class Target {
}
}

View File

@ -24,8 +24,29 @@ public interface Issue1111Mapper {
List<List<Target>> listList(List<List<Source>> in);
class Source { }
class Source {
private final String value;
class Target { }
public Source(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
class Target {
private final String value;
public Target(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}

View File

@ -27,7 +27,7 @@ public class Issue1111Test {
@ProcessorTest
public void shouldCompile() {
List<List<Source>> source = Arrays.asList( Arrays.asList( new Source() ) );
List<List<Source>> source = Arrays.asList( Arrays.asList( new Source( "test" ) ) );
List<List<Issue1111Mapper.Target>> target = Issue1111Mapper.INSTANCE.listList( source );

View File

@ -30,6 +30,16 @@ public abstract class Issue1130Mapper {
}
static class BEntity {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
static class ADto {
@ -46,6 +56,7 @@ public abstract class Issue1130Mapper {
class BDto {
private final String passedViaConstructor;
private String id;
BDto(String passedViaConstructor) {
this.passedViaConstructor = passedViaConstructor;
@ -54,6 +65,14 @@ public abstract class Issue1130Mapper {
String getPassedViaConstructor() {
return passedViaConstructor;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
abstract void mergeA(AEntity source, @MappingTarget ADto target);

View File

@ -7,13 +7,14 @@ package org.mapstruct.ap.test.bugs._1242;
import org.mapstruct.Mapper;
import org.mapstruct.ObjectFactory;
import org.mapstruct.ReportingPolicy;
/**
* Results in an ambiguous factory method error, as there are two methods with matching source types available.
*
* @author Andreas Gudian
*/
@Mapper(uses = TargetFactories.class)
@Mapper(uses = TargetFactories.class, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class ErroneousIssue1242MapperMultipleSources {
abstract TargetA toTargetA(SourceA source);

View File

@ -7,13 +7,14 @@ package org.mapstruct.ap.test.bugs._1242;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.ReportingPolicy;
/**
* Test mapper for properly resolving the best fitting factory method
*
* @author Andreas Gudian
*/
@Mapper(uses = TargetFactories.class)
@Mapper(uses = TargetFactories.class, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class Issue1242Mapper {
abstract TargetA toTargetA(SourceA source);

View File

@ -54,7 +54,7 @@ public class Issue1242Test {
diagnostics = {
@Diagnostic(type = ErroneousIssue1242MapperMultipleSources.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 20,
line = 21,
message = "Ambiguous factory methods found for creating TargetB: " +
"TargetB anotherTargetBCreator(SourceB source), " +
"TargetB TargetFactories.createTargetB(SourceB source, @TargetType Class<TargetB> clazz), " +

View File

@ -9,6 +9,7 @@ package org.mapstruct.ap.test.bugs._1242;
* @author Andreas Gudian
*/
class TargetB {
protected String value;
private final String passedViaConstructor;
TargetB(String passedViaConstructor) {
@ -18,4 +19,12 @@ class TargetB {
String getPassedViaConstructor() {
return passedViaConstructor;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -27,8 +27,17 @@ public interface Issue1345Mapper {
class A {
private String value;
private String readOnlyProperty;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getReadOnlyProperty() {
return readOnlyProperty;
}
@ -36,8 +45,17 @@ public interface Issue1345Mapper {
class B {
private String value;
private String property;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getProperty() {
return property;
}

View File

@ -18,13 +18,13 @@ public abstract class Issue1460Mapper {
public abstract Target map(Source source);
public abstract String forceUsageOfIssue1460Enum(Issue1460Enum source);
public abstract Value<Issue1460Enum> forceUsageOfIssue1460Enum(Issue1460Enum source);
public abstract String forceUsageOfLocale(Locale source);
public abstract Value<Locale> forceUsageOfLocale(Locale source);
public abstract String forceUsageOfLocalDate(LocalDate source);
public abstract Value<LocalDate> forceUsageOfLocalDate(LocalDate source);
public abstract String forceUsageOfDateTime(DateTime source);
public abstract Value<DateTime> forceUsageOfDateTime(DateTime source);
public static class Issue1460Enum {
}
@ -37,4 +37,17 @@ public abstract class Issue1460Mapper {
public static class DateTime {
}
public static class Value<T> {
private final T source;
public Value(T source) {
this.source = source;
}
public T getSource() {
return source;
}
}
}

View File

@ -18,8 +18,17 @@ public abstract class Issue1460JavaTimeMapper {
public abstract Target map(Source source);
public abstract String forceUsageOfLocalDate(LocalDate source);
public abstract LocalTarget forceUsageOfLocalDate(LocalDate source);
public static class LocalDate {
}
public static class LocalTarget {
private final LocalDate source;
public LocalTarget(LocalDate source) {
this.source = source;
}
}
}

View File

@ -6,4 +6,14 @@
package org.mapstruct.ap.test.bugs._1590;
public class Book {
private final String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -28,7 +28,7 @@ public class Issue1590Test {
@ProcessorTest
public void shouldTestMappingLocalDates() {
BookShelf source = new BookShelf();
source.setBooks( Arrays.asList( new Book() ) );
source.setBooks( Arrays.asList( new Book("Test") ) );
BookShelf target = BookShelfMapper.INSTANCE.map( source );

View File

@ -6,4 +6,14 @@
package org.mapstruct.ap.test.bugs._1650;
public class C {
private final int value;
public C(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}

View File

@ -6,4 +6,14 @@
package org.mapstruct.ap.test.bugs._1650;
public class CPrime {
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}

View File

@ -27,7 +27,7 @@ public class Issue1650Test {
A a = new A();
a.setB( new B() );
a.getB().setC( new C() );
a.getB().setC( new C( 10 ) );
APrime aPrime = new APrime();

View File

@ -22,11 +22,31 @@ public interface Issue1821Mapper {
ExtendedTarget mapExtended(Source source);
class Target {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
class ExtendedTarget extends Target {
}
class Source {
private final String value;
public Source(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}

View File

@ -15,7 +15,7 @@ public class Issue1821Test {
@ProcessorTest
public void shouldNotGiveNullPtr() {
Issue1821Mapper.INSTANCE.map( new Issue1821Mapper.Source() );
Issue1821Mapper.INSTANCE.map( new Issue1821Mapper.Source( "test" ) );
}
}

View File

@ -43,8 +43,8 @@ public class Issue611Test {
*/
@ProcessorTest
public void rightMapperIsFound() {
SomeClass.InnerMapper.Source source1 = new SomeClass.InnerMapper.Source();
SomeOtherClass.InnerMapper.Source source2 = new SomeOtherClass.InnerMapper.Source();
SomeClass.InnerMapper.Source source1 = new SomeClass.InnerMapper.Source( "test" );
SomeOtherClass.InnerMapper.Source source2 = new SomeOtherClass.InnerMapper.Source( "test2" );
SomeClass.InnerMapper.Target target1 = SomeClass.InnerMapper.INSTANCE.toTarget( source1 );
SomeOtherClass.InnerMapper.Target target2 = SomeOtherClass.InnerMapper.INSTANCE.toTarget( source2 );

View File

@ -19,9 +19,29 @@ public class SomeClass {
Target toTarget(Source in);
class Source {
private final String value;
public Source(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
class Target {
private final String value;
public Target(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
@ -33,9 +53,29 @@ public class SomeClass {
Target toTarget(Source in);
class Source {
private final String value;
public Source(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
class Target {
private final String value;
public Target(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
}

View File

@ -19,9 +19,29 @@ public class SomeOtherClass {
Target toTarget(Source in);
class Source {
private final String value;
public Source(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
class Target {
private final String value;
public Target(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
}

View File

@ -9,6 +9,9 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
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.GeneratedSource;
import static org.assertj.core.api.Assertions.assertThat;
@ -80,6 +83,17 @@ public class BuilderInfoTargetTest {
}
@ProcessorTest
@WithClasses( {
SimpleImmutableUpdateMapper.class
} )
@ExpectedCompilationOutcome(value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = SimpleImmutableUpdateMapper.class,
kind = javax.tools.Diagnostic.Kind.WARNING,
line = 18,
message = "No target property found for target \"SimpleImmutableTarget\"."),
})
public void updatingTargetWithNoSettersShouldNotFail() {
SimpleMutableSource source = new SimpleMutableSource();
@ -90,7 +104,7 @@ public class BuilderInfoTargetTest {
.build();
assertThat( target.getAge() ).isEqualTo( 20 );
SimpleBuilderMapper.INSTANCE.toImmutable( source, target );
SimpleImmutableUpdateMapper.INSTANCE.toImmutable( source, target );
assertThat( target.getAge() ).isEqualTo( 20 );
}
}

View File

@ -21,9 +21,6 @@ public interface SimpleBuilderMapper {
@Mapping(target = "builder.name", source = "source.fullName")
void updateImmutable(SimpleMutableSource source, @MappingTarget SimpleImmutableTarget.Builder builder);
// This method is fine as if the mapping target has setters it would use them, otherwise it won't
void toImmutable(SimpleMutableSource source, @MappingTarget SimpleImmutableTarget target);
@Mapping(target = "name", source = "fullName")
SimpleImmutableTarget toImmutable(SimpleMutableSource source);

View File

@ -0,0 +1,19 @@
/*
* 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.builder.mappingTarget.simple;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SimpleImmutableUpdateMapper {
SimpleImmutableUpdateMapper INSTANCE = Mappers.getMapper( SimpleImmutableUpdateMapper.class );
// This method is fine as if the mapping target has setters it would use them, otherwise it won't
void toImmutable(SimpleMutableSource source, @MappingTarget SimpleImmutableTarget target);
}

View File

@ -11,6 +11,9 @@ import java.util.Collections;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
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 static org.assertj.core.api.Assertions.assertThat;
@ -41,6 +44,13 @@ public class ImmutableProductTest {
CupboardNoSetterMapper.class,
CupboardEntityOnlyGetter.class
})
@ExpectedCompilationOutcome(value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = CupboardNoSetterMapper.class,
kind = javax.tools.Diagnostic.Kind.WARNING,
line = 22,
message = "No target property found for target \"CupboardEntityOnlyGetter\"."),
})
public void shouldIgnoreImmutableTarget() {
CupboardDto in = new CupboardDto();
in.setContent( Arrays.asList( "flour", "peas" ) );

View File

@ -11,4 +11,13 @@ package org.mapstruct.ap.test.collection.wildcard;
*/
public class Idea {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -11,4 +11,13 @@ package org.mapstruct.ap.test.collection.wildcard;
*/
public class Plan {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -10,6 +10,9 @@ import org.mapstruct.ap.test.constructor.PersonDto;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
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 static org.assertj.core.api.Assertions.assertThat;
@ -44,6 +47,15 @@ public class ConstructorVisibilityTest {
@WithClasses({
SimpleWithPublicParameterlessConstructorMapper.class
})
@ExpectedCompilationOutcome(value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = SimpleWithPublicParameterlessConstructorMapper.class,
kind = javax.tools.Diagnostic.Kind.WARNING,
line = 21,
message = "No target property found for target " +
"\"SimpleWithPublicParameterlessConstructorMapper.Person\"."),
})
public void shouldUsePublicParameterConstructorIfPresent() {
PersonDto source = new PersonDto();
source.setName( "Bob" );

View File

@ -16,5 +16,5 @@ public abstract class AbstractDestinationClassNameMapper {
public static final AbstractDestinationClassNameMapper INSTANCE =
Mappers.getMapper( AbstractDestinationClassNameMapper.class );
public abstract String intToString(Integer source);
public abstract Target map(Integer source);
}

View File

@ -16,5 +16,5 @@ public abstract class AbstractDestinationPackageNameMapper {
public static final AbstractDestinationPackageNameMapper INSTANCE =
Mappers.getMapper( AbstractDestinationPackageNameMapper.class );
public abstract String intToString(Integer source);
public abstract Target map(Integer source);
}

View File

@ -15,5 +15,5 @@ import org.mapstruct.factory.Mappers;
public interface DestinationClassNameMapper {
DestinationClassNameMapper INSTANCE = Mappers.getMapper( DestinationClassNameMapper.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -17,5 +17,5 @@ import org.mapstruct.factory.Mappers;
public interface DestinationClassNameMapperDecorated {
DestinationClassNameMapperDecorated INSTANCE = Mappers.getMapper( DestinationClassNameMapperDecorated.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -16,7 +16,7 @@ public abstract class DestinationClassNameMapperDecorator implements Destination
}
@Override
public String intToString(Integer source) {
return delegate.intToString( source );
public Target map(Integer source) {
return delegate.map( source );
}
}

View File

@ -15,5 +15,5 @@ import org.mapstruct.factory.Mappers;
public interface DestinationClassNameMapperWithConfig {
DestinationClassNameMapperWithConfig INSTANCE = Mappers.getMapper( DestinationClassNameMapperWithConfig.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -16,5 +16,5 @@ public interface DestinationClassNameMapperWithConfigOverride {
DestinationClassNameMapperWithConfigOverride INSTANCE =
Mappers.getMapper( DestinationClassNameMapperWithConfigOverride.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.fail;
/**
* @author Christophe Labouisse on 27/05/2015.
*/
@WithClasses( Target.class )
public class DestinationClassNameTest {
@ProcessorTest
@WithClasses({ DestinationClassNameMapper.class })

View File

@ -13,5 +13,5 @@ import org.mapstruct.MappingConstants;
*/
@Mapper(implementationName = "<CLASS_NAME>Jsr330Impl", componentModel = MappingConstants.ComponentModel.JSR330)
public interface DestinationClassNameWithJsr330Mapper {
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -15,5 +15,5 @@ import org.mapstruct.factory.Mappers;
public interface DestinationPackageNameMapper {
DestinationPackageNameMapper INSTANCE = Mappers.getMapper( DestinationPackageNameMapper.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -17,5 +17,5 @@ import org.mapstruct.factory.Mappers;
public interface DestinationPackageNameMapperDecorated {
DestinationPackageNameMapperDecorated INSTANCE = Mappers.getMapper( DestinationPackageNameMapperDecorated.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -16,7 +16,7 @@ public abstract class DestinationPackageNameMapperDecorator implements Destinati
}
@Override
public String intToString(Integer source) {
return delegate.intToString( source );
public Target map(Integer source) {
return delegate.map( source );
}
}

View File

@ -15,5 +15,5 @@ import org.mapstruct.factory.Mappers;
public interface DestinationPackageNameMapperWithConfig {
DestinationPackageNameMapperWithConfig INSTANCE = Mappers.getMapper( DestinationPackageNameMapperWithConfig.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -16,5 +16,5 @@ public interface DestinationPackageNameMapperWithConfigOverride {
DestinationPackageNameMapperWithConfigOverride INSTANCE =
Mappers.getMapper( DestinationPackageNameMapperWithConfigOverride.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -15,5 +15,5 @@ import org.mapstruct.factory.Mappers;
public interface DestinationPackageNameMapperWithSuffix {
DestinationPackageNameMapperWithSuffix INSTANCE = Mappers.getMapper( DestinationPackageNameMapperWithSuffix.class );
String intToString(Integer source);
Target map(Integer source);
}

View File

@ -15,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Christophe Labouisse on 27/05/2015.
*/
@IssueKey( "556" )
@WithClasses( Target.class )
public class DestinationPackageNameTest {
@ProcessorTest
@WithClasses({ DestinationPackageNameMapper.class })

View File

@ -0,0 +1,19 @@
/*
* 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.destination;
public class Target {
private final Integer source;
public Target(Integer source) {
this.source = source;
}
public Integer getSource() {
return source;
}
}

View File

@ -0,0 +1,9 @@
/*
* 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.emptytarget;
public class EmptyTarget {
}

View File

@ -0,0 +1,18 @@
/*
* 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.emptytarget;
import org.mapstruct.Mapper;
@Mapper
public interface EmptyTargetMapper {
TargetWithNoSetters mapToTargetWithSetters(Source source);
EmptyTarget mapToEmptyTarget(Source source);
Target mapToTarget(Source source);
}

View File

@ -0,0 +1,39 @@
/*
* 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.emptytarget;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
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;
@IssueKey("1140")
@WithClasses({
EmptyTarget.class,
EmptyTargetMapper.class,
Source.class,
Target.class,
TargetWithNoSetters.class,
})
class EmptyTargetTest {
@ProcessorTest
@ExpectedCompilationOutcome(value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = EmptyTargetMapper.class,
kind = javax.tools.Diagnostic.Kind.WARNING,
line = 13,
message = "No target property found for target \"TargetWithNoSetters\"."),
@Diagnostic(type = EmptyTargetMapper.class,
kind = javax.tools.Diagnostic.Kind.WARNING,
line = 15,
message = "No target property found for target \"EmptyTarget\".")
})
void shouldProvideWarnings() {
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.emptytarget;
public class Source {
private String label;
private double weight;
private Object content;
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.emptytarget;
/**
* @author Filip Hrisafov
*/
public class Target {
private final String label;
private final double weight;
private final Object content;
public Target(String label, double weight, Object content) {
this.label = label;
this.weight = weight;
this.content = content;
}
public String getLabel() {
return label;
}
public double getWeight() {
return weight;
}
public Object getContent() {
return content;
}
}

View File

@ -0,0 +1,15 @@
/*
* 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.emptytarget;
public class TargetWithNoSetters {
private int flightNumber;
private String airplaneName;
public String getAirplaneName() {
return airplaneName;
}
}

View File

@ -25,7 +25,7 @@ public interface SourceTargetMapper {
ParseException sourceToTarget(Named source);
//custom types
Map listToMap(List list);
Value<Map> listToMap(List list);
java.util.List<ParseException> namedsToExceptions(java.util.List<Named> source);
@ -36,4 +36,12 @@ public interface SourceTargetMapper {
java.util.Map<Date, Date> stringsToDates(java.util.Map<String, String> stringDates);
Target sourceToTarget(Source target);
class Value<T> {
private T value;
public Value(List list) {
}
}
}

View File

@ -11,4 +11,13 @@ package org.mapstruct.ap.test.java8stream.wildcard;
*/
public class Idea {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -11,4 +11,13 @@ package org.mapstruct.ap.test.java8stream.wildcard;
*/
public class Plan {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -8,14 +8,24 @@ package org.mapstruct.ap.test.missingignoredsource;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.factory.Mappers;
@Mapper(
unmappedTargetPolicy = ReportingPolicy.IGNORE,
unmappedSourcePolicy = ReportingPolicy.IGNORE)
public interface ErroneousSourceTargetMapper {
ErroneousSourceTargetMapper INSTANCE = Mappers.getMapper( ErroneousSourceTargetMapper.class );
@BeanMapping(ignoreUnmappedSourceProperties = "bar")
Object sourceToTarget(Object source);
Target map(Target source);
class Target {
private final String value;
public Target(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}

View File

@ -22,7 +22,7 @@ public class MissingIgnoredSourceTest {
diagnostics = {
@Diagnostic(type = ErroneousSourceTargetMapper.class,
kind = Kind.ERROR,
line = 20,
line = 18,
message = "Ignored unknown source property: \"bar\".")
}
)

View File

@ -7,10 +7,11 @@ package org.mapstruct.ap.test.selection.methodgenerics.objectfactory;
import org.mapstruct.Mapper;
import org.mapstruct.ObjectFactory;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.TargetType;
import org.mapstruct.factory.Mappers;
@Mapper
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface ObjectFactoryMapper {
ObjectFactoryMapper INSTANCE = Mappers.getMapper( ObjectFactoryMapper.class );
@ -44,6 +45,16 @@ public interface ObjectFactoryMapper {
}
abstract class Target {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
class TargetA extends Target {

View File

@ -7,4 +7,13 @@ package org.mapstruct.ap.test.subclassmapping.fixture;
public abstract class AbstractParentSource {
private String parentValue;
public String getParentValue() {
return parentValue;
}
public void setParentValue(String parentValue) {
this.parentValue = parentValue;
}
}

View File

@ -7,4 +7,13 @@ package org.mapstruct.ap.test.subclassmapping.fixture;
public abstract class AbstractParentTarget {
private String parentValue;
public String getParentValue() {
return parentValue;
}
public void setParentValue(String parentValue) {
this.parentValue = parentValue;
}
}

View File

@ -7,4 +7,13 @@ package org.mapstruct.ap.test.subclassmapping.fixture;
public class ImplementedParentSource extends AbstractParentSource {
private String implementedParentValue;
public String getImplementedParentValue() {
return implementedParentValue;
}
public void setImplementedParentValue(String implementedParentValue) {
this.implementedParentValue = implementedParentValue;
}
}

View File

@ -7,4 +7,13 @@ package org.mapstruct.ap.test.subclassmapping.fixture;
public class ImplementedParentTarget extends AbstractParentTarget {
private String implementedParentValue;
public String getImplementedParentValue() {
return implementedParentValue;
}
public void setImplementedParentValue(String implementedParentValue) {
this.implementedParentValue = implementedParentValue;
}
}

View File

@ -6,6 +6,7 @@
package org.mapstruct.ap.test.versioninfo;
import org.mapstruct.Mapper;
import org.mapstruct.ap.test.WithProperties;
/**
* @author Andreas Gudian
@ -13,5 +14,5 @@ import org.mapstruct.Mapper;
*/
@Mapper
public interface SimpleMapper {
Object toObject(Object object);
WithProperties toObject(WithProperties object);
}

View File

@ -6,11 +6,12 @@
package org.mapstruct.ap.test.versioninfo;
import org.mapstruct.Mapper;
import org.mapstruct.ap.test.WithProperties;
/**
* @author Filip Hrisafov
*/
@Mapper(suppressTimestampInGenerated = true)
public interface SuppressTimestampViaMapper {
Object toObject(Object object);
WithProperties toObject(WithProperties object);
}

View File

@ -7,13 +7,14 @@ package org.mapstruct.ap.test.versioninfo;
import org.mapstruct.Mapper;
import org.mapstruct.MapperConfig;
import org.mapstruct.ap.test.WithProperties;
/**
* @author Filip Hrisafov
*/
@Mapper(config = SuppressTimestampViaMapperConfig.Config.class)
public interface SuppressTimestampViaMapperConfig {
Object toObject(Object object);
WithProperties toObject(WithProperties object);
@MapperConfig(suppressTimestampInGenerated = true)
interface Config {

View File

@ -6,6 +6,7 @@
package org.mapstruct.ap.test.versioninfo;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
import org.mapstruct.ap.testutil.WithClasses;
@ -18,7 +19,7 @@ import org.mapstruct.ap.testutil.runner.GeneratedSource;
*
*/
@IssueKey( "424" )
@WithClasses( SimpleMapper.class )
@WithClasses( { SimpleMapper.class, WithProperties.class } )
public class VersionInfoTest {
@RegisterExtension
final GeneratedSource generatedSource = new GeneratedSource();

View File

@ -58,6 +58,8 @@ public class SubclassAbstractMapperImpl implements SubclassAbstractMapper {
SubTarget subTarget = new SubTarget();
subTarget.setParentValue( subSource.getParentValue() );
subTarget.setImplementedParentValue( subSource.getImplementedParentValue() );
subTarget.setValue( subSource.getValue() );
return subTarget;
@ -74,6 +76,9 @@ public class SubclassAbstractMapperImpl implements SubclassAbstractMapper {
SubTargetOther subTargetOther = new SubTargetOther( finalValue );
subTargetOther.setParentValue( subSourceOther.getParentValue() );
subTargetOther.setImplementedParentValue( subSourceOther.getImplementedParentValue() );
return subTargetOther;
}
@ -88,6 +93,9 @@ public class SubclassAbstractMapperImpl implements SubclassAbstractMapper {
SubSourceSeparate subSourceSeparate = new SubSourceSeparate( separateValue );
subSourceSeparate.setParentValue( subTargetSeparate.getParentValue() );
subSourceSeparate.setImplementedParentValue( subTargetSeparate.getImplementedParentValue() );
return subSourceSeparate;
}
@ -102,6 +110,9 @@ public class SubclassAbstractMapperImpl implements SubclassAbstractMapper {
SubSourceOverride subSourceOverride = new SubSourceOverride( finalValue );
subSourceOverride.setParentValue( subTargetOther.getParentValue() );
subSourceOverride.setImplementedParentValue( subTargetOther.getImplementedParentValue() );
return subSourceOverride;
}
@ -112,6 +123,8 @@ public class SubclassAbstractMapperImpl implements SubclassAbstractMapper {
SubSource subSource = new SubSource();
subSource.setParentValue( subTarget.getParentValue() );
subSource.setImplementedParentValue( subTarget.getImplementedParentValue() );
subSource.setValue( subTarget.getValue() );
return subSource;

View File

@ -29,6 +29,9 @@ public class SubclassImplementedMapperImpl implements SubclassImplementedMapper
else {
ImplementedParentTarget implementedParentTarget = new ImplementedParentTarget();
implementedParentTarget.setParentValue( item.getParentValue() );
implementedParentTarget.setImplementedParentValue( item.getImplementedParentValue() );
return implementedParentTarget;
}
}
@ -40,6 +43,8 @@ public class SubclassImplementedMapperImpl implements SubclassImplementedMapper
SubTarget subTarget = new SubTarget();
subTarget.setParentValue( subSource.getParentValue() );
subTarget.setImplementedParentValue( subSource.getImplementedParentValue() );
subTarget.setValue( subSource.getValue() );
return subTarget;
@ -56,6 +61,9 @@ public class SubclassImplementedMapperImpl implements SubclassImplementedMapper
SubTargetOther subTargetOther = new SubTargetOther( finalValue );
subTargetOther.setParentValue( subSourceOther.getParentValue() );
subTargetOther.setImplementedParentValue( subSourceOther.getImplementedParentValue() );
return subTargetOther;
}
}

View File

@ -38,6 +38,8 @@ public class SubclassInterfaceMapperImpl implements SubclassInterfaceMapper {
SubTarget subTarget = new SubTarget();
subTarget.setParentValue( subSource.getParentValue() );
subTarget.setImplementedParentValue( subSource.getImplementedParentValue() );
subTarget.setValue( subSource.getValue() );
return subTarget;
@ -54,6 +56,9 @@ public class SubclassInterfaceMapperImpl implements SubclassInterfaceMapper {
SubTargetOther subTargetOther = new SubTargetOther( finalValue );
subTargetOther.setParentValue( subSourceOther.getParentValue() );
subTargetOther.setImplementedParentValue( subSourceOther.getImplementedParentValue() );
return subTargetOther;
}
}