diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java index 88df2d24d..35d430e94 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; + import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; @@ -40,7 +41,7 @@ import javax.lang.model.util.Types; import org.mapstruct.ap.util.Executables; import org.mapstruct.ap.util.Filters; import org.mapstruct.ap.util.Nouns; -import org.mapstruct.ap.util.TypeUtilsJDK6Fix; +import org.mapstruct.ap.util.SpecificCompilerWorkarounds; /** * Represents (a reference to) the type of a bean property, parameter etc. Types are managed per generated source file. @@ -239,7 +240,7 @@ public class Type extends ModelElement implements Comparable { return new Type( typeUtils, elementUtils, - typeUtils.erasure( typeMirror ), + SpecificCompilerWorkarounds.erasure( typeUtils, typeMirror ), typeElement, typeParameters, implementationType, @@ -429,8 +430,9 @@ public class Type extends ModelElement implements Comparable { private boolean isSubType(TypeMirror candidate, Class clazz) { String className = clazz.getCanonicalName(); - TypeMirror classType = typeUtils.erasure( elementUtils.getTypeElement( className ).asType() ); - return TypeUtilsJDK6Fix.isSubType( typeUtils, candidate, classType ); + TypeMirror classType = + SpecificCompilerWorkarounds.erasure( typeUtils, elementUtils.getTypeElement( className ).asType() ); + return SpecificCompilerWorkarounds.isSubType( typeUtils, candidate, classType ); } /** diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java index 59e6d4433..d0b2ad95a 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java @@ -51,7 +51,9 @@ import javax.lang.model.util.Types; import org.mapstruct.ap.prism.MappingTargetPrism; import org.mapstruct.ap.prism.TargetTypePrism; import org.mapstruct.ap.util.AnnotationProcessingException; -import org.mapstruct.ap.util.TypeUtilsJDK6Fix; +import org.mapstruct.ap.util.SpecificCompilerWorkarounds; + +import static org.mapstruct.ap.util.SpecificCompilerWorkarounds.erasure; /** * Factory creating {@link Type} instances. @@ -74,12 +76,10 @@ public class TypeFactory { this.elementUtils = elementUtils; this.typeUtils = typeUtils; - iterableType = typeUtils.erasure( elementUtils.getTypeElement( Iterable.class.getCanonicalName() ).asType() ); - collectionType = typeUtils.erasure( - elementUtils.getTypeElement( Collection.class.getCanonicalName() ) - .asType() - ); - mapType = typeUtils.erasure( elementUtils.getTypeElement( Map.class.getCanonicalName() ).asType() ); + iterableType = erasure( typeUtils, elementUtils.getTypeElement( Iterable.class.getCanonicalName() ).asType() ); + collectionType = + erasure( typeUtils, elementUtils.getTypeElement( Collection.class.getCanonicalName() ).asType() ); + mapType = erasure( typeUtils, elementUtils.getTypeElement( Map.class.getCanonicalName() ).asType() ); implementationTypes.put( Iterable.class.getName(), getType( ArrayList.class ) ); implementationTypes.put( Collection.class.getName(), getType( ArrayList.class ) ); @@ -123,10 +123,9 @@ public class TypeFactory { Type implementationType = getImplementationType( mirror ); - boolean isVoid = mirror.getKind() == TypeKind.VOID; - boolean isIterableType = !isVoid && TypeUtilsJDK6Fix.isSubType( typeUtils, mirror, iterableType ); - boolean isCollectionType = !isVoid && TypeUtilsJDK6Fix.isSubType( typeUtils, mirror, collectionType ); - boolean isMapType = !isVoid && TypeUtilsJDK6Fix.isSubType( typeUtils, mirror, mapType ); + boolean isIterableType = SpecificCompilerWorkarounds.isSubType( typeUtils, mirror, iterableType ); + boolean isCollectionType = SpecificCompilerWorkarounds.isSubType( typeUtils, mirror, collectionType ); + boolean isMapType = SpecificCompilerWorkarounds.isSubType( typeUtils, mirror, mapType ); boolean isEnumType; boolean isInterface; diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java b/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java index 2e5c7ba15..45761a2dc 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java @@ -36,7 +36,7 @@ import javax.lang.model.util.SimpleTypeVisitor6; import javax.lang.model.util.Types; import org.mapstruct.ap.model.common.Type; -import org.mapstruct.ap.util.TypeUtilsJDK6Fix; +import org.mapstruct.ap.util.SpecificCompilerWorkarounds; /** * SourceMethodMatcher $8.4 of the JavaLanguage specification describes a method body as such: @@ -222,8 +222,8 @@ public class MethodMatcher { } else { // check if types are in bound - if ( TypeUtilsJDK6Fix.isSubType( typeUtils, t.getLowerBound(), p ) && - TypeUtilsJDK6Fix.isSubType( typeUtils, p, t.getUpperBound() ) ) { + if ( SpecificCompilerWorkarounds.isSubType( typeUtils, t.getLowerBound(), p ) && + SpecificCompilerWorkarounds.isSubType( typeUtils, p, t.getUpperBound() ) ) { genericTypesMap.put( t, p ); return Boolean.TRUE; } @@ -243,7 +243,7 @@ public class MethodMatcher { case DECLARED: // for example method: String method(? extends String) // isSubType checks range [subtype, type], e.g. isSubtype [Object, String]==true - return TypeUtilsJDK6Fix.isSubType( typeUtils, p, extendsBound ); + return SpecificCompilerWorkarounds.isSubType( typeUtils, p, extendsBound ); case TYPEVAR: // for example method: T method(? extends T) @@ -265,7 +265,7 @@ public class MethodMatcher { // for example method: String method(? super String) // to check super type, we can simply reverse the argument, but that would initially yield // a result: JLS section 4.10, Subtyping. + *

+ * Work-around for a bug related to sub-typing in the Eclipse JSR 269 implementation. * * @param types the type utils * @param t1 the first type @@ -41,6 +46,31 @@ public class TypeUtilsJDK6Fix { * @throws IllegalArgumentException if given an executable or package type */ public static boolean isSubType(Types types, TypeMirror t1, TypeMirror t2) { - return types.isSubtype( types.erasure( t1 ), types.erasure( t2 ) ); + if ( t1.getKind() == TypeKind.VOID ) { + return false; + } + + return types.isSubtype( erasure( types, t1 ), erasure( types, t2 ) ); + } + + /** + * Returns the erasure of a type. + *

+ * Performs an additional test on the given type to check if it is not void. Calling + * {@link Types#erasure(TypeMirror)} with a void kind type will create a ClassCastException in Eclipse JDT. + * + * @param types the type utils + * @param t the type to be erased + * @return the erasure of the given type + * @throws IllegalArgumentException if given a package type + * @jls 4.6 Type Erasure + */ + public static TypeMirror erasure(Types types, TypeMirror t) { + if ( t.getKind() == TypeKind.VOID ) { + return t; + } + else { + return types.erasure( t ); + } } }