mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
In the MethodMatcher we need to do a special check when the target type is primitive. The reason for that is that a Long is assignable to a primitive double. However, doing that means that information can be lost and thus we should not pick such methods. When the target type is primitive, then a method will be matched if and only if boxed equivalent of the target type is assignable to the boxed equivalent of the candidate return type
This commit is contained in:
parent
b1eda5a04e
commit
73f70b1564
@ -82,6 +82,17 @@ public class MethodMatcher {
|
|||||||
// (the relation target / target type, target type being a class)
|
// (the relation target / target type, target type being a class)
|
||||||
|
|
||||||
if ( !analyser.candidateReturnType.isVoid() ) {
|
if ( !analyser.candidateReturnType.isVoid() ) {
|
||||||
|
if ( targetType.isPrimitive() ) {
|
||||||
|
// If the target type is primitive
|
||||||
|
// then we are going to check if its boxed equivalent
|
||||||
|
// is assignable to the candidate return type
|
||||||
|
// This is done because primitives can be assigned from their own narrower counterparts
|
||||||
|
// directly without any casting.
|
||||||
|
// e.g. a Long is assignable to a primitive double
|
||||||
|
// However, in order not to lose information we are not going to allow this
|
||||||
|
return targetType.getBoxedEquivalent()
|
||||||
|
.isAssignableTo( analyser.candidateReturnType.getBoxedEquivalent() );
|
||||||
|
}
|
||||||
if ( !( analyser.candidateReturnType.isAssignableTo( targetType ) ) ) {
|
if ( !( analyser.candidateReturnType.isAssignableTo( targetType ) ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.bugs._2840;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface Issue2840Mapper {
|
||||||
|
|
||||||
|
Issue2840Mapper INSTANCE =
|
||||||
|
Mappers.getMapper( Issue2840Mapper.class );
|
||||||
|
|
||||||
|
Issue2840Mapper.Target map(Short shortValue, Integer intValue);
|
||||||
|
|
||||||
|
default int toInt(Number number) {
|
||||||
|
return number.intValue() + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
default short toShort(Number number) {
|
||||||
|
return (short) (number.shortValue() + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
|
||||||
|
private int intValue;
|
||||||
|
private short shortValue;
|
||||||
|
|
||||||
|
public int getIntValue() {
|
||||||
|
return intValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntValue(int intValue) {
|
||||||
|
this.intValue = intValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getShortValue() {
|
||||||
|
return shortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShortValue(short shortValue) {
|
||||||
|
this.shortValue = shortValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* 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.bugs._2840;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@IssueKey("2840")
|
||||||
|
@WithClasses({
|
||||||
|
Issue2840Mapper.class,
|
||||||
|
})
|
||||||
|
class Issue2840Test {
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
void shouldUseMethodWithMostSpecificReturnType() {
|
||||||
|
Issue2840Mapper.Target target = Issue2840Mapper.INSTANCE.map( (short) 10, 50 );
|
||||||
|
|
||||||
|
assertThat( target.getShortValue() ).isEqualTo( (short) 20 );
|
||||||
|
assertThat( target.getIntValue() ).isEqualTo( 55 );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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.bugs._2913;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface Issue2913Mapper {
|
||||||
|
|
||||||
|
Issue2913Mapper INSTANCE = Mappers.getMapper( Issue2913Mapper.class );
|
||||||
|
|
||||||
|
@Mapping(target = "doublePrimitiveValue", source = "rounding")
|
||||||
|
@Mapping(target = "doubleValue", source = "rounding")
|
||||||
|
@Mapping(target = "longPrimitiveValue", source = "rounding")
|
||||||
|
@Mapping(target = "longValue", source = "rounding")
|
||||||
|
Target map(Source source);
|
||||||
|
|
||||||
|
default Long mapAmount(BigDecimal amount) {
|
||||||
|
return amount != null ? amount.movePointRight( 2 ).longValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
|
||||||
|
private double doublePrimitiveValue;
|
||||||
|
private Double doubleValue;
|
||||||
|
private long longPrimitiveValue;
|
||||||
|
private Long longValue;
|
||||||
|
|
||||||
|
public double getDoublePrimitiveValue() {
|
||||||
|
return doublePrimitiveValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoublePrimitiveValue(double doublePrimitiveValue) {
|
||||||
|
this.doublePrimitiveValue = doublePrimitiveValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getDoubleValue() {
|
||||||
|
return doubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoubleValue(Double doubleValue) {
|
||||||
|
this.doubleValue = doubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLongPrimitiveValue() {
|
||||||
|
return longPrimitiveValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongPrimitiveValue(long longPrimitiveValue) {
|
||||||
|
this.longPrimitiveValue = longPrimitiveValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getLongValue() {
|
||||||
|
return longValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongValue(Long longValue) {
|
||||||
|
this.longValue = longValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
|
||||||
|
private final BigDecimal rounding;
|
||||||
|
|
||||||
|
public Source(BigDecimal rounding) {
|
||||||
|
this.rounding = rounding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getRounding() {
|
||||||
|
return rounding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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.bugs._2913;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@IssueKey("2913")
|
||||||
|
@WithClasses({
|
||||||
|
Issue2913Mapper.class,
|
||||||
|
})
|
||||||
|
class Issue2913Test {
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
void shouldNotWidenWithUserDefinedMethods() {
|
||||||
|
Issue2913Mapper.Source source = new Issue2913Mapper.Source( BigDecimal.valueOf( 10.543 ) );
|
||||||
|
Issue2913Mapper.Target target = Issue2913Mapper.INSTANCE.map( source );
|
||||||
|
|
||||||
|
assertThat( target.getDoubleValue() ).isEqualTo( 10.543 );
|
||||||
|
assertThat( target.getDoublePrimitiveValue() ).isEqualTo( 10.543 );
|
||||||
|
assertThat( target.getLongValue() ).isEqualTo( 1054 );
|
||||||
|
assertThat( target.getLongPrimitiveValue() ).isEqualTo( 1054 );
|
||||||
|
}
|
||||||
|
}
|
@ -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.bugs._2921;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface Issue2921Mapper {
|
||||||
|
|
||||||
|
Issue2921Mapper INSTANCE = Mappers.getMapper( Issue2921Mapper.class );
|
||||||
|
|
||||||
|
Target map(Source source);
|
||||||
|
|
||||||
|
default Short toShort(Integer value) {
|
||||||
|
throw new UnsupportedOperationException( "toShort method should not be used" );
|
||||||
|
}
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
private final Integer value;
|
||||||
|
|
||||||
|
public Source(Integer value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
public Target(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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.bugs._2921;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@IssueKey("2921")
|
||||||
|
@WithClasses({
|
||||||
|
Issue2921Mapper.class,
|
||||||
|
})
|
||||||
|
class Issue2921Test {
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
void shouldNotUseIntegerToShortForMappingIntegerToInt() {
|
||||||
|
Issue2921Mapper.Target target = Issue2921Mapper.INSTANCE.map( new Issue2921Mapper.Source( 10 ) );
|
||||||
|
assertThat( target.getValue() ).isEqualTo( 10 );
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user