mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#3036 Fix compile errors when intersection types are used in lifecycle methods
This commit is contained in:
parent
266c5fa41c
commit
3a325ea66b
@ -32,6 +32,10 @@ public final class FullFeatureCompilationExclusionCliEnhancer implements Process
|
|||||||
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/cdi/**/*.java" );
|
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/cdi/**/*.java" );
|
||||||
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/jakarta_cdi/**/*.java" );
|
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/jakarta_cdi/**/*.java" );
|
||||||
additionalExcludes.add( "org/mapstruct/ap/test/annotatewith/deprecated/jdk11/*.java" );
|
additionalExcludes.add( "org/mapstruct/ap/test/annotatewith/deprecated/jdk11/*.java" );
|
||||||
|
if ( processorType == ProcessorTest.ProcessorType.ECLIPSE_JDT ) {
|
||||||
|
additionalExcludes.add(
|
||||||
|
"org/mapstruct/ap/test/selection/methodgenerics/wildcards/LifecycleIntersectionMapper.java" );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case JAVA_9:
|
case JAVA_9:
|
||||||
// TODO find out why this fails:
|
// TODO find out why this fails:
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<additionalExclude3>x</additionalExclude3>
|
<additionalExclude3>x</additionalExclude3>
|
||||||
<additionalExclude4>x</additionalExclude4>
|
<additionalExclude4>x</additionalExclude4>
|
||||||
<additionalExclude5>x</additionalExclude5>
|
<additionalExclude5>x</additionalExclude5>
|
||||||
|
<additionalExclude6>x</additionalExclude6>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -28,6 +28,7 @@ import javax.lang.model.element.TypeElement;
|
|||||||
import javax.lang.model.element.VariableElement;
|
import javax.lang.model.element.VariableElement;
|
||||||
import javax.lang.model.type.ArrayType;
|
import javax.lang.model.type.ArrayType;
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
|
import javax.lang.model.type.IntersectionType;
|
||||||
import javax.lang.model.type.PrimitiveType;
|
import javax.lang.model.type.PrimitiveType;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
@ -114,6 +115,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
private List<Accessor> alternativeTargetAccessors = null;
|
private List<Accessor> alternativeTargetAccessors = null;
|
||||||
|
|
||||||
private Type boundingBase = null;
|
private Type boundingBase = null;
|
||||||
|
private List<Type> boundTypes = null;
|
||||||
|
|
||||||
private Type boxedEquivalent = null;
|
private Type boxedEquivalent = null;
|
||||||
|
|
||||||
@ -354,6 +356,10 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
return (typeMirror.getKind() == TypeKind.TYPEVAR);
|
return (typeMirror.getKind() == TypeKind.TYPEVAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isIntersection() {
|
||||||
|
return typeMirror.getKind() == TypeKind.INTERSECTION;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isJavaLangType() {
|
public boolean isJavaLangType() {
|
||||||
return packageName != null && packageName.startsWith( "java." );
|
return packageName != null && packageName.startsWith( "java." );
|
||||||
}
|
}
|
||||||
@ -1264,6 +1270,29 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
return boundingBase;
|
return boundingBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Type> getTypeBounds() {
|
||||||
|
if ( this.boundTypes != null ) {
|
||||||
|
return boundTypes;
|
||||||
|
}
|
||||||
|
Type bound = getTypeBound();
|
||||||
|
if ( bound == null ) {
|
||||||
|
this.boundTypes = Collections.emptyList();
|
||||||
|
}
|
||||||
|
else if ( !bound.isIntersection() ) {
|
||||||
|
this.boundTypes = Collections.singletonList( bound );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
List<? extends TypeMirror> bounds = ( (IntersectionType) bound.typeMirror ).getBounds();
|
||||||
|
this.boundTypes = new ArrayList<>( bounds.size() );
|
||||||
|
for ( TypeMirror mirror : bounds ) {
|
||||||
|
boundTypes.add( typeFactory.getType( mirror ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.boundTypes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasAccessibleConstructor() {
|
public boolean hasAccessibleConstructor() {
|
||||||
if ( hasAccessibleConstructor == null ) {
|
if ( hasAccessibleConstructor == null ) {
|
||||||
hasAccessibleConstructor = false;
|
hasAccessibleConstructor = false;
|
||||||
|
@ -325,8 +325,7 @@ public class MethodMatcher {
|
|||||||
*/
|
*/
|
||||||
private boolean candidatesWithinBounds(Map<Type, TypeVarCandidate> methodParCandidates ) {
|
private boolean candidatesWithinBounds(Map<Type, TypeVarCandidate> methodParCandidates ) {
|
||||||
for ( Map.Entry<Type, TypeVarCandidate> entry : methodParCandidates.entrySet() ) {
|
for ( Map.Entry<Type, TypeVarCandidate> entry : methodParCandidates.entrySet() ) {
|
||||||
Type bound = entry.getKey().getTypeBound();
|
for ( Type bound : entry.getKey().getTypeBounds() ) {
|
||||||
if ( bound != null ) {
|
|
||||||
for ( Type.ResolvedPair pair : entry.getValue().pairs ) {
|
for ( Type.ResolvedPair pair : entry.getValue().pairs ) {
|
||||||
if ( entry.getKey().hasUpperBound() ) {
|
if ( entry.getKey().hasUpperBound() ) {
|
||||||
if ( !pair.getMatch().asRawType().isAssignableTo( bound.asRawType() ) ) {
|
if ( !pair.getMatch().asRawType().isAssignableTo( bound.asRawType() ) ) {
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* 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.wildcards;
|
||||||
|
|
||||||
|
import org.mapstruct.AfterMapping;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingTarget;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface LifecycleIntersectionMapper {
|
||||||
|
|
||||||
|
LifecycleIntersectionMapper INSTANCE = Mappers.getMapper( LifecycleIntersectionMapper.class );
|
||||||
|
|
||||||
|
@Mapping(target = "realm", ignore = true)
|
||||||
|
RealmTarget mapRealm(String source);
|
||||||
|
|
||||||
|
@Mapping(target = "uniqueRealm", ignore = true)
|
||||||
|
UniqueRealmTarget mapUniqueRealm(String source);
|
||||||
|
|
||||||
|
@Mapping(target = "realm", ignore = true)
|
||||||
|
@Mapping(target = "uniqueRealm", ignore = true)
|
||||||
|
BothRealmsTarget mapBothRealms(String source);
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
default <T extends RealmObject & UniqueRealmObject> void afterMapping(String source, @MappingTarget T target) {
|
||||||
|
target.setRealm( "realm_" + source );
|
||||||
|
target.setUniqueRealm( "uniqueRealm_" + source );
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RealmObject {
|
||||||
|
void setRealm(String realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UniqueRealmObject {
|
||||||
|
void setUniqueRealm(String realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RealmTarget implements RealmObject {
|
||||||
|
|
||||||
|
protected String realm;
|
||||||
|
|
||||||
|
public String getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRealm(String realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UniqueRealmTarget implements UniqueRealmObject {
|
||||||
|
protected String uniqueRealm;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUniqueRealm(String uniqueRealm) {
|
||||||
|
this.uniqueRealm = uniqueRealm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUniqueRealm() {
|
||||||
|
return uniqueRealm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BothRealmsTarget implements RealmObject, UniqueRealmObject {
|
||||||
|
|
||||||
|
protected String realm;
|
||||||
|
protected String uniqueRealm;
|
||||||
|
|
||||||
|
public String getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRealm(String realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUniqueRealm() {
|
||||||
|
return uniqueRealm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUniqueRealm(String uniqueRealm) {
|
||||||
|
this.uniqueRealm = uniqueRealm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.selection.methodgenerics.wildcards;
|
package org.mapstruct.ap.test.selection.methodgenerics.wildcards;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
import org.mapstruct.ap.testutil.ProcessorTest;
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
import org.mapstruct.ap.testutil.WithClasses;
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
import org.mapstruct.ap.testutil.runner.Compiler;
|
import org.mapstruct.ap.testutil.runner.Compiler;
|
||||||
@ -54,4 +55,23 @@ public class WildCardTest {
|
|||||||
assertThat( target ).isNotNull();
|
assertThat( target ).isNotNull();
|
||||||
assertThat( target.getProp() ).isEqualTo( typeC );
|
assertThat( target.getProp() ).isEqualTo( typeC );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Eclipse does not handle intersection types correctly (TODO: worthwhile to investigate?)
|
||||||
|
@ProcessorTest(Compiler.JDK)
|
||||||
|
@WithClasses(LifecycleIntersectionMapper.class)
|
||||||
|
@IssueKey("3036")
|
||||||
|
public void testLifecycleIntersection() {
|
||||||
|
|
||||||
|
LifecycleIntersectionMapper.RealmTarget realmTarget = LifecycleIntersectionMapper.INSTANCE.mapRealm( "test" );
|
||||||
|
assertThat( realmTarget.getRealm() ).isNull();
|
||||||
|
|
||||||
|
LifecycleIntersectionMapper.UniqueRealmTarget uniqueRealmTarget =
|
||||||
|
LifecycleIntersectionMapper.INSTANCE.mapUniqueRealm( "test" );
|
||||||
|
assertThat( uniqueRealmTarget.getUniqueRealm() ).isNull();
|
||||||
|
|
||||||
|
LifecycleIntersectionMapper.BothRealmsTarget bothRealmsTarget =
|
||||||
|
LifecycleIntersectionMapper.INSTANCE.mapBothRealms( "test" );
|
||||||
|
assertThat( bothRealmsTarget.getRealm() ).isEqualTo( "realm_test" );
|
||||||
|
assertThat( bothRealmsTarget.getUniqueRealm() ).isEqualTo( "uniqueRealm_test" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user