mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#312 rename TypeUtilsJDK8Fix to SpecificCompilerWorkarounds and encapsulate all access to Types#erasure(..) by that class, preventing ClassCastExceptions in Eclipse JDT in case we try to determine the erasure of "void"
This commit is contained in:
parent
c590e35548
commit
912ba714c1
@ -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<Type> {
|
||||
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<Type> {
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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 extends String & Serializable> 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: <type, superType] (so type not included) so we need to check sameType also.
|
||||
return TypeUtilsJDK6Fix.isSubType( typeUtils, superBound, p ) ||
|
||||
return SpecificCompilerWorkarounds.isSubType( typeUtils, superBound, p ) ||
|
||||
typeUtils.isSameType( p, superBound );
|
||||
|
||||
case TYPEVAR:
|
||||
@ -284,7 +284,7 @@ public class MethodMatcher {
|
||||
// to check super type, we can simply reverse the argument, but that would initially yield
|
||||
// a result: <type, superType] (so type not included) so we need to check sameType also.
|
||||
TypeMirror superBoundAsDeclared = typeParameter.getBounds().get( 0 );
|
||||
return ( TypeUtilsJDK6Fix.isSubType( typeUtils, superBoundAsDeclared, p ) ||
|
||||
return ( SpecificCompilerWorkarounds.isSubType( typeUtils, superBoundAsDeclared, p ) ||
|
||||
typeUtils.isSameType( p, superBoundAsDeclared ) );
|
||||
default:
|
||||
// does this situation occur?
|
||||
@ -325,7 +325,7 @@ public class MethodMatcher {
|
||||
if ( t != null && bounds != null ) {
|
||||
for ( TypeMirror bound : bounds ) {
|
||||
if ( !( bound.getKind().equals( TypeKind.DECLARED ) &&
|
||||
TypeUtilsJDK6Fix.isSubType( typeUtils, t, bound ) ) ) {
|
||||
SpecificCompilerWorkarounds.isSubType( typeUtils, t, bound ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -19,20 +19,25 @@
|
||||
|
||||
package org.mapstruct.ap.util;
|
||||
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
/**
|
||||
* Work-around for a bug related to sub-typing in the Eclipse JSR 269 implementation.
|
||||
* Contains workarounds for various quirks in specific compilers.
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
* @author Andreas Gudian
|
||||
*/
|
||||
public class TypeUtilsJDK6Fix {
|
||||
public class SpecificCompilerWorkarounds {
|
||||
|
||||
private TypeUtilsJDK6Fix() { }
|
||||
private SpecificCompilerWorkarounds() { }
|
||||
|
||||
/**
|
||||
* Tests whether one type is a subtype of another. Any type is considered to be a subtype of itself. Also see <a
|
||||
* href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html">JLS section 4.10, Subtyping</a>.
|
||||
* <p />
|
||||
* 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.
|
||||
* <p/>
|
||||
* 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 );
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user