mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
parent
55c62ab43f
commit
7f38efad4d
@ -248,10 +248,12 @@ public class MethodMatcher {
|
|||||||
// e.g. <T> String method( List<? extends T> in )
|
// e.g. <T> String method( List<? extends T> in )
|
||||||
|
|
||||||
Type.ResolvedPair resolved = mthdParType.resolveParameterToType( matchingType, aCandidateMethodType );
|
Type.ResolvedPair resolved = mthdParType.resolveParameterToType( matchingType, aCandidateMethodType );
|
||||||
if ( resolved == null ) {
|
if ( resolved.getMatch() == null ) {
|
||||||
// cannot find a candidate type, but should have since the typeFromCandidateMethod had parameters
|
// we should be dealing with something containing a type parameter at this point. This is
|
||||||
// to be resolved
|
// covered with the checks above. Therefore resolved itself cannot be null.
|
||||||
return !hasGenericTypeParameters( aCandidateMethodType );
|
// If there is no match here, continue with the next candidate, perhaps there will a match with
|
||||||
|
// the next method type parameter
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolved something at this point, a candidate can be fetched or created
|
// resolved something at this point, a candidate can be fetched or created
|
||||||
@ -270,13 +272,10 @@ public class MethodMatcher {
|
|||||||
// it might be already set, but we just checked if its an equivalent type
|
// it might be already set, but we just checked if its an equivalent type
|
||||||
if ( typeVarCandidate.match == null ) {
|
if ( typeVarCandidate.match == null ) {
|
||||||
typeVarCandidate.match = resolved.getMatch();
|
typeVarCandidate.match = resolved.getMatch();
|
||||||
if ( typeVarCandidate.match == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
typeVarCandidate.pairs.add( resolved );
|
typeVarCandidate.pairs.add( resolved );
|
||||||
}
|
}
|
||||||
else if ( !areEquivalent( resolved.getMatch(), typeVarCandidate.match ) ) {
|
else if ( !areEquivalent( resolved.getMatch(), typeVarCandidate.match ) ) {
|
||||||
// type has been resolved twice, but with a different candidate (conflict)
|
// type has been resolved twice, but with a different candidate (conflict). Stop
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,22 @@ public class MultipleTypeVarTest {
|
|||||||
assertThat( target.getProp() ).containsExactly( entry( "test", 5L ) );
|
assertThat( target.getProp() ).containsExactly( entry( "test", 5L ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses( ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.class )
|
||||||
|
public void testGenericReturnTypeVarBothGenericArgumentsFlipped() {
|
||||||
|
|
||||||
|
ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.Pair pair
|
||||||
|
= new ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.Pair( "test", 5L );
|
||||||
|
ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.Source src =
|
||||||
|
new ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.Source( pair );
|
||||||
|
ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.Target target =
|
||||||
|
ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.INSTANCE.toTarget( src );
|
||||||
|
|
||||||
|
assertThat( target ).isNotNull();
|
||||||
|
assertThat( target.getProp() ).isNotNull();
|
||||||
|
assertThat( target.getProp() ).containsExactly( entry( "test", 5L ) );
|
||||||
|
}
|
||||||
|
|
||||||
@ProcessorTest
|
@ProcessorTest
|
||||||
@WithClasses( SourceTypeHasMultipleTypeVarBothGenericMapper.class )
|
@WithClasses( SourceTypeHasMultipleTypeVarBothGenericMapper.class )
|
||||||
public void testGenericSourceTypeVarBothGeneric() {
|
public void testGenericSourceTypeVarBothGeneric() {
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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.selection.methodgenerics.multiple;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper {
|
||||||
|
|
||||||
|
ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper INSTANCE =
|
||||||
|
Mappers.getMapper( ReturnTypeHasMultipleTypeVarBothArgumentsFlippedGenericMapper.class );
|
||||||
|
|
||||||
|
Target toTarget(Source source);
|
||||||
|
|
||||||
|
default <U, T> HashMap<T, U> toMap( Pair<T, U> entry) {
|
||||||
|
HashMap<T, U> result = new HashMap<>( );
|
||||||
|
result.put( entry.first, entry.second );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
|
||||||
|
private Pair<String, Long> prop;
|
||||||
|
|
||||||
|
public Source(Pair<String, Long> prop) {
|
||||||
|
this.prop = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<String, Long> getProp() {
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
|
||||||
|
private Map<String, Long> prop;
|
||||||
|
|
||||||
|
public Map<String, Long> getProp() {
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Target setProp(Map<String, Long> prop) {
|
||||||
|
this.prop = prop;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Pair<T, U> {
|
||||||
|
private final T first;
|
||||||
|
private final U second;
|
||||||
|
|
||||||
|
public Pair(T first, U second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getFirst() {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U getSecond() {
|
||||||
|
return second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 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.selection.methodgenerics.objectfactory;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.ObjectFactory;
|
||||||
|
import org.mapstruct.TargetType;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ObjectFactoryMapper {
|
||||||
|
|
||||||
|
ObjectFactoryMapper INSTANCE = Mappers.getMapper( ObjectFactoryMapper.class );
|
||||||
|
|
||||||
|
TargetA toTarget(SourceA source);
|
||||||
|
|
||||||
|
@ObjectFactory
|
||||||
|
default <T extends Target, S extends Source> T createTarget(S source, @TargetType Class<T> targetType) {
|
||||||
|
if ( source.isA() ) {
|
||||||
|
return (T) new TargetA();
|
||||||
|
}
|
||||||
|
return (T) new TargetB();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Source {
|
||||||
|
public abstract boolean isA();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceA extends Source {
|
||||||
|
@Override
|
||||||
|
public boolean isA() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceB extends Source {
|
||||||
|
@Override
|
||||||
|
public boolean isA() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Target {
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetA extends Target {
|
||||||
|
|
||||||
|
private TargetA() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetB extends Target {
|
||||||
|
|
||||||
|
private TargetB() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.selection.methodgenerics.objectfactory;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
|
||||||
|
public class ObjectFactoryTest {
|
||||||
|
|
||||||
|
@IssueKey( "2463" )
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses( ObjectFactoryMapper.class )
|
||||||
|
public void testSelectionOfFactoryMethod() {
|
||||||
|
|
||||||
|
ObjectFactoryMapper.SourceA source = new ObjectFactoryMapper.SourceA();
|
||||||
|
|
||||||
|
ObjectFactoryMapper.Target target = ObjectFactoryMapper.INSTANCE.toTarget( source );
|
||||||
|
|
||||||
|
assertThat( target ).isNotNull();
|
||||||
|
assertThat( target ).isInstanceOf( ObjectFactoryMapper.TargetA.class );
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user