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)
|
||||
|
||||
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 ) ) ) {
|
||||
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