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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
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.Executables;
|
||||||
import org.mapstruct.ap.util.Filters;
|
import org.mapstruct.ap.util.Filters;
|
||||||
import org.mapstruct.ap.util.Nouns;
|
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.
|
* 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(
|
return new Type(
|
||||||
typeUtils,
|
typeUtils,
|
||||||
elementUtils,
|
elementUtils,
|
||||||
typeUtils.erasure( typeMirror ),
|
SpecificCompilerWorkarounds.erasure( typeUtils, typeMirror ),
|
||||||
typeElement,
|
typeElement,
|
||||||
typeParameters,
|
typeParameters,
|
||||||
implementationType,
|
implementationType,
|
||||||
@ -429,8 +430,9 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
|
|
||||||
private boolean isSubType(TypeMirror candidate, Class<?> clazz) {
|
private boolean isSubType(TypeMirror candidate, Class<?> clazz) {
|
||||||
String className = clazz.getCanonicalName();
|
String className = clazz.getCanonicalName();
|
||||||
TypeMirror classType = typeUtils.erasure( elementUtils.getTypeElement( className ).asType() );
|
TypeMirror classType =
|
||||||
return TypeUtilsJDK6Fix.isSubType( typeUtils, candidate, 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.MappingTargetPrism;
|
||||||
import org.mapstruct.ap.prism.TargetTypePrism;
|
import org.mapstruct.ap.prism.TargetTypePrism;
|
||||||
import org.mapstruct.ap.util.AnnotationProcessingException;
|
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.
|
* Factory creating {@link Type} instances.
|
||||||
@ -74,12 +76,10 @@ public class TypeFactory {
|
|||||||
this.elementUtils = elementUtils;
|
this.elementUtils = elementUtils;
|
||||||
this.typeUtils = typeUtils;
|
this.typeUtils = typeUtils;
|
||||||
|
|
||||||
iterableType = typeUtils.erasure( elementUtils.getTypeElement( Iterable.class.getCanonicalName() ).asType() );
|
iterableType = erasure( typeUtils, elementUtils.getTypeElement( Iterable.class.getCanonicalName() ).asType() );
|
||||||
collectionType = typeUtils.erasure(
|
collectionType =
|
||||||
elementUtils.getTypeElement( Collection.class.getCanonicalName() )
|
erasure( typeUtils, elementUtils.getTypeElement( Collection.class.getCanonicalName() ).asType() );
|
||||||
.asType()
|
mapType = erasure( typeUtils, elementUtils.getTypeElement( Map.class.getCanonicalName() ).asType() );
|
||||||
);
|
|
||||||
mapType = typeUtils.erasure( elementUtils.getTypeElement( Map.class.getCanonicalName() ).asType() );
|
|
||||||
|
|
||||||
implementationTypes.put( Iterable.class.getName(), getType( ArrayList.class ) );
|
implementationTypes.put( Iterable.class.getName(), getType( ArrayList.class ) );
|
||||||
implementationTypes.put( Collection.class.getName(), getType( ArrayList.class ) );
|
implementationTypes.put( Collection.class.getName(), getType( ArrayList.class ) );
|
||||||
@ -123,10 +123,9 @@ public class TypeFactory {
|
|||||||
|
|
||||||
Type implementationType = getImplementationType( mirror );
|
Type implementationType = getImplementationType( mirror );
|
||||||
|
|
||||||
boolean isVoid = mirror.getKind() == TypeKind.VOID;
|
boolean isIterableType = SpecificCompilerWorkarounds.isSubType( typeUtils, mirror, iterableType );
|
||||||
boolean isIterableType = !isVoid && TypeUtilsJDK6Fix.isSubType( typeUtils, mirror, iterableType );
|
boolean isCollectionType = SpecificCompilerWorkarounds.isSubType( typeUtils, mirror, collectionType );
|
||||||
boolean isCollectionType = !isVoid && TypeUtilsJDK6Fix.isSubType( typeUtils, mirror, collectionType );
|
boolean isMapType = SpecificCompilerWorkarounds.isSubType( typeUtils, mirror, mapType );
|
||||||
boolean isMapType = !isVoid && TypeUtilsJDK6Fix.isSubType( typeUtils, mirror, mapType );
|
|
||||||
|
|
||||||
boolean isEnumType;
|
boolean isEnumType;
|
||||||
boolean isInterface;
|
boolean isInterface;
|
||||||
|
@ -36,7 +36,7 @@ import javax.lang.model.util.SimpleTypeVisitor6;
|
|||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.common.Type;
|
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:
|
* SourceMethodMatcher $8.4 of the JavaLanguage specification describes a method body as such:
|
||||||
@ -222,8 +222,8 @@ public class MethodMatcher {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// check if types are in bound
|
// check if types are in bound
|
||||||
if ( TypeUtilsJDK6Fix.isSubType( typeUtils, t.getLowerBound(), p ) &&
|
if ( SpecificCompilerWorkarounds.isSubType( typeUtils, t.getLowerBound(), p ) &&
|
||||||
TypeUtilsJDK6Fix.isSubType( typeUtils, p, t.getUpperBound() ) ) {
|
SpecificCompilerWorkarounds.isSubType( typeUtils, p, t.getUpperBound() ) ) {
|
||||||
genericTypesMap.put( t, p );
|
genericTypesMap.put( t, p );
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ public class MethodMatcher {
|
|||||||
case DECLARED:
|
case DECLARED:
|
||||||
// for example method: String method(? extends String)
|
// for example method: String method(? extends String)
|
||||||
// isSubType checks range [subtype, type], e.g. isSubtype [Object, String]==true
|
// 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:
|
case TYPEVAR:
|
||||||
// for example method: <T extends String & Serializable> T method(? extends T)
|
// 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)
|
// for example method: String method(? super String)
|
||||||
// to check super type, we can simply reverse the argument, but that would initially yield
|
// 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.
|
// 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 );
|
typeUtils.isSameType( p, superBound );
|
||||||
|
|
||||||
case TYPEVAR:
|
case TYPEVAR:
|
||||||
@ -284,7 +284,7 @@ public class MethodMatcher {
|
|||||||
// to check super type, we can simply reverse the argument, but that would initially yield
|
// 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.
|
// a result: <type, superType] (so type not included) so we need to check sameType also.
|
||||||
TypeMirror superBoundAsDeclared = typeParameter.getBounds().get( 0 );
|
TypeMirror superBoundAsDeclared = typeParameter.getBounds().get( 0 );
|
||||||
return ( TypeUtilsJDK6Fix.isSubType( typeUtils, superBoundAsDeclared, p ) ||
|
return ( SpecificCompilerWorkarounds.isSubType( typeUtils, superBoundAsDeclared, p ) ||
|
||||||
typeUtils.isSameType( p, superBoundAsDeclared ) );
|
typeUtils.isSameType( p, superBoundAsDeclared ) );
|
||||||
default:
|
default:
|
||||||
// does this situation occur?
|
// does this situation occur?
|
||||||
@ -325,7 +325,7 @@ public class MethodMatcher {
|
|||||||
if ( t != null && bounds != null ) {
|
if ( t != null && bounds != null ) {
|
||||||
for ( TypeMirror bound : bounds ) {
|
for ( TypeMirror bound : bounds ) {
|
||||||
if ( !( bound.getKind().equals( TypeKind.DECLARED ) &&
|
if ( !( bound.getKind().equals( TypeKind.DECLARED ) &&
|
||||||
TypeUtilsJDK6Fix.isSubType( typeUtils, t, bound ) ) ) {
|
SpecificCompilerWorkarounds.isSubType( typeUtils, t, bound ) ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,20 +19,25 @@
|
|||||||
|
|
||||||
package org.mapstruct.ap.util;
|
package org.mapstruct.ap.util;
|
||||||
|
|
||||||
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.Types;
|
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 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
|
* 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>.
|
* 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 types the type utils
|
||||||
* @param t1 the first type
|
* @param t1 the first type
|
||||||
@ -41,6 +46,31 @@ public class TypeUtilsJDK6Fix {
|
|||||||
* @throws IllegalArgumentException if given an executable or package type
|
* @throws IllegalArgumentException if given an executable or package type
|
||||||
*/
|
*/
|
||||||
public static boolean isSubType(Types types, TypeMirror t1, TypeMirror t2) {
|
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