Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ private Assignment forgeIterableMapping(Type sourceType, Type targetType, Source

private Assignment forgeWithElementMapping(Type sourceType, Type targetType, SourceRHS source,
ContainerMappingMethodBuilder<?, ? extends ContainerMappingMethod> builder) {

sourceType = sourceType.replaceSuperBoundWith( targetType, ctx.getTypeFactory().getType( Object.class ) );
targetType = targetType.withoutBounds();
ForgedMethod methodRef = prepareForgedMethod( sourceType, targetType, source, "[]" );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ public boolean isStreamType() {
/**
* A wild card type can have two types of bounds (mutual exclusive): extends and super.
*
* @return true if the bound has a wild card super bound (e.g. ? super Number)
* @return true if the bound has a wild card super bound (e.g. {@code ? super Number})
*/
public boolean hasSuperBound() {
boolean result = false;
Expand All @@ -465,7 +465,7 @@ public boolean hasSuperBound() {
/**
* A wild card type can have two types of bounds (mutual exclusive): extends and super.
*
* @return true if the bound has a wild card super bound (e.g. ? extends Number)
* @return true if the bound has a wild card extends bound (e.g. {@code ? extends Number})
*/
public boolean hasExtendsBound() {
boolean result = false;
Expand Down Expand Up @@ -618,6 +618,66 @@ public Type erasure() {
);
}

public Type replaceSuperBoundWith( Type compare, Type replacement ) {
if ( typeParameters.isEmpty() ) {
return this;
}
List<Type> targetTypeParameters = compare.getTypeParameters();
if ( targetTypeParameters.size() != typeParameters.size() ) {
return this;
}
TypeMirror replacementMirror = replacement.getTypeMirror();
boolean noChange = true;
List<Type> bounds = new ArrayList<>( typeParameters.size() );
TypeMirror[] mirrors = new TypeMirror[ typeParameters.size() ];
for ( int x = 0; x < typeParameters.size(); x++ ) {
Type type = typeParameters.get( x );
if ( !type.hasSuperBound() || type.isRawAssignableTo( targetTypeParameters.get( x ) ) ) {
bounds.add( type );
mirrors[ x ] = type.getTypeMirror();
}
else {
bounds.add( replacement );
mirrors[x] = replacementMirror;
noChange = false;
}
}

if ( noChange ) {
return this;
}

DeclaredType declaredType = typeUtils.getDeclaredType(
typeElement,
mirrors
);
return new Type(
typeUtils,
elementUtils,
typeFactory,
accessorNaming,
declaredType,
(TypeElement) declaredType.asElement(),
bounds,
implementationType,
componentType,
packageName,
name,
qualifiedName,
isInterface,
isEnumType,
isIterableType,
isCollectionType,
isMapType,
isStream,
toBeImportedTypes,
notToBeImportedTypes,
isToBeImported,
isLiteral,
loggingVerbose
);
}

public Type withoutBounds() {
if ( typeParameters.isEmpty() ) {
return this;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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.generics.wildcard;

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface CollectionExtendToSuperMapper {

CollectionExtendToSuperMapper INSTANCE = Mappers.getMapper( CollectionExtendToSuperMapper.class );

CollectionSuperTypes toSuper(CollectionExtendTypes extendTypes);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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.generics.wildcard;

import java.util.Collection;

public class CollectionExtendTypes {

private Collection<? extends SimpleObject> simpleObjectsCollection;

public Collection<? extends SimpleObject> getSimpleObjectsCollection() {
return simpleObjectsCollection;
}

public void setSimpleObjectsCollection(Collection<? extends SimpleObject> simpleObjectsCollection) {
this.simpleObjectsCollection = simpleObjectsCollection;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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.generics.wildcard;

import java.util.Collection;

public class CollectionSuperTypes {

private Collection<? super SimpleObject> simpleObjectsCollection;

public Collection<? super SimpleObject> getSimpleObjectsCollection() {
return simpleObjectsCollection;
}

public void setSimpleObjectsCollection(Collection<? super SimpleObject> simpleObjectsCollection) {
this.simpleObjectsCollection = simpleObjectsCollection;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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.generics.wildcard;

import java.util.ArrayList;
import java.util.List;

import org.mapstruct.ap.testutil.ProcessorTest;
import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;

import static org.assertj.core.api.Assertions.assertThat;

@WithClasses(SimpleObject.class)
public class DistinguishBetweenSuperAndExtendTest {

@ProcessorTest
@WithClasses({
CollectionExtendTypes.class,
CollectionSuperTypes.class,
ErroneousCollectionSuperToExtendMapper.class
})
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousCollectionSuperToExtendMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 13,
message = "Can't map property " +
"\"Collection<? super org.mapstruct.ap.test.generics.wildcard.SimpleObject> " +
"simpleObjectsCollection\" to " +
"\"Collection<? extends org.mapstruct.ap.test.generics.wildcard.SimpleObject> " +
"simpleObjectsCollection\". Consider to declare/implement a mapping method: " +
"\"Collection<? extends org.mapstruct.ap.test.generics.wildcard.SimpleObject> " +
"map(Collection<? super org.mapstruct.ap.test.generics.wildcard.SimpleObject>" +
" value)\".")
})
public void shouldFailOnSuperToExtendMappingForCollection() {

}

@ProcessorTest
@WithClasses(ErroneousStreamSuperToExtendMapper.class)
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousStreamSuperToExtendMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 15,
message = "Can't map property " +
"\"Stream<? super org.mapstruct.ap.test.generics.wildcard.SimpleObject> " +
"simpleObjectsStream\" to " +
"\"Stream<? extends org.mapstruct.ap.test.generics.wildcard.SimpleObject> " +
"simpleObjectsStream\". Consider to declare/implement a mapping method: " +
"\"Stream<? extends org.mapstruct.ap.test.generics.wildcard.SimpleObject> " +
"map(Stream<? super org.mapstruct.ap.test.generics.wildcard.SimpleObject>" +
" value)\".")
})
public void shouldFailOnSuperToExtendMappingForStream() {

}

@ProcessorTest
@WithClasses({
CollectionExtendTypes.class,
CollectionSuperTypes.class,
CollectionExtendToSuperMapper.class
})
public void shouldMapExtendBoundToSuperBound() {
CollectionExtendTypes collectionExtendTypes = new CollectionExtendTypes();
List<SimpleObject> simpleObjects = new ArrayList<>();
simpleObjects.add( new SimpleObject() );
collectionExtendTypes.setSimpleObjectsCollection( simpleObjects );
CollectionSuperTypes result = CollectionExtendToSuperMapper.INSTANCE.toSuper( collectionExtendTypes );
assertThat( result ).isNotNull();
assertThat( result.getSimpleObjectsCollection() ).hasSize( 1 );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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.generics.wildcard;

import org.mapstruct.Mapper;

@Mapper
public interface ErroneousCollectionSuperToExtendMapper {

CollectionExtendTypes map(CollectionSuperTypes types);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.generics.wildcard;

import org.mapstruct.Mapper;

import java.util.stream.Stream;

@Mapper
public interface ErroneousStreamSuperToExtendMapper {

ExtendStreamTypes map(SuperStreamTypes types);

class ExtendStreamTypes {
private Stream<? extends SimpleObject> simpleObjectsStream;

public Stream<? extends SimpleObject> getSimpleObjectsStream() {
return simpleObjectsStream;
}

public void setSimpleObjectsStream(Stream<? extends SimpleObject> simpleObjectsStream) {
this.simpleObjectsStream = simpleObjectsStream;
}
}

class SuperStreamTypes {

private Stream<? super SimpleObject> simpleObjectsStream;

public Stream<? super SimpleObject> getSimpleObjectsStream() {
return simpleObjectsStream;
}

public void setSimpleObjectsStream(Stream<? super SimpleObject> simpleObjectsStream) {
this.simpleObjectsStream = simpleObjectsStream;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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.generics.wildcard;

public class SimpleObject {
}
Loading