#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,20 +295,24 @@ public class MappingResolverImpl implements MappingResolver {
} }
// 2 step method, then: method(conversion(source)) // 2 step method, then: method(conversion(source))
assignment = ConversionMethod.getBestMatch( this, sourceType, targetType ); if ( allowConversion() ) {
if ( assignment != null ) { assignment = ConversionMethod.getBestMatch( this, sourceType, targetType );
usedSupportedMappings.addAll( supportingMethodCandidates ); if ( assignment != null ) {
return assignment; usedSupportedMappings.addAll( supportingMethodCandidates );
return assignment;
}
} }
// stop here when looking for update methods. // stop here when looking for update methods.
selectionCriteria.setPreferUpdateMapping( false ); selectionCriteria.setPreferUpdateMapping( false );
// 2 step method, finally: conversion(method(source)) // 2 step method, finally: conversion(method(source))
assignment = MethodConversion.getBestMatch( this, sourceType, targetType ); if ( allowConversion() ) {
if ( assignment != null ) { assignment = MethodConversion.getBestMatch( this, sourceType, targetType );
usedSupportedMappings.addAll( supportingMethodCandidates ); if ( assignment != null ) {
return assignment; usedSupportedMappings.addAll( supportingMethodCandidates );
return assignment;
}
} }
} }
@ -763,22 +767,26 @@ public class MappingResolverImpl implements MappingResolver {
return mmAttempt.result; return mmAttempt.result;
} }
} }
MethodMethod<Method, BuiltInMethod> mbAttempt = if ( att.allowConversion() ) {
new MethodMethod<>( att, att.methods, att.builtIns, att::toMethodRef, att::toBuildInRef ) MethodMethod<Method, BuiltInMethod> mbAttempt =
.getBestMatch( sourceType, targetType ); new MethodMethod<>( att, att.methods, att.builtIns, att::toMethodRef, att::toBuildInRef )
if ( mbAttempt.hasResult ) { .getBestMatch( sourceType, targetType );
return mbAttempt.result; if ( mbAttempt.hasResult ) {
return mbAttempt.result;
}
MethodMethod<BuiltInMethod, Method> bmAttempt =
new MethodMethod<>( att, att.builtIns, att.methods, att::toBuildInRef, att::toMethodRef )
.getBestMatch( sourceType, targetType );
if ( bmAttempt.hasResult ) {
return bmAttempt.result;
}
MethodMethod<BuiltInMethod, BuiltInMethod> bbAttempt =
new MethodMethod<>( att, att.builtIns, att.builtIns, att::toBuildInRef, att::toBuildInRef )
.getBestMatch( sourceType, targetType );
return bbAttempt.result;
} }
MethodMethod<BuiltInMethod, Method> bmAttempt =
new MethodMethod<>( att, att.builtIns, att.methods, att::toBuildInRef, att::toMethodRef ) return null;
.getBestMatch( sourceType, targetType );
if ( bmAttempt.hasResult ) {
return bmAttempt.result;
}
MethodMethod<BuiltInMethod, BuiltInMethod> bbAttempt =
new MethodMethod<>( att, att.builtIns, att.builtIns, att::toBuildInRef, att::toBuildInRef )
.getBestMatch( sourceType, targetType );
return bbAttempt.result;
} }
MethodMethod(ResolvingAttempt attempt, List<T1> xMethods, List<T2> yMethods, MethodMethod(ResolvingAttempt attempt, List<T1> xMethods, List<T2> yMethods,

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() { 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() { private FridgeDTO createFridgeDTO() {
FridgeDTO fridgeDTO = new FridgeDTO(); FridgeDTO fridgeDTO = new FridgeDTO();
ShelveDTO shelveDTO = new ShelveDTO(); 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 {
}