#2677 Use type without bounds when looking for read / presence accessor in a SourceReference

This commit is contained in:
Filip Hrisafov 2022-01-30 20:49:05 +01:00 committed by GitHub
parent 12070186a4
commit 37835a5607
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 213 additions and 3 deletions

View File

@ -311,11 +311,12 @@ public class SourceReference extends AbstractReference {
Type newType = type;
for ( int i = 0; i < entryNames.length; i++ ) {
boolean matchFound = false;
ReadAccessor readAccessor = newType.getReadAccessor( entryNames[i] );
Type noBoundsType = newType.withoutBounds();
ReadAccessor readAccessor = noBoundsType.getReadAccessor( entryNames[i] );
if ( readAccessor != null ) {
PresenceCheckAccessor presenceChecker = newType.getPresenceChecker( entryNames[i] );
PresenceCheckAccessor presenceChecker = noBoundsType.getPresenceChecker( entryNames[i] );
newType = typeFactory.getReturnType(
(DeclaredType) newType.getTypeMirror(),
(DeclaredType) noBoundsType.getTypeMirror(),
readAccessor
);
sourceEntries.add( forSourceReference(

View File

@ -0,0 +1,117 @@
/*
* 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._2677;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* @author Filip Hrisafov
*/
@Mapper
public interface Issue2677Mapper {
Issue2677Mapper INSTANCE = Mappers.getMapper( Issue2677Mapper.class );
@Mapping(target = "id", source = "value.id")
Output map(Wrapper<? extends Parent> in);
@Mapping(target = ".", source = "value")
Output mapImplicitly(Wrapper<? extends Parent> in);
@Mapping(target = "id", source = "value.id")
Output mapFromParent(Wrapper<Parent> in);
@Mapping(target = "id", source = "value.id")
Output mapFromChild(Wrapper<Child> in);
@Mapping( target = "value", source = "wrapperValue")
Wrapper<String> mapToWrapper(String wrapperValue, Wrapper<? super Parent> wrapper);
@Mapping(target = "id", source = "value.id")
Output mapWithPresenceCheck(Wrapper<? extends ParentWithPresenceCheck> in);
class Wrapper<T> {
private final T value;
private final String status;
public Wrapper(T value, String status) {
this.value = value;
this.status = status;
}
public String getStatus() {
return status;
}
public T getValue() {
return value;
}
}
class Parent {
private final int id;
public Parent(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
class Child extends Parent {
private final String whatever;
public Child(int id, String whatever) {
super( id );
this.whatever = whatever;
}
public String getWhatever() {
return whatever;
}
}
class ParentWithPresenceCheck {
private final int id;
public ParentWithPresenceCheck(int id) {
this.id = id;
}
public int getId() {
return id;
}
public boolean hasId() {
return id > 10;
}
}
class Output {
private int id;
private String status;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
}

View File

@ -0,0 +1,92 @@
/*
* 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._2677;
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("2677")
@WithClasses({
Issue2677Mapper.class
})
class Issue2677Test {
@ProcessorTest
void shouldCorrectlyUseGenericsWithExtends() {
Issue2677Mapper.Parent parent = new Issue2677Mapper.Parent( 10 );
Issue2677Mapper.Child child = new Issue2677Mapper.Child( 15, "Test" );
Issue2677Mapper.Output output = Issue2677Mapper.INSTANCE.map( new Issue2677Mapper.Wrapper<>(
parent,
"extends"
) );
assertThat( output.getStatus() ).isEqualTo( "extends" );
assertThat( output.getId() ).isEqualTo( 10 );
output = Issue2677Mapper.INSTANCE.mapFromChild( new Issue2677Mapper.Wrapper<>(
child,
"child"
) );
assertThat( output.getStatus() ).isEqualTo( "child" );
assertThat( output.getId() ).isEqualTo( 15 );
output = Issue2677Mapper.INSTANCE.mapFromParent( new Issue2677Mapper.Wrapper<>(
parent,
"parent"
) );
assertThat( output.getStatus() ).isEqualTo( "parent" );
assertThat( output.getId() ).isEqualTo( 10 );
output = Issue2677Mapper.INSTANCE.mapImplicitly( new Issue2677Mapper.Wrapper<>(
child,
"implicit"
) );
assertThat( output.getStatus() ).isEqualTo( "implicit" );
assertThat( output.getId() ).isEqualTo( 15 );
Issue2677Mapper.Wrapper<String> result = Issue2677Mapper.INSTANCE.mapToWrapper(
"test",
new Issue2677Mapper.Wrapper<>(
child,
"super"
)
);
assertThat( result.getStatus() ).isEqualTo( "super" );
assertThat( result.getValue() ).isEqualTo( "test" );
output = Issue2677Mapper.INSTANCE.mapWithPresenceCheck(
new Issue2677Mapper.Wrapper<>(
new Issue2677Mapper.ParentWithPresenceCheck( 8 ),
"presenceCheck"
)
);
assertThat( output.getStatus() ).isEqualTo( "presenceCheck" );
assertThat( output.getId() ).isEqualTo( 0 );
output = Issue2677Mapper.INSTANCE.mapWithPresenceCheck(
new Issue2677Mapper.Wrapper<>(
new Issue2677Mapper.ParentWithPresenceCheck( 15 ),
"presenceCheck"
)
);
assertThat( output.getStatus() ).isEqualTo( "presenceCheck" );
assertThat( output.getId() ).isEqualTo( 15 );
}
}