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 )
|
||||
|
||||
Type.ResolvedPair resolved = mthdParType.resolveParameterToType( matchingType, aCandidateMethodType );
|
||||
if ( resolved == null ) {
|
||||
// cannot find a candidate type, but should have since the typeFromCandidateMethod had parameters
|
||||
// to be resolved
|
||||
return !hasGenericTypeParameters( aCandidateMethodType );
|
||||
if ( resolved.getMatch() == null ) {
|
||||
// we should be dealing with something containing a type parameter at this point. This is
|
||||
// covered with the checks above. Therefore resolved itself cannot be null.
|
||||
// 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
|
||||
@ -270,13 +272,10 @@ public class MethodMatcher {
|
||||
// it might be already set, but we just checked if its an equivalent type
|
||||
if ( typeVarCandidate.match == null ) {
|
||||
typeVarCandidate.match = resolved.getMatch();
|
||||
if ( typeVarCandidate.match == null) {
|
||||
return false;
|
||||
}
|
||||
typeVarCandidate.pairs.add( resolved );
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,22 @@ public class MultipleTypeVarTest {
|
||||
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
|
||||
@WithClasses( SourceTypeHasMultipleTypeVarBothGenericMapper.class )
|
||||
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