#3186 Do not use conversions in 2-step mapping when they are disabled

This commit is contained in:
Filip Hrisafov 2023-04-15 23:18:32 +02:00
parent d10d48ccff
commit c6ea69eaf9
8 changed files with 380 additions and 23 deletions

View File

@ -295,22 +295,26 @@ public class MappingResolverImpl implements MappingResolver {
}
// 2 step method, then: method(conversion(source))
if ( allowConversion() ) {
assignment = ConversionMethod.getBestMatch( this, sourceType, targetType );
if ( assignment != null ) {
usedSupportedMappings.addAll( supportingMethodCandidates );
return assignment;
}
}
// stop here when looking for update methods.
selectionCriteria.setPreferUpdateMapping( false );
// 2 step method, finally: conversion(method(source))
if ( allowConversion() ) {
assignment = MethodConversion.getBestMatch( this, sourceType, targetType );
if ( assignment != null ) {
usedSupportedMappings.addAll( supportingMethodCandidates );
return assignment;
}
}
}
if ( hasQualfiers() ) {
if ((sourceType.isCollectionType() || sourceType.isArrayType()) && targetType.isIterableType()) {
@ -763,6 +767,7 @@ public class MappingResolverImpl implements MappingResolver {
return mmAttempt.result;
}
}
if ( att.allowConversion() ) {
MethodMethod<Method, BuiltInMethod> mbAttempt =
new MethodMethod<>( att, att.methods, att.builtIns, att::toMethodRef, att::toBuildInRef )
.getBestMatch( sourceType, targetType );
@ -781,6 +786,9 @@ public class MappingResolverImpl implements MappingResolver {
return bbAttempt.result;
}
return null;
}
MethodMethod(ResolvingAttempt attempt, List<T1> xMethods, List<T2> yMethods,
Function<SelectedMethod<T1>, Assignment> xCreate,
Function<SelectedMethod<T2>, Assignment> yCreate) {

View File

@ -0,0 +1,44 @@
/*
* 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.mappingcontrol;
import java.time.ZonedDateTime;
import java.util.Date;
import org.mapstruct.Mapper;
/**
* @author Filip Hrisafov
*/
@Mapper(mappingControl = NoConversion.class)
public interface ErroneousBuiltInAndBuiltInMapper {
Target map(Source source);
class Source {
private final ZonedDateTime time;
public Source(ZonedDateTime time) {
this.time = time;
}
public ZonedDateTime getTime() {
return time;
}
}
class Target {
private final Date time;
public Target(Date time) {
this.time = time;
}
public Date getTime() {
return time;
}
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.mappingcontrol;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Calendar;
import org.mapstruct.Mapper;
/**
* @author Filip Hrisafov
*/
@Mapper(mappingControl = NoConversion.class)
public interface ErroneousBuiltInAndMethodMapper {
Target map(Source source);
default ZonedDateTime fromInt(int time) {
return ZonedDateTime.ofInstant( Instant.ofEpochMilli( time ), ZoneOffset.UTC );
}
class Source {
private final int time;
public Source(int time) {
this.time = time;
}
public int getTime() {
return time;
}
}
class Target {
private Calendar time;
public Target(Calendar time) {
this.time = time;
}
public Calendar getTime() {
return time;
}
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.mappingcontrol;
import java.time.Instant;
import java.util.Date;
import org.mapstruct.Mapper;
/**
* @author Filip Hrisafov
*/
@Mapper(mappingControl = NoConversion.class)
public interface ErroneousConversionAndMethodMapper {
Target map(Source source);
default Instant fromDate(int time) {
return Instant.ofEpochMilli( time );
}
class Source {
private final int time;
public Source(int time) {
this.time = time;
}
public int getTime() {
return time;
}
}
class Target {
private Date time;
public Target(Date time) {
this.time = time;
}
public Date getTime() {
return time;
}
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.mappingcontrol;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import org.mapstruct.Mapper;
/**
* @author Filip Hrisafov
*/
@Mapper(mappingControl = NoConversion.class)
public interface ErroneousMethodAndBuiltInMapper {
Target map(Source source);
default Date fromCalendar(Calendar calendar) {
return calendar != null ? calendar.getTime() : null;
}
class Source {
private final ZonedDateTime time;
public Source(ZonedDateTime time) {
this.time = time;
}
public ZonedDateTime getTime() {
return time;
}
}
class Target {
private final Date time;
public Target(Date time) {
this.time = time;
}
public Date getTime() {
return time;
}
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.mappingcontrol;
import java.time.Instant;
import java.util.Date;
import org.mapstruct.Mapper;
/**
* @author Filip Hrisafov
*/
@Mapper(mappingControl = NoConversion.class)
public interface ErroneousMethodAndConversionMapper {
Target map(Source source);
default long fromInstant(Instant value) {
return value != null ? value.getEpochSecond() : null;
}
class Source {
private final Date time;
public Source(Date time) {
this.time = time;
}
public Date getTime() {
return time;
}
}
class Target {
private long time;
public Target(long time) {
this.time = time;
}
public long getTime() {
return time;
}
}
}

View File

@ -240,6 +240,96 @@ public class MappingControlTest {
public void complexSelectionNotAllowedWithConfig() {
}
@ProcessorTest
@IssueKey("3186")
@WithClasses({
ErroneousMethodAndBuiltInMapper.class,
NoConversion.class
})
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousMethodAndBuiltInMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 20,
message = "Can't map property \"ZonedDateTime time\" to \"Date time\". " +
"Consider to declare/implement a mapping method: \"Date map(ZonedDateTime value)\"."
)
})
public void conversionSelectionNotAllowedInTwoStepMethodBuiltIdConversion() {
}
@ProcessorTest
@IssueKey("3186")
@WithClasses({
ErroneousBuiltInAndBuiltInMapper.class,
NoConversion.class
})
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousBuiltInAndBuiltInMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 19,
message = "Can't map property \"ZonedDateTime time\" to \"Date time\". " +
"Consider to declare/implement a mapping method: \"Date map(ZonedDateTime value)\"."
)
})
public void conversionSelectionNotAllowedInTwoStepBuiltInBuiltInConversion() {
}
@ProcessorTest
@IssueKey("3186")
@WithClasses({
ErroneousBuiltInAndMethodMapper.class,
NoConversion.class
})
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousBuiltInAndMethodMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 21,
message = "Can't map property \"int time\" to \"Calendar time\". " +
"Consider to declare/implement a mapping method: \"Calendar map(int value)\"."
)
})
public void conversionSelectionNotAllowedInTwoStepBuiltInMethodConversion() {
}
@ProcessorTest
@IssueKey("3186")
@WithClasses({
ErroneousMethodAndConversionMapper.class,
NoConversion.class
})
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousMethodAndConversionMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 19,
message = "Can't map property \"Date time\" to \"long time\". " +
"Consider to declare/implement a mapping method: \"long map(Date value)\"."
)
})
public void conversionSelectionNotAllowedInTwoStepMethodConversionConversion() {
}
@ProcessorTest
@IssueKey("3186")
@WithClasses({
ErroneousConversionAndMethodMapper.class,
NoConversion.class
})
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousConversionAndMethodMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 19,
message = "Can't map property \"int time\" to \"Date time\". " +
"Consider to declare/implement a mapping method: \"Date map(int value)\"."
)
})
public void conversionSelectionNotAllowedInTwoStepConversionMethodConversion() {
}
private FridgeDTO createFridgeDTO() {
FridgeDTO fridgeDTO = new FridgeDTO();
ShelveDTO shelveDTO = new ShelveDTO();

View File

@ -0,0 +1,20 @@
/*
* 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.mappingcontrol;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.mapstruct.control.MappingControl;
import org.mapstruct.util.Experimental;
@Retention(RetentionPolicy.CLASS)
@Experimental
@MappingControl( MappingControl.Use.DIRECT )
@MappingControl( MappingControl.Use.MAPPING_METHOD )
@MappingControl( MappingControl.Use.COMPLEX_MAPPING )
public @interface NoConversion {
}