mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
861 remove compiler specific workarounds (#2227)
This commit is contained in:
parent
74d06fea5d
commit
c2e8034030
@ -12,7 +12,7 @@ import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.util.Elements;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Accessibility;
|
||||
import org.mapstruct.ap.internal.model.common.ModelElement;
|
||||
@ -35,7 +35,7 @@ public abstract class GeneratedType extends ModelElement {
|
||||
|
||||
private T myself;
|
||||
protected TypeFactory typeFactory;
|
||||
protected Elements elementUtils;
|
||||
protected ElementUtils elementUtils;
|
||||
protected Options options;
|
||||
protected VersionInformation versionInformation;
|
||||
protected SortedSet<Type> extraImportedTypes;
|
||||
@ -46,7 +46,7 @@ public abstract class GeneratedType extends ModelElement {
|
||||
myself = selfType.cast( this );
|
||||
}
|
||||
|
||||
public T elementUtils(Elements elementUtils) {
|
||||
public T elementUtils(ElementUtils elementUtils) {
|
||||
this.elementUtils = elementUtils;
|
||||
return myself;
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ import java.util.function.Supplier;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||
@ -103,8 +103,8 @@ public class MappingBuilderContext {
|
||||
}
|
||||
|
||||
private final TypeFactory typeFactory;
|
||||
private final Elements elementUtils;
|
||||
private final Types typeUtils;
|
||||
private final ElementUtils elementUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final FormattingMessager messager;
|
||||
private final AccessorNamingUtils accessorNaming;
|
||||
private final EnumMappingStrategy enumMappingStrategy;
|
||||
@ -120,8 +120,8 @@ public class MappingBuilderContext {
|
||||
|
||||
//CHECKSTYLE:OFF
|
||||
public MappingBuilderContext(TypeFactory typeFactory,
|
||||
Elements elementUtils,
|
||||
Types typeUtils,
|
||||
ElementUtils elementUtils,
|
||||
TypeUtils typeUtils,
|
||||
FormattingMessager messager,
|
||||
AccessorNamingUtils accessorNaming,
|
||||
EnumMappingStrategy enumMappingStrategy,
|
||||
@ -175,11 +175,11 @@ public class MappingBuilderContext {
|
||||
return typeFactory;
|
||||
}
|
||||
|
||||
public Elements getElementUtils() {
|
||||
public ElementUtils getElementUtils() {
|
||||
return elementUtils;
|
||||
}
|
||||
|
||||
public Types getTypeUtils() {
|
||||
public TypeUtils getTypeUtils() {
|
||||
return typeUtils;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BeanMappingGem;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
@ -295,7 +295,7 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
return ctx.getEnumMappingStrategy().getEnumConstant( typeElement, enumConstant );
|
||||
}
|
||||
|
||||
private SelectionParameters getSelectionParameters(Method method, Types typeUtils) {
|
||||
private SelectionParameters getSelectionParameters(Method method, TypeUtils typeUtils) {
|
||||
BeanMappingGem beanMapping = BeanMappingGem.instanceOn( method.getExecutable() );
|
||||
if ( beanMapping != null ) {
|
||||
List<TypeMirror> qualifiers = beanMapping.qualifiedBy().get();
|
||||
|
@ -9,7 +9,7 @@ import java.util.Collection;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.spi.BuilderInfo;
|
||||
|
||||
@ -84,7 +84,7 @@ public class BuilderType {
|
||||
}
|
||||
|
||||
public static BuilderType create(BuilderInfo builderInfo, Type typeToBuild, TypeFactory typeFactory,
|
||||
Types typeUtils) {
|
||||
TypeUtils typeUtils) {
|
||||
if ( builderInfo == null ) {
|
||||
return null;
|
||||
}
|
||||
|
@ -28,22 +28,21 @@ import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.SimpleTypeVisitor8;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.CollectionMappingStrategyGem;
|
||||
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.Executables;
|
||||
import org.mapstruct.ap.internal.util.Fields;
|
||||
import org.mapstruct.ap.internal.util.Filters;
|
||||
import org.mapstruct.ap.internal.util.JavaStreamConstants;
|
||||
import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
import org.mapstruct.ap.internal.util.Nouns;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.AccessorType;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
|
||||
/**
|
||||
* Represents (a reference to) the type of a bean property, parameter etc. Types are managed per generated source file.
|
||||
@ -57,8 +56,8 @@ import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
*/
|
||||
public class Type extends ModelElement implements Comparable<Type> {
|
||||
|
||||
private final Types typeUtils;
|
||||
private final Elements elementUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final ElementUtils elementUtils;
|
||||
private final TypeFactory typeFactory;
|
||||
private final AccessorNamingUtils accessorNaming;
|
||||
|
||||
@ -109,7 +108,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
private final Filters filters;
|
||||
|
||||
//CHECKSTYLE:OFF
|
||||
public Type(Types typeUtils, Elements elementUtils, TypeFactory typeFactory,
|
||||
public Type(TypeUtils typeUtils, ElementUtils elementUtils, TypeFactory typeFactory,
|
||||
AccessorNamingUtils accessorNaming,
|
||||
TypeMirror typeMirror, TypeElement typeElement,
|
||||
List<Type> typeParameters, ImplementationType implementationType, Type componentType,
|
||||
@ -662,7 +661,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
|
||||
private List<ExecutableElement> getAllMethods() {
|
||||
if ( allMethods == null ) {
|
||||
allMethods = Executables.getAllEnclosedExecutableElements( elementUtils, typeElement );
|
||||
allMethods = elementUtils.getAllEnclosedExecutableElements( typeElement );
|
||||
}
|
||||
|
||||
return allMethods;
|
||||
@ -670,7 +669,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
|
||||
private List<VariableElement> getAllFields() {
|
||||
if ( allFields == null ) {
|
||||
allFields = Fields.getAllEnclosedFields( elementUtils, typeElement );
|
||||
allFields = elementUtils.getAllEnclosedFields( typeElement );
|
||||
}
|
||||
|
||||
return allFields;
|
||||
@ -861,7 +860,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
private boolean isStream(TypeMirror candidate) {
|
||||
TypeElement streamTypeElement = elementUtils.getTypeElement( JavaStreamConstants.STREAM_FQN );
|
||||
TypeMirror streamType = streamTypeElement == null ? null : typeUtils.erasure( streamTypeElement.asType() );
|
||||
return streamType != null && typeUtils.isSubtype( candidate, streamType );
|
||||
return streamType != null && typeUtils.isSubtypeErased( candidate, streamType );
|
||||
}
|
||||
|
||||
private boolean isMap(TypeMirror candidate) {
|
||||
@ -871,7 +870,7 @@ 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 typeUtils.isSubtype( candidate, classType );
|
||||
return typeUtils.isSubtypeErased( candidate, classType );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1141,9 +1140,9 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
private static class TypeVarMatcher extends SimpleTypeVisitor8<Type, Type> {
|
||||
|
||||
private TypeVariable typeVarToMatch;
|
||||
private Types types;
|
||||
private TypeUtils types;
|
||||
|
||||
TypeVarMatcher( Types types, Type typeVarToMatch ) {
|
||||
TypeVarMatcher(TypeUtils types, Type typeVarToMatch ) {
|
||||
super( null );
|
||||
this.typeVarToMatch = (TypeVariable) typeVarToMatch.getTypeMirror();
|
||||
this.types = types;
|
||||
|
@ -36,8 +36,8 @@ import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
|
||||
@ -81,8 +81,8 @@ public class TypeFactory {
|
||||
return sb.toString();
|
||||
};
|
||||
|
||||
private final Elements elementUtils;
|
||||
private final Types typeUtils;
|
||||
private final ElementUtils elementUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final FormattingMessager messager;
|
||||
private final RoundContext roundContext;
|
||||
|
||||
@ -97,8 +97,8 @@ public class TypeFactory {
|
||||
|
||||
private final boolean loggingVerbose;
|
||||
|
||||
public TypeFactory(Elements elementUtils, Types typeUtils, FormattingMessager messager, RoundContext roundContext,
|
||||
Map<String, String> notToBeImportedTypes, boolean loggingVerbose) {
|
||||
public TypeFactory(ElementUtils elementUtils, TypeUtils typeUtils, FormattingMessager messager,
|
||||
RoundContext roundContext, Map<String, String> notToBeImportedTypes, boolean loggingVerbose) {
|
||||
this.elementUtils = elementUtils;
|
||||
this.typeUtils = typeUtils;
|
||||
this.messager = messager;
|
||||
@ -198,10 +198,10 @@ public class TypeFactory {
|
||||
|
||||
ImplementationType implementationType = getImplementationType( mirror );
|
||||
|
||||
boolean isIterableType = typeUtils.isSubtype( mirror, iterableType );
|
||||
boolean isCollectionType = typeUtils.isSubtype( mirror, collectionType );
|
||||
boolean isMapType = typeUtils.isSubtype( mirror, mapType );
|
||||
boolean isStreamType = streamType != null && typeUtils.isSubtype( mirror, streamType );
|
||||
boolean isIterableType = typeUtils.isSubtypeErased( mirror, iterableType );
|
||||
boolean isCollectionType = typeUtils.isSubtypeErased( mirror, collectionType );
|
||||
boolean isMapType = typeUtils.isSubtypeErased( mirror, mapType );
|
||||
boolean isStreamType = streamType != null && typeUtils.isSubtypeErased( mirror, streamType );
|
||||
|
||||
boolean isEnumType;
|
||||
boolean isInterface;
|
||||
|
@ -11,8 +11,8 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.gem.BeanMappingGem;
|
||||
@ -50,7 +50,7 @@ public class BeanMappingOptions extends DelegatingOptions {
|
||||
|
||||
public static BeanMappingOptions getInstanceOn(BeanMappingGem beanMapping, MapperOptions mapperOptions,
|
||||
ExecutableElement method, FormattingMessager messager,
|
||||
Types typeUtils, TypeFactory typeFactory
|
||||
TypeUtils typeUtils, TypeFactory typeFactory
|
||||
) {
|
||||
if ( beanMapping == null || !isConsistent( beanMapping, method, messager ) ) {
|
||||
BeanMappingOptions options = new BeanMappingOptions( null, null, mapperOptions );
|
||||
@ -143,7 +143,7 @@ public class BeanMappingOptions extends DelegatingOptions {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingControl getMappingControl(Elements elementUtils) {
|
||||
public MappingControl getMappingControl(ElementUtils elementUtils) {
|
||||
return Optional.ofNullable( beanMapping ).map( BeanMappingGem::mappingControl )
|
||||
.filter( GemValue::hasValue )
|
||||
.map( GemValue::getValue )
|
||||
|
@ -9,7 +9,7 @@ import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
@ -124,7 +124,7 @@ public class DefaultOptions extends DelegatingOptions {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingControl getMappingControl(Elements elementUtils) {
|
||||
public MappingControl getMappingControl(ElementUtils elementUtils) {
|
||||
return MappingControl.fromTypeMirror( mapper.mappingControl().getDefaultValue(), elementUtils );
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
import org.mapstruct.ap.internal.gem.CollectionMappingStrategyGem;
|
||||
@ -101,7 +101,7 @@ public abstract class DelegatingOptions {
|
||||
return next.getBuilder();
|
||||
}
|
||||
|
||||
public MappingControl getMappingControl(Elements elementUtils) {
|
||||
public MappingControl getMappingControl(ElementUtils elementUtils) {
|
||||
return next.getMappingControl( elementUtils );
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,8 @@ package org.mapstruct.ap.internal.model.source;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.gem.IterableMappingGem;
|
||||
@ -31,7 +31,7 @@ public class IterableMappingOptions extends DelegatingOptions {
|
||||
|
||||
public static IterableMappingOptions fromGem(IterableMappingGem iterableMapping,
|
||||
MapperOptions mappperOptions, ExecutableElement method,
|
||||
FormattingMessager messager, Types typeUtils) {
|
||||
FormattingMessager messager, TypeUtils typeUtils) {
|
||||
|
||||
if ( iterableMapping == null || !isConsistent( iterableMapping, method, messager ) ) {
|
||||
IterableMappingOptions options = new IterableMappingOptions( null, null, null, mappperOptions );
|
||||
@ -102,7 +102,7 @@ public class IterableMappingOptions extends DelegatingOptions {
|
||||
.orElse( next().getNullValueMappingStrategy() );
|
||||
}
|
||||
|
||||
public MappingControl getElementMappingControl(Elements elementUtils) {
|
||||
public MappingControl getElementMappingControl(ElementUtils elementUtils) {
|
||||
return Optional.ofNullable( iterableMapping ).map( IterableMappingGem::elementMappingControl )
|
||||
.filter( GemValue::hasValue )
|
||||
.map( GemValue::getValue )
|
||||
|
@ -8,8 +8,8 @@ package org.mapstruct.ap.internal.model.source;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.gem.MapMappingGem;
|
||||
@ -32,7 +32,8 @@ public class MapMappingOptions extends DelegatingOptions {
|
||||
private final MapMappingGem mapMapping;
|
||||
|
||||
public static MapMappingOptions fromGem(MapMappingGem mapMapping, MapperOptions mapperOptions,
|
||||
ExecutableElement method, FormattingMessager messager, Types typeUtils) {
|
||||
ExecutableElement method, FormattingMessager messager,
|
||||
TypeUtils typeUtils) {
|
||||
|
||||
if ( mapMapping == null || !isConsistent( mapMapping, method, messager ) ) {
|
||||
MapMappingOptions options = new MapMappingOptions(
|
||||
@ -146,7 +147,7 @@ public class MapMappingOptions extends DelegatingOptions {
|
||||
.orElse( next().getNullValueMappingStrategy() );
|
||||
}
|
||||
|
||||
public MappingControl getKeyMappingControl(Elements elementUtils) {
|
||||
public MappingControl getKeyMappingControl(ElementUtils elementUtils) {
|
||||
return Optional.ofNullable( mapMapping ).map( MapMappingGem::keyMappingControl )
|
||||
.filter( GemValue::hasValue )
|
||||
.map( GemValue::getValue )
|
||||
@ -154,7 +155,7 @@ public class MapMappingOptions extends DelegatingOptions {
|
||||
.orElse( next().getMappingControl( elementUtils ) );
|
||||
}
|
||||
|
||||
public MappingControl getValueMappingControl(Elements elementUtils) {
|
||||
public MappingControl getValueMappingControl(ElementUtils elementUtils) {
|
||||
return Optional.ofNullable( mapMapping ).map( MapMappingGem::valueMappingControl )
|
||||
.filter( GemValue::hasValue )
|
||||
.map( GemValue::getValue )
|
||||
|
@ -8,7 +8,7 @@ package org.mapstruct.ap.internal.model.source;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
import org.mapstruct.ap.internal.gem.CollectionMappingStrategyGem;
|
||||
@ -132,7 +132,7 @@ public class MapperConfigOptions extends DelegatingOptions {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingControl getMappingControl(Elements elementUtils) {
|
||||
public MappingControl getMappingControl(ElementUtils elementUtils) {
|
||||
return mapperConfig.mappingControl().hasValue() ?
|
||||
MappingControl.fromTypeMirror( mapperConfig.mappingControl().getValue(), elementUtils ) :
|
||||
next().getMappingControl( elementUtils );
|
||||
|
@ -12,7 +12,7 @@ import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
@ -162,7 +162,7 @@ public class MapperOptions extends DelegatingOptions {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingControl getMappingControl(Elements elementUtils) {
|
||||
public MappingControl getMappingControl(ElementUtils elementUtils) {
|
||||
return mapper.mappingControl().hasValue() ?
|
||||
MappingControl.fromTypeMirror( mapper.mappingControl().getValue(), elementUtils ) :
|
||||
next().getMappingControl( elementUtils );
|
||||
|
@ -14,7 +14,7 @@ import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.MappingControlGem;
|
||||
import org.mapstruct.ap.internal.gem.MappingControlUseGem;
|
||||
@ -32,7 +32,7 @@ public class MappingControl {
|
||||
private boolean allowMappingMethod = false;
|
||||
private boolean allow2Steps = false;
|
||||
|
||||
public static MappingControl fromTypeMirror(TypeMirror mirror, Elements elementUtils) {
|
||||
public static MappingControl fromTypeMirror(TypeMirror mirror, ElementUtils elementUtils) {
|
||||
MappingControl mappingControl = new MappingControl();
|
||||
if ( TypeKind.DECLARED == mirror.getKind() ) {
|
||||
resolveControls( mappingControl, ( (DeclaredType) mirror ).asElement(), new HashSet<>(), elementUtils );
|
||||
@ -60,7 +60,7 @@ public class MappingControl {
|
||||
}
|
||||
|
||||
private static void resolveControls(MappingControl control, Element element, Set<Element> handledElements,
|
||||
Elements elementUtils) {
|
||||
ElementUtils elementUtils) {
|
||||
for ( AnnotationMirror annotationMirror : element.getAnnotationMirrors() ) {
|
||||
Element lElement = annotationMirror.getAnnotationType().asElement();
|
||||
if ( isAnnotation( lElement, MAPPING_CONTROL_FQN ) ) {
|
||||
@ -102,7 +102,7 @@ public class MappingControl {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAnnotationInPackage(Element element, String packageFQN, Elements elementUtils) {
|
||||
private static boolean isAnnotationInPackage(Element element, String packageFQN, ElementUtils elementUtils) {
|
||||
if ( ElementKind.ANNOTATION_TYPE == element.getKind() ) {
|
||||
return packageFQN.equals( elementUtils.getPackageOf( element ).getQualifiedName().toString() );
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.MappingGem;
|
||||
import org.mapstruct.ap.internal.gem.MappingsGem;
|
||||
@ -93,7 +93,7 @@ public class MappingOptions extends DelegatingOptions {
|
||||
|
||||
public static void addInstances(MappingsGem gem, ExecutableElement method,
|
||||
BeanMappingOptions beanMappingOptions,
|
||||
FormattingMessager messager, Types typeUtils,
|
||||
FormattingMessager messager, TypeUtils typeUtils,
|
||||
Set<MappingOptions> mappings) {
|
||||
|
||||
for ( MappingGem mapping : gem.value().getValue() ) {
|
||||
@ -102,7 +102,8 @@ public class MappingOptions extends DelegatingOptions {
|
||||
}
|
||||
|
||||
public static void addInstance(MappingGem mapping, ExecutableElement method,
|
||||
BeanMappingOptions beanMappingOptions, FormattingMessager messager, Types typeUtils,
|
||||
BeanMappingOptions beanMappingOptions, FormattingMessager messager,
|
||||
TypeUtils typeUtils,
|
||||
Set<MappingOptions> mappings) {
|
||||
|
||||
if ( !isConsistent( mapping, method, messager ) ) {
|
||||
@ -421,7 +422,7 @@ public class MappingOptions extends DelegatingOptions {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingControl getMappingControl(Elements elementUtils) {
|
||||
public MappingControl getMappingControl(ElementUtils elementUtils) {
|
||||
return Optional.ofNullable( mapping ).map( MappingGem::mappingControl )
|
||||
.filter( GemValue::hasValue )
|
||||
.map( GemValue::getValue )
|
||||
|
@ -19,7 +19,7 @@ import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
@ -53,10 +53,10 @@ import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
public class MethodMatcher {
|
||||
|
||||
private final SourceMethod candidateMethod;
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final TypeFactory typeFactory;
|
||||
|
||||
MethodMatcher(Types typeUtils, TypeFactory typeFactory, SourceMethod candidateMethod) {
|
||||
MethodMatcher(TypeUtils typeUtils, TypeFactory typeFactory, SourceMethod candidateMethod) {
|
||||
this.typeUtils = typeUtils;
|
||||
this.candidateMethod = candidateMethod;
|
||||
this.typeFactory = typeFactory;
|
||||
@ -312,8 +312,8 @@ public class MethodMatcher {
|
||||
// check if types are in bound
|
||||
TypeMirror lowerBound = t.getLowerBound();
|
||||
TypeMirror upperBound = t.getUpperBound();
|
||||
if ( ( isNullType( lowerBound ) || typeUtils.isSubtype( lowerBound, p ) )
|
||||
&& ( isNullType( upperBound ) || typeUtils.isSubtype( p, upperBound ) ) ) {
|
||||
if ( ( isNullType( lowerBound ) || typeUtils.isSubtypeErased( lowerBound, p ) )
|
||||
&& ( isNullType( upperBound ) || typeUtils.isSubtypeErased( p, upperBound ) ) ) {
|
||||
genericTypesMap.put( t, p );
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
@ -359,7 +359,7 @@ public class MethodMatcher {
|
||||
// for example method: String method(? super String)
|
||||
// to check super type, we can simply inverse the argument, but that would initially yield
|
||||
// a result: <type, superType] (so type not included) so we need to check sameType also.
|
||||
return typeUtils.isSubtype( superBound, p ) || typeUtils.isSameType( p, superBound );
|
||||
return typeUtils.isSubtypeErased( superBound, p ) || typeUtils.isSameType( p, superBound );
|
||||
|
||||
case TYPEVAR:
|
||||
|
||||
@ -377,7 +377,7 @@ public class MethodMatcher {
|
||||
// to check super type, we can simply inverse 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 ( typeUtils.isSubtype( superBoundAsDeclared, p ) || typeUtils.isSameType(
|
||||
return ( typeUtils.isSubtypeErased( superBoundAsDeclared, p ) || typeUtils.isSameType(
|
||||
p,
|
||||
superBoundAsDeclared ) );
|
||||
default:
|
||||
@ -415,7 +415,7 @@ public class MethodMatcher {
|
||||
List<? extends TypeMirror> bounds = tpe != null ? tpe.getBounds() : null;
|
||||
if ( t != null && bounds != null ) {
|
||||
for ( TypeMirror bound : bounds ) {
|
||||
if ( !( bound.getKind() == TypeKind.DECLARED && typeUtils.isSubtype( t, bound ) ) ) {
|
||||
if ( !( bound.getKind() == TypeKind.DECLARED && typeUtils.isSubtypeErased( t, bound ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.SourceRHS;
|
||||
|
||||
@ -24,7 +24,7 @@ public class SelectionParameters {
|
||||
private final List<TypeMirror> qualifiers;
|
||||
private final List<String> qualifyingNames;
|
||||
private final TypeMirror resultType;
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final SourceRHS sourceRHS;
|
||||
|
||||
/**
|
||||
@ -45,12 +45,12 @@ public class SelectionParameters {
|
||||
}
|
||||
|
||||
public SelectionParameters(List<TypeMirror> qualifiers, List<String> qualifyingNames, TypeMirror resultType,
|
||||
Types typeUtils) {
|
||||
TypeUtils typeUtils) {
|
||||
this( qualifiers, qualifyingNames, resultType, typeUtils, null );
|
||||
}
|
||||
|
||||
private SelectionParameters(List<TypeMirror> qualifiers, List<String> qualifyingNames, TypeMirror resultType,
|
||||
Types typeUtils, SourceRHS sourceRHS) {
|
||||
TypeUtils typeUtils, SourceRHS sourceRHS) {
|
||||
this.qualifiers = qualifiers;
|
||||
this.qualifyingNames = qualifyingNames;
|
||||
this.resultType = resultType;
|
||||
|
@ -13,7 +13,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Accessibility;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
@ -37,7 +37,7 @@ import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
*/
|
||||
public class SourceMethod implements Method {
|
||||
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final TypeFactory typeFactory;
|
||||
|
||||
private final Type declaringMapper;
|
||||
@ -82,7 +82,7 @@ public class SourceMethod implements Method {
|
||||
private IterableMappingOptions iterableMapping = null;
|
||||
private MapMappingOptions mapMapping = null;
|
||||
private BeanMappingOptions beanMapping = null;
|
||||
private Types typeUtils;
|
||||
private TypeUtils typeUtils;
|
||||
private TypeFactory typeFactory = null;
|
||||
private MapperOptions mapper = null;
|
||||
private List<SourceMethod> prototypeMethods = Collections.emptyList();
|
||||
@ -146,7 +146,7 @@ public class SourceMethod implements Method {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTypeUtils(Types typeUtils) {
|
||||
public Builder setTypeUtils(TypeUtils typeUtils) {
|
||||
this.typeUtils = typeUtils;
|
||||
return this;
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ package org.mapstruct.ap.internal.model.source.selector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
@ -25,7 +25,7 @@ public class MethodSelectors {
|
||||
|
||||
private final List<MethodSelector> selectors;
|
||||
|
||||
public MethodSelectors(Types typeUtils, Elements elementUtils, TypeFactory typeFactory,
|
||||
public MethodSelectors(TypeUtils typeUtils, ElementUtils elementUtils, TypeFactory typeFactory,
|
||||
FormattingMessager messager) {
|
||||
selectors = Arrays.asList(
|
||||
new MethodFamilySelector(),
|
||||
|
@ -12,8 +12,8 @@ import java.util.Set;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
@ -40,10 +40,10 @@ import org.mapstruct.ap.internal.gem.QualifierGem;
|
||||
*/
|
||||
public class QualifierSelector implements MethodSelector {
|
||||
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final TypeMirror namedAnnotationTypeMirror;
|
||||
|
||||
public QualifierSelector( Types typeUtils, Elements elementUtils ) {
|
||||
public QualifierSelector(TypeUtils typeUtils, ElementUtils elementUtils ) {
|
||||
this.typeUtils = typeUtils;
|
||||
namedAnnotationTypeMirror = elementUtils.getTypeElement( "org.mapstruct.Named" ).asType();
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
@ -24,9 +24,9 @@ import org.mapstruct.ap.internal.model.source.Method;
|
||||
*/
|
||||
public class TargetTypeSelector implements MethodSelector {
|
||||
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
|
||||
public TargetTypeSelector( Types typeUtils ) {
|
||||
public TargetTypeSelector( TypeUtils typeUtils ) {
|
||||
this.typeUtils = typeUtils;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.XmlElementRefGem;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
@ -37,9 +37,9 @@ import org.mapstruct.ap.internal.gem.XmlElementDeclGem;
|
||||
*/
|
||||
public class XmlElementDeclSelector implements MethodSelector {
|
||||
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
|
||||
public XmlElementDeclSelector(Types typeUtils) {
|
||||
public XmlElementDeclSelector(TypeUtils typeUtils) {
|
||||
this.typeUtils = typeUtils;
|
||||
}
|
||||
|
||||
|
@ -13,18 +13,17 @@ import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.processor.ModelElementProcessor.ProcessorContext;
|
||||
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.RoundContext;
|
||||
import org.mapstruct.ap.internal.util.workarounds.TypesDecorator;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
import org.mapstruct.ap.spi.EnumMappingStrategy;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
@ -41,7 +40,8 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
||||
private final Options options;
|
||||
private final TypeFactory typeFactory;
|
||||
private final VersionInformation versionInformation;
|
||||
private final Types delegatingTypes;
|
||||
private final TypeUtils delegatingTypes;
|
||||
private final ElementUtils delegatingElements;
|
||||
private final AccessorNamingUtils accessorNaming;
|
||||
private final RoundContext roundContext;
|
||||
|
||||
@ -52,10 +52,11 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
||||
this.messager = new DelegatingMessager( processingEnvironment.getMessager(), options.isVerbose() );
|
||||
this.accessorNaming = roundContext.getAnnotationProcessorContext().getAccessorNaming();
|
||||
this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment );
|
||||
this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation );
|
||||
this.delegatingTypes = TypeUtils.create( processingEnvironment, versionInformation );
|
||||
this.delegatingElements = ElementUtils.create( processingEnvironment, versionInformation );
|
||||
this.roundContext = roundContext;
|
||||
this.typeFactory = new TypeFactory(
|
||||
processingEnvironment.getElementUtils(),
|
||||
delegatingElements,
|
||||
delegatingTypes,
|
||||
messager,
|
||||
roundContext,
|
||||
@ -71,13 +72,13 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Types getTypeUtils() {
|
||||
public TypeUtils getTypeUtils() {
|
||||
return delegatingTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Elements getElementUtils() {
|
||||
return processingEnvironment.getElementUtils();
|
||||
public ElementUtils getElementUtils() {
|
||||
return delegatingElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,8 +18,8 @@ import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.BeanMappingMethod;
|
||||
import org.mapstruct.ap.internal.model.ContainerMappingMethod;
|
||||
@ -73,8 +73,8 @@ import static org.mapstruct.ap.internal.util.Collections.join;
|
||||
*/
|
||||
public class MapperCreationProcessor implements ModelElementProcessor<List<SourceMethod>, Mapper> {
|
||||
|
||||
private Elements elementUtils;
|
||||
private Types typeUtils;
|
||||
private ElementUtils elementUtils;
|
||||
private TypeUtils typeUtils;
|
||||
private FormattingMessager messager;
|
||||
private Options options;
|
||||
private VersionInformation versionInformation;
|
||||
|
@ -21,9 +21,15 @@ import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.ExecutableType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BeanMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.IterableMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.MapMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.MappingGem;
|
||||
import org.mapstruct.ap.internal.gem.MappingsGem;
|
||||
import org.mapstruct.ap.internal.gem.ObjectFactoryGem;
|
||||
import org.mapstruct.ap.internal.gem.ValueMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.ValueMappingsGem;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
@ -36,24 +42,16 @@ import org.mapstruct.ap.internal.model.source.MappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.ParameterProvidedMethods;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
import org.mapstruct.ap.internal.model.source.ValueMappingOptions;
|
||||
import org.mapstruct.ap.internal.gem.BeanMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.IterableMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.MapMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.MappingGem;
|
||||
import org.mapstruct.ap.internal.gem.MappingsGem;
|
||||
import org.mapstruct.ap.internal.gem.ObjectFactoryGem;
|
||||
import org.mapstruct.ap.internal.gem.ValueMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.ValueMappingsGem;
|
||||
import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
|
||||
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.Executables;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Executables.getAllEnclosedExecutableElements;
|
||||
|
||||
/**
|
||||
* A {@link ModelElementProcessor} which retrieves a list of {@link SourceMethod}s
|
||||
* representing all the mapping methods of the given bean mapper type as well as
|
||||
@ -73,8 +71,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
private TypeFactory typeFactory;
|
||||
private AccessorNamingUtils accessorNaming;
|
||||
private Map<String, EnumTransformationStrategy> enumTransformationStrategies;
|
||||
private Types typeUtils;
|
||||
private Elements elementUtils;
|
||||
private TypeUtils typeUtils;
|
||||
private ElementUtils elementUtils;
|
||||
private Options options;
|
||||
|
||||
@Override
|
||||
@ -119,7 +117,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
|
||||
TypeElement typeElement = asTypeElement( mapperAnnotation.mapperConfigType() );
|
||||
List<SourceMethod> methods = new ArrayList<>();
|
||||
for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, typeElement ) ) {
|
||||
for ( ExecutableElement executable : elementUtils.getAllEnclosedExecutableElements( typeElement ) ) {
|
||||
|
||||
ExecutableType methodType = typeFactory.getMethodType( mapperAnnotation.mapperConfigType(), executable );
|
||||
List<Parameter> parameters = typeFactory.getParameters( methodType, executable );
|
||||
@ -160,7 +158,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
MapperOptions mapperOptions, List<SourceMethod> prototypeMethods) {
|
||||
List<SourceMethod> methods = new ArrayList<>();
|
||||
|
||||
for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, usedMapper ) ) {
|
||||
for ( ExecutableElement executable : elementUtils.getAllEnclosedExecutableElements( usedMapper ) ) {
|
||||
SourceMethod method = getMethod(
|
||||
usedMapper,
|
||||
executable,
|
||||
|
@ -8,8 +8,8 @@ package org.mapstruct.ap.internal.processor;
|
||||
import java.util.Map;
|
||||
import javax.annotation.processing.Filer;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
@ -35,7 +35,7 @@ public interface ModelElementProcessor<P, R> {
|
||||
/**
|
||||
* Context object passed to
|
||||
* {@link ModelElementProcessor#process(ProcessorContext, TypeElement, Object)}
|
||||
* providing access to common infrastructure objects such as {@link Types}
|
||||
* providing access to common infrastructure objects such as {@link TypeUtils}
|
||||
* etc.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
@ -44,9 +44,9 @@ public interface ModelElementProcessor<P, R> {
|
||||
|
||||
Filer getFiler();
|
||||
|
||||
Types getTypeUtils();
|
||||
TypeUtils getTypeUtils();
|
||||
|
||||
Elements getElementUtils();
|
||||
ElementUtils getElementUtils();
|
||||
|
||||
TypeFactory getTypeFactory();
|
||||
|
||||
|
@ -32,8 +32,8 @@ import javax.lang.model.type.ExecutableType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.conversion.ConversionProvider;
|
||||
import org.mapstruct.ap.internal.conversion.Conversions;
|
||||
@ -78,7 +78,7 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
private static final int LIMIT_REPORTING_AMBIGUOUS = 5;
|
||||
|
||||
private final FormattingMessager messager;
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final TypeFactory typeFactory;
|
||||
|
||||
private final List<Method> sourceModel;
|
||||
@ -98,7 +98,7 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
*/
|
||||
private final Set<SupportingMappingMethod> usedSupportedMappings = new HashSet<>();
|
||||
|
||||
public MappingResolverImpl(FormattingMessager messager, Elements elementUtils, Types typeUtils,
|
||||
public MappingResolverImpl(FormattingMessager messager, ElementUtils elementUtils, TypeUtils typeUtils,
|
||||
TypeFactory typeFactory, List<Method> sourceModel,
|
||||
List<MapperReference> mapperReferences, boolean verboseLogging) {
|
||||
this.messager = messager;
|
||||
|
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
|
||||
|
||||
import static javax.lang.model.util.ElementFilter.fieldsIn;
|
||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||
|
||||
public abstract class AbstractElementUtilsDecorator implements ElementUtils {
|
||||
|
||||
private final Elements delegate;
|
||||
|
||||
AbstractElementUtilsDecorator(ProcessingEnvironment processingEnv) {
|
||||
this.delegate = processingEnv.getElementUtils();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageElement getPackageElement(CharSequence name) {
|
||||
return delegate.getPackageElement( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeElement getTypeElement(CharSequence name) {
|
||||
return delegate.getTypeElement( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValuesWithDefaults(
|
||||
AnnotationMirror a) {
|
||||
return delegate.getElementValuesWithDefaults( a );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDocComment(Element e) {
|
||||
return delegate.getDocComment( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated(Element e) {
|
||||
return delegate.isDeprecated( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getBinaryName(TypeElement type) {
|
||||
return delegate.getBinaryName( type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageElement getPackageOf(Element type) {
|
||||
return delegate.getPackageOf( type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Element> getAllMembers(TypeElement type) {
|
||||
return delegate.getAllMembers( type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e) {
|
||||
return delegate.getAllAnnotationMirrors( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hides(Element hider, Element hidden) {
|
||||
return delegate.hides( hider, hidden );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overrides(ExecutableElement overrider, ExecutableElement overridden, TypeElement type) {
|
||||
return delegate.overrides( overrider, overridden, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConstantExpression(Object value) {
|
||||
return delegate.getConstantExpression( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printElements(Writer w, Element... elements) {
|
||||
delegate.printElements( w, elements );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getName(CharSequence cs) {
|
||||
return delegate.getName( cs );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFunctionalInterface(TypeElement type) {
|
||||
return delegate.isFunctionalInterface( type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ExecutableElement> getAllEnclosedExecutableElements(TypeElement element) {
|
||||
List<ExecutableElement> enclosedElements = new ArrayList<>();
|
||||
element = replaceTypeElementIfNecessary( element );
|
||||
addEnclosedMethodsInHierarchy( enclosedElements, element, element );
|
||||
|
||||
return enclosedElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VariableElement> getAllEnclosedFields( TypeElement element) {
|
||||
List<VariableElement> enclosedElements = new ArrayList<>();
|
||||
element = replaceTypeElementIfNecessary( element );
|
||||
addEnclosedFieldsInHierarchy( enclosedElements, element, element );
|
||||
|
||||
return enclosedElements;
|
||||
}
|
||||
|
||||
private void addEnclosedMethodsInHierarchy(List<ExecutableElement> alreadyAdded, TypeElement element,
|
||||
TypeElement parentType) {
|
||||
if ( element != parentType ) { // otherwise the element was already checked for replacement
|
||||
element = replaceTypeElementIfNecessary( element );
|
||||
}
|
||||
|
||||
if ( element.asType().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
addMethodNotYetOverridden( alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
|
||||
|
||||
if ( hasNonObjectSuperclass( element ) ) {
|
||||
addEnclosedMethodsInHierarchy(
|
||||
alreadyAdded,
|
||||
asTypeElement( element.getSuperclass() ),
|
||||
parentType
|
||||
);
|
||||
}
|
||||
|
||||
for ( TypeMirror interfaceType : element.getInterfaces() ) {
|
||||
addEnclosedMethodsInHierarchy(
|
||||
alreadyAdded,
|
||||
asTypeElement( interfaceType ),
|
||||
parentType
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param alreadyCollected methods that have already been collected and to which the not-yet-overridden methods will
|
||||
* be added
|
||||
* @param methodsToAdd methods to add to alreadyAdded, if they are not yet overridden by an element in the list
|
||||
* @param parentType the type for with elements are collected
|
||||
*/
|
||||
private void addMethodNotYetOverridden(List<ExecutableElement> alreadyCollected,
|
||||
List<ExecutableElement> methodsToAdd,
|
||||
TypeElement parentType) {
|
||||
List<ExecutableElement> safeToAdd = new ArrayList<>( methodsToAdd.size() );
|
||||
for ( ExecutableElement toAdd : methodsToAdd ) {
|
||||
if ( isNotPrivate( toAdd ) && isNotObjectEquals( toAdd )
|
||||
&& methodWasNotYetOverridden( alreadyCollected, toAdd, parentType ) ) {
|
||||
safeToAdd.add( toAdd );
|
||||
}
|
||||
}
|
||||
|
||||
alreadyCollected.addAll( 0, safeToAdd );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executable the executable to check
|
||||
* @return {@code true}, iff the executable does not represent {@link java.lang.Object#equals(Object)} or an
|
||||
* overridden version of it
|
||||
*/
|
||||
private boolean isNotObjectEquals(ExecutableElement executable) {
|
||||
if ( executable.getSimpleName().contentEquals( "equals" ) && executable.getParameters().size() == 1
|
||||
&& asTypeElement( executable.getParameters().get( 0 ).asType() ).getQualifiedName().contentEquals(
|
||||
"java.lang.Object"
|
||||
) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param alreadyCollected the list of already collected methods of one type hierarchy (order is from sub-types to
|
||||
* super-types)
|
||||
* @param executable the method to check
|
||||
* @param parentType the type for which elements are collected
|
||||
* @return {@code true}, iff the given executable was not yet overridden by a method in the given list.
|
||||
*/
|
||||
private boolean methodWasNotYetOverridden(List<ExecutableElement> alreadyCollected,
|
||||
ExecutableElement executable, TypeElement parentType) {
|
||||
for ( ListIterator<ExecutableElement> it = alreadyCollected.listIterator(); it.hasNext(); ) {
|
||||
ExecutableElement executableInSubtype = it.next();
|
||||
if ( executableInSubtype == null ) {
|
||||
continue;
|
||||
}
|
||||
if ( delegate.overrides( executableInSubtype, executable, parentType ) ) {
|
||||
return false;
|
||||
}
|
||||
else if ( delegate.overrides( executable, executableInSubtype, parentType ) ) {
|
||||
// remove the method from another interface hierarchy that is overridden by the executable to add
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addEnclosedFieldsInHierarchy( List<VariableElement> alreadyAdded,
|
||||
TypeElement element, TypeElement parentType) {
|
||||
if ( element != parentType ) { // otherwise the element was already checked for replacement
|
||||
element = replaceTypeElementIfNecessary( element );
|
||||
}
|
||||
|
||||
if ( element.asType().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
addFields( alreadyAdded, fieldsIn( element.getEnclosedElements() ) );
|
||||
|
||||
if ( hasNonObjectSuperclass( element ) ) {
|
||||
addEnclosedFieldsInHierarchy(
|
||||
alreadyAdded,
|
||||
asTypeElement( element.getSuperclass() ),
|
||||
parentType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addFields(List<VariableElement> alreadyCollected, List<VariableElement> variablesToAdd) {
|
||||
List<VariableElement> safeToAdd = new ArrayList<>( variablesToAdd.size() );
|
||||
safeToAdd.addAll( variablesToAdd );
|
||||
|
||||
alreadyCollected.addAll( 0, safeToAdd );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element the type element to check
|
||||
* @return {@code true}, iff the type has a super-class that is not java.lang.Object
|
||||
*/
|
||||
private boolean hasNonObjectSuperclass(TypeElement element) {
|
||||
if ( element.getSuperclass().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
return element.getSuperclass().getKind() == TypeKind.DECLARED
|
||||
&& !asTypeElement( element.getSuperclass() ).getQualifiedName().toString().equals( "java.lang.Object" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mirror the type positionHint
|
||||
* @return the corresponding type element
|
||||
*/
|
||||
private TypeElement asTypeElement(TypeMirror mirror) {
|
||||
return (TypeElement) ( (DeclaredType) mirror ).asElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executable the executable to check
|
||||
* @return {@code true}, iff the executable does not have a private modifier
|
||||
*/
|
||||
private boolean isNotPrivate(ExecutableElement executable) {
|
||||
return !executable.getModifiers().contains( Modifier.PRIVATE );
|
||||
}
|
||||
|
||||
protected abstract TypeElement replaceTypeElementIfNecessary(TypeElement element);
|
||||
|
||||
}
|
@ -3,10 +3,9 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.internal.util.workarounds;
|
||||
package org.mapstruct.ap.internal.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
@ -21,23 +20,18 @@ import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
|
||||
/**
|
||||
* Replaces the usage of {@link Types} within MapStruct by delegating to the original implementation or to our specific
|
||||
* workarounds if necessary.
|
||||
* Replaces the usage of {@link TypeUtils} within MapStruct by delegating to the original implementation or to our
|
||||
* specific workarounds if necessary.
|
||||
*
|
||||
* @author Andreas Gudian
|
||||
*/
|
||||
public class TypesDecorator implements Types {
|
||||
private final Types delegate;
|
||||
private final ProcessingEnvironment processingEnv;
|
||||
private final VersionInformation versionInformation;
|
||||
public abstract class AbstractTypeUtilsDecorator implements TypeUtils {
|
||||
|
||||
public TypesDecorator(ProcessingEnvironment processingEnv, VersionInformation versionInformation) {
|
||||
private final Types delegate;
|
||||
|
||||
AbstractTypeUtilsDecorator(ProcessingEnvironment processingEnv) {
|
||||
this.delegate = processingEnv.getTypeUtils();
|
||||
this.processingEnv = processingEnv;
|
||||
this.versionInformation = versionInformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,12 +46,12 @@ public class TypesDecorator implements Types {
|
||||
|
||||
@Override
|
||||
public boolean isSubtype(TypeMirror t1, TypeMirror t2) {
|
||||
return SpecificCompilerWorkarounds.isSubtype( delegate, t1, t2 );
|
||||
return delegate.isSubtype( t1, t2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssignable(TypeMirror t1, TypeMirror t2) {
|
||||
return SpecificCompilerWorkarounds.isAssignable( delegate, t1, t2 );
|
||||
return delegate.isAssignable( t1, t2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,7 +71,7 @@ public class TypesDecorator implements Types {
|
||||
|
||||
@Override
|
||||
public TypeMirror erasure(TypeMirror t) {
|
||||
return SpecificCompilerWorkarounds.erasure( delegate, t );
|
||||
return delegate.erasure( t );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -132,11 +126,11 @@ public class TypesDecorator implements Types {
|
||||
|
||||
@Override
|
||||
public TypeMirror asMemberOf(DeclaredType containing, Element element) {
|
||||
return SpecificCompilerWorkarounds.asMemberOf(
|
||||
delegate,
|
||||
processingEnv,
|
||||
versionInformation,
|
||||
containing,
|
||||
element );
|
||||
return delegate.asMemberOf( containing, element );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubtypeErased(TypeMirror t1, TypeMirror t2) {
|
||||
return delegate.isSubtype( erasure( t1 ), erasure( t2 ) );
|
||||
}
|
||||
}
|
@ -6,9 +6,9 @@
|
||||
package org.mapstruct.ap.internal.util;
|
||||
|
||||
/**
|
||||
* Utilities for working with classes. It is mainly needed because using the {@link javax.lang.model.util.Elements}
|
||||
* Utilities for working with classes. It is mainly needed because using the {@link ElementUtils}
|
||||
* is not always correct. For example when compiling with JDK 9 and source version 8 classes from different modules
|
||||
* are available by {@link javax.lang.model.util.Elements#getTypeElement(CharSequence)} but they are actually not
|
||||
* are available by {@link ElementUtils#getTypeElement(CharSequence)} but they are actually not
|
||||
* if those modules are not added during compilation.
|
||||
*
|
||||
* @author Filip Hrisafov
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
public class EclipseElementUtilsDecorator extends AbstractElementUtilsDecorator {
|
||||
|
||||
private final Elements delegate;
|
||||
|
||||
EclipseElementUtilsDecorator(ProcessingEnvironment processingEnv) {
|
||||
super( processingEnv );
|
||||
this.delegate = processingEnv.getElementUtils();
|
||||
}
|
||||
|
||||
/**
|
||||
* When running during Eclipse Incremental Compilation, we might get a TypeElement that has an UnresolvedTypeBinding
|
||||
* and which is not automatically resolved. In that case, getEnclosedElements returns an empty list. We take that as
|
||||
* a hint to check if the TypeElement resolved by FQN might have any enclosed elements and, if so, return the
|
||||
* resolved element.
|
||||
*
|
||||
* @param element the original element
|
||||
* @return the element freshly resolved using the qualified name, if the original element did not return any
|
||||
* enclosed elements, whereas the resolved element does return enclosed elements.
|
||||
*/
|
||||
protected TypeElement replaceTypeElementIfNecessary(TypeElement element) {
|
||||
if ( element.getEnclosedElements().isEmpty() ) {
|
||||
TypeElement resolvedByName = delegate.getTypeElement( element.getQualifiedName() );
|
||||
if ( resolvedByName != null && !resolvedByName.getEnclosedElements().isEmpty() ) {
|
||||
return resolvedByName;
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
|
||||
public class EclipseTypeUtilsDecorator extends AbstractTypeUtilsDecorator {
|
||||
|
||||
EclipseTypeUtilsDecorator(ProcessingEnvironment processingEnv) {
|
||||
super( processingEnv );
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import java.util.List;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
|
||||
public interface ElementUtils extends Elements {
|
||||
|
||||
static ElementUtils create(ProcessingEnvironment processingEnvironment, VersionInformation info ) {
|
||||
if ( info.isEclipseJDTCompiler() ) {
|
||||
return new EclipseElementUtilsDecorator( processingEnvironment );
|
||||
}
|
||||
else {
|
||||
return new JavacElementUtilsDecorator( processingEnvironment );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all executable elements within the given type element, including executable elements defined in super
|
||||
* classes and implemented interfaces. Methods defined in {@link java.lang.Object},
|
||||
* implementations of {@link java.lang.Object#equals(Object)} and private methods are ignored
|
||||
*
|
||||
* @param element the element to inspect
|
||||
* @return the executable elements usable in the type
|
||||
*/
|
||||
List<ExecutableElement> getAllEnclosedExecutableElements(TypeElement element);
|
||||
|
||||
/**
|
||||
* Finds all variable elements within the given type element, including variable
|
||||
* elements defined in super classes and implemented interfaces and including the fields in the .
|
||||
*
|
||||
* @param element the element to inspect
|
||||
* @return the executable elements usable in the type
|
||||
*/
|
||||
List<VariableElement> getAllEnclosedFields(TypeElement element);
|
||||
}
|
@ -7,24 +7,12 @@ package org.mapstruct.ap.internal.util;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.AfterMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.BeforeMappingGem;
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
|
||||
|
||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||
import static org.mapstruct.ap.internal.util.workarounds.SpecificCompilerWorkarounds.replaceTypeElementIfNecessary;
|
||||
|
||||
/**
|
||||
* Provides functionality around {@link ExecutableElement}s.
|
||||
@ -74,151 +62,6 @@ public class Executables {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mirror the type positionHint
|
||||
*
|
||||
* @return the corresponding type element
|
||||
*/
|
||||
private static TypeElement asTypeElement(TypeMirror mirror) {
|
||||
return (TypeElement) ( (DeclaredType) mirror ).asElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all executable elements within the given type element, including executable elements defined in super
|
||||
* classes and implemented interfaces. Methods defined in {@link java.lang.Object},
|
||||
* implementations of {@link java.lang.Object#equals(Object)} and private methods are ignored
|
||||
*
|
||||
* @param elementUtils element helper
|
||||
* @param element the element to inspect
|
||||
*
|
||||
* @return the executable elements usable in the type
|
||||
*/
|
||||
public static List<ExecutableElement> getAllEnclosedExecutableElements(Elements elementUtils, TypeElement element) {
|
||||
List<ExecutableElement> enclosedElements = new ArrayList<>();
|
||||
element = replaceTypeElementIfNecessary( elementUtils, element );
|
||||
addEnclosedElementsInHierarchy( elementUtils, enclosedElements, element, element );
|
||||
|
||||
return enclosedElements;
|
||||
}
|
||||
|
||||
private static void addEnclosedElementsInHierarchy(Elements elementUtils, List<ExecutableElement> alreadyAdded,
|
||||
TypeElement element, TypeElement parentType) {
|
||||
if ( element != parentType ) { // otherwise the element was already checked for replacement
|
||||
element = replaceTypeElementIfNecessary( elementUtils, element );
|
||||
}
|
||||
|
||||
if ( element.asType().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
addNotYetOverridden( elementUtils, alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
|
||||
|
||||
if ( hasNonObjectSuperclass( element ) ) {
|
||||
addEnclosedElementsInHierarchy(
|
||||
elementUtils,
|
||||
alreadyAdded,
|
||||
asTypeElement( element.getSuperclass() ),
|
||||
parentType
|
||||
);
|
||||
}
|
||||
|
||||
for ( TypeMirror interfaceType : element.getInterfaces() ) {
|
||||
addEnclosedElementsInHierarchy(
|
||||
elementUtils,
|
||||
alreadyAdded,
|
||||
asTypeElement( interfaceType ),
|
||||
parentType
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param alreadyCollected methods that have already been collected and to which the not-yet-overridden methods will
|
||||
* be added
|
||||
* @param methodsToAdd methods to add to alreadyAdded, if they are not yet overridden by an element in the list
|
||||
* @param parentType the type for with elements are collected
|
||||
*/
|
||||
private static void addNotYetOverridden(Elements elementUtils, List<ExecutableElement> alreadyCollected,
|
||||
List<ExecutableElement> methodsToAdd, TypeElement parentType) {
|
||||
List<ExecutableElement> safeToAdd = new ArrayList<>( methodsToAdd.size() );
|
||||
for ( ExecutableElement toAdd : methodsToAdd ) {
|
||||
if ( isNotPrivate( toAdd ) && isNotObjectEquals( toAdd )
|
||||
&& wasNotYetOverridden( elementUtils, alreadyCollected, toAdd, parentType ) ) {
|
||||
safeToAdd.add( toAdd );
|
||||
}
|
||||
}
|
||||
|
||||
alreadyCollected.addAll( 0, safeToAdd );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executable the executable to check
|
||||
*
|
||||
* @return {@code true}, iff the executable does not represent {@link java.lang.Object#equals(Object)} or an
|
||||
* overridden version of it
|
||||
*/
|
||||
private static boolean isNotObjectEquals(ExecutableElement executable) {
|
||||
if ( executable.getSimpleName().contentEquals( "equals" ) && executable.getParameters().size() == 1
|
||||
&& asTypeElement( executable.getParameters().get( 0 ).asType() ).getQualifiedName().contentEquals(
|
||||
"java.lang.Object"
|
||||
) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executable the executable to check
|
||||
*
|
||||
* @return {@code true}, iff the executable does not have a private modifier
|
||||
*/
|
||||
private static boolean isNotPrivate(ExecutableElement executable) {
|
||||
return !executable.getModifiers().contains( Modifier.PRIVATE );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param elementUtils the elementUtils
|
||||
* @param alreadyCollected the list of already collected methods of one type hierarchy (order is from sub-types to
|
||||
* super-types)
|
||||
* @param executable the method to check
|
||||
* @param parentType the type for which elements are collected
|
||||
* @return {@code true}, iff the given executable was not yet overridden by a method in the given list.
|
||||
*/
|
||||
private static boolean wasNotYetOverridden(Elements elementUtils, List<ExecutableElement> alreadyCollected,
|
||||
ExecutableElement executable, TypeElement parentType) {
|
||||
for ( ListIterator<ExecutableElement> it = alreadyCollected.listIterator(); it.hasNext(); ) {
|
||||
ExecutableElement executableInSubtype = it.next();
|
||||
if ( executableInSubtype == null ) {
|
||||
continue;
|
||||
}
|
||||
if ( elementUtils.overrides( executableInSubtype, executable, parentType ) ) {
|
||||
return false;
|
||||
}
|
||||
else if ( elementUtils.overrides( executable, executableInSubtype, parentType ) ) {
|
||||
// remove the method from another interface hierarchy that is overridden by the executable to add
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element the type element to check
|
||||
*
|
||||
* @return {@code true}, iff the type has a super-class that is not java.lang.Object
|
||||
*/
|
||||
private static boolean hasNonObjectSuperclass(TypeElement element) {
|
||||
if ( element.getSuperclass().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
return element.getSuperclass().getKind() == TypeKind.DECLARED
|
||||
&& !asTypeElement( element.getSuperclass() ).getQualifiedName().toString().equals( "java.lang.Object" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executableElement the element to check
|
||||
* @return {@code true}, if the executable element is a method annotated with {@code @BeforeMapping} or
|
||||
|
@ -5,21 +5,15 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
|
||||
|
||||
import static javax.lang.model.util.ElementFilter.fieldsIn;
|
||||
import static org.mapstruct.ap.internal.util.workarounds.SpecificCompilerWorkarounds.replaceTypeElementIfNecessary;
|
||||
|
||||
/**
|
||||
* Provides functionality around {@link VariableElement}s.
|
||||
*
|
||||
@ -42,53 +36,6 @@ public class Fields {
|
||||
return !method.getModifiers().contains( Modifier.STATIC );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all variable elements within the given type element, including variable
|
||||
* elements defined in super classes and implemented interfaces and including the fields in the .
|
||||
*
|
||||
* @param elementUtils element helper
|
||||
* @param element the element to inspect
|
||||
*
|
||||
* @return the executable elements usable in the type
|
||||
*/
|
||||
public static List<VariableElement> getAllEnclosedFields(Elements elementUtils, TypeElement element) {
|
||||
List<VariableElement> enclosedElements = new ArrayList<>();
|
||||
element = replaceTypeElementIfNecessary( elementUtils, element );
|
||||
addEnclosedElementsInHierarchy( elementUtils, enclosedElements, element, element );
|
||||
|
||||
return enclosedElements;
|
||||
}
|
||||
|
||||
private static void addEnclosedElementsInHierarchy(Elements elementUtils, List<VariableElement> alreadyAdded,
|
||||
TypeElement element, TypeElement parentType) {
|
||||
if ( element != parentType ) { // otherwise the element was already checked for replacement
|
||||
element = replaceTypeElementIfNecessary( elementUtils, element );
|
||||
}
|
||||
|
||||
if ( element.asType().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
addFields( alreadyAdded, fieldsIn( element.getEnclosedElements() ) );
|
||||
|
||||
|
||||
if ( hasNonObjectSuperclass( element ) ) {
|
||||
addEnclosedElementsInHierarchy(
|
||||
elementUtils,
|
||||
alreadyAdded,
|
||||
asTypeElement( element.getSuperclass() ),
|
||||
parentType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addFields(List<VariableElement> alreadyCollected, List<VariableElement> variablesToAdd) {
|
||||
List<VariableElement> safeToAdd = new ArrayList<>( variablesToAdd.size() );
|
||||
safeToAdd.addAll( variablesToAdd );
|
||||
|
||||
alreadyCollected.addAll( 0, safeToAdd );
|
||||
}
|
||||
|
||||
private static TypeElement asTypeElement(TypeMirror mirror) {
|
||||
return (TypeElement) ( (DeclaredType) mirror ).asElement();
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.ExecutableType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.ExecutableElementAccessor;
|
||||
@ -60,10 +59,10 @@ public class Filters {
|
||||
}
|
||||
|
||||
private final AccessorNamingUtils accessorNaming;
|
||||
private final Types typeUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
private final TypeMirror typeMirror;
|
||||
|
||||
public Filters(AccessorNamingUtils accessorNaming, Types typeUtils, TypeMirror typeMirror) {
|
||||
public Filters(AccessorNamingUtils accessorNaming, TypeUtils typeUtils, TypeMirror typeMirror) {
|
||||
this.accessorNaming = accessorNaming;
|
||||
this.typeUtils = typeUtils;
|
||||
this.typeMirror = typeMirror;
|
||||
|
@ -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.internal.util;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
public class JavacElementUtilsDecorator extends AbstractElementUtilsDecorator {
|
||||
|
||||
JavacElementUtilsDecorator(ProcessingEnvironment processingEnv) {
|
||||
super( processingEnv );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeElement replaceTypeElementIfNecessary(TypeElement element) {
|
||||
return element;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
|
||||
public class JavacTypeUtilsDecorator extends AbstractTypeUtilsDecorator {
|
||||
|
||||
JavacTypeUtilsDecorator(ProcessingEnvironment processingEnv) {
|
||||
super( processingEnv );
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
|
||||
public interface TypeUtils extends Types {
|
||||
|
||||
static TypeUtils create(ProcessingEnvironment processingEnvironment, VersionInformation info ) {
|
||||
if ( info.isEclipseJDTCompiler() ) {
|
||||
return new EclipseTypeUtilsDecorator( processingEnvironment );
|
||||
}
|
||||
else {
|
||||
return new JavacTypeUtilsDecorator( processingEnvironment );
|
||||
}
|
||||
}
|
||||
|
||||
boolean isSubtypeErased(TypeMirror t1, TypeMirror t2);
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* 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.internal.util.workarounds;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.eclipse.jdt.core.compiler.CharOperation;
|
||||
import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl;
|
||||
import org.eclipse.jdt.internal.compiler.apt.model.ElementImpl;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
|
||||
|
||||
/**
|
||||
* Contains the workaround for {@link Types#asMemberOf(DeclaredType, Element)} using Eclipse implementation types.
|
||||
* <p>
|
||||
* <strong>This class may only be accessed through {@link EclipseClassLoaderBridge} when running within Eclipse</strong>
|
||||
*
|
||||
* @author Andreas Gudian
|
||||
*/
|
||||
final class EclipseAsMemberOfWorkaround {
|
||||
private EclipseAsMemberOfWorkaround() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Eclipse-specific implementation of {@link Types#asMemberOf(DeclaredType, Element)}.
|
||||
* <p>
|
||||
* Returns {@code null} if the implementation could not determine the result.
|
||||
*/
|
||||
static TypeMirror asMemberOf(ProcessingEnvironment environment, DeclaredType containing,
|
||||
Element element) {
|
||||
|
||||
ElementImpl elementImpl = tryCast( element, ElementImpl.class );
|
||||
BaseProcessingEnvImpl env = tryCast( environment, BaseProcessingEnvImpl.class );
|
||||
|
||||
if ( elementImpl == null || env == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ReferenceBinding referenceBinding =
|
||||
(ReferenceBinding) ( (ElementImpl) environment.getTypeUtils().asElement( containing ) )._binding;
|
||||
|
||||
MethodBinding methodBinding = (MethodBinding) elementImpl._binding;
|
||||
|
||||
// matches in super-classes have priority
|
||||
MethodBinding inSuperclassHiearchy = findInSuperclassHierarchy( methodBinding, referenceBinding );
|
||||
|
||||
if ( inSuperclassHiearchy != null ) {
|
||||
return env.getFactory().newTypeMirror( inSuperclassHiearchy );
|
||||
}
|
||||
|
||||
// if nothing was found, traverse the interfaces and collect all candidate methods that match
|
||||
List<MethodBinding> candidatesFromInterfaces = new ArrayList<>();
|
||||
|
||||
collectFromInterfaces(
|
||||
methodBinding,
|
||||
referenceBinding,
|
||||
new HashSet<>(),
|
||||
candidatesFromInterfaces );
|
||||
|
||||
// there can be multiple matches for the same method name from adjacent interface hierarchies.
|
||||
candidatesFromInterfaces.sort( MostSpecificMethodBindingComparator.INSTANCE );
|
||||
|
||||
if ( !candidatesFromInterfaces.isEmpty() ) {
|
||||
// return the most specific match
|
||||
return env.getFactory().newTypeMirror( candidatesFromInterfaces.get( 0 ) );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <T> T tryCast(Object instance, Class<T> type) {
|
||||
if ( type.isInstance( instance ) ) {
|
||||
return type.cast( instance );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void collectFromInterfaces(MethodBinding methodBinding, ReferenceBinding typeBinding,
|
||||
Set<ReferenceBinding> visitedTypes, List<MethodBinding> found) {
|
||||
if ( typeBinding == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// also check the interfaces of the superclass hierarchy (the superclasses themselves don't contain a match,
|
||||
// we checked that already)
|
||||
collectFromInterfaces( methodBinding, typeBinding.superclass(), visitedTypes, found );
|
||||
|
||||
for ( ReferenceBinding ifc : typeBinding.superInterfaces() ) {
|
||||
if ( visitedTypes.contains( ifc ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
visitedTypes.add( ifc );
|
||||
|
||||
// finding a match in one interface
|
||||
MethodBinding f = findMatchingMethodBinding( methodBinding, ifc.methods() );
|
||||
|
||||
if ( f == null ) {
|
||||
collectFromInterfaces( methodBinding, ifc, visitedTypes, found );
|
||||
}
|
||||
else {
|
||||
// no need for recursion if we found a candidate in this type already
|
||||
found.add( f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param baseMethod binding to compare against
|
||||
* @param methods the candidate methods
|
||||
* @return The method from the list of candidates that matches the name and original/erasure of
|
||||
* {@code methodBinding}, or {@code null} if none was found.
|
||||
*/
|
||||
private static MethodBinding findMatchingMethodBinding(MethodBinding baseMethod, MethodBinding[] methods) {
|
||||
for ( MethodBinding method : methods ) {
|
||||
if ( CharOperation.equals( method.selector, baseMethod.selector )
|
||||
&& ( method.original() == baseMethod || method.areParameterErasuresEqual( baseMethod ) ) ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static MethodBinding findInSuperclassHierarchy(MethodBinding baseMethod, ReferenceBinding typeBinding) {
|
||||
while ( typeBinding != null ) {
|
||||
MethodBinding matching = findMatchingMethodBinding( baseMethod, typeBinding.methods() );
|
||||
if ( matching != null ) {
|
||||
return matching;
|
||||
}
|
||||
|
||||
typeBinding = typeBinding.superclass();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares MethodBindings by their signature: the more specific method is considered <em>lower</em>.
|
||||
*
|
||||
* @author Andreas Gudian
|
||||
*/
|
||||
private static final class MostSpecificMethodBindingComparator implements Comparator<MethodBinding> {
|
||||
private static final MostSpecificMethodBindingComparator INSTANCE = new MostSpecificMethodBindingComparator();
|
||||
|
||||
@Override
|
||||
public int compare(MethodBinding first, MethodBinding second) {
|
||||
boolean firstParamsAssignableFromSecond =
|
||||
first.areParametersCompatibleWith( second.parameters );
|
||||
boolean secondParamsAssignableFromFirst =
|
||||
second.areParametersCompatibleWith( first.parameters );
|
||||
|
||||
if ( firstParamsAssignableFromSecond != secondParamsAssignableFromFirst ) {
|
||||
return firstParamsAssignableFromSecond ? 1 : -1;
|
||||
}
|
||||
|
||||
if ( TypeBinding.equalsEquals( first.returnType, second.returnType ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean firstReturnTypeAssignableFromSecond =
|
||||
second.returnType.isCompatibleWith( first.returnType );
|
||||
|
||||
return firstReturnTypeAssignableFromSecond ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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.internal.util.workarounds;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
|
||||
/**
|
||||
* In Eclipse 4.6, the ClassLoader of the annotation processor does not provide access to the implementation types of
|
||||
* the APT-API anymore, so we need to create a new ClassLoader containing the processor class path URLs and having the
|
||||
* ClassLoader of the APT-API implementations as parent. The method invocation then consequently needs to be done via
|
||||
* reflection.
|
||||
*
|
||||
* @author Andreas Gudian
|
||||
*/
|
||||
class EclipseClassLoaderBridge {
|
||||
private static final String ECLIPSE_AS_MEMBER_OF_WORKAROUND =
|
||||
"org.mapstruct.ap.internal.util.workarounds.EclipseAsMemberOfWorkaround";
|
||||
|
||||
private static ClassLoader classLoader;
|
||||
private static Method asMemberOf;
|
||||
|
||||
private EclipseClassLoaderBridge() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes {@link EclipseAsMemberOfWorkaround#asMemberOf(ProcessingEnvironment, DeclaredType, Element)} via
|
||||
* reflection using a special ClassLoader.
|
||||
*/
|
||||
static TypeMirror invokeAsMemberOfWorkaround(ProcessingEnvironment env, DeclaredType containing, Element element)
|
||||
throws Exception {
|
||||
return (TypeMirror) getAsMemberOf( element.getClass().getClassLoader() ).invoke(
|
||||
null,
|
||||
env,
|
||||
containing,
|
||||
element );
|
||||
}
|
||||
|
||||
private static ClassLoader getOrCreateClassLoader(ClassLoader parent) {
|
||||
if ( classLoader == null ) {
|
||||
classLoader = new URLClassLoader(
|
||||
( (URLClassLoader) EclipseClassLoaderBridge.class.getClassLoader() ).getURLs(),
|
||||
parent );
|
||||
}
|
||||
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
private static Method getAsMemberOf(ClassLoader platformClassLoader) throws Exception {
|
||||
if ( asMemberOf == null ) {
|
||||
Class<?> workaroundClass =
|
||||
getOrCreateClassLoader( platformClassLoader ).loadClass( ECLIPSE_AS_MEMBER_OF_WORKAROUND );
|
||||
|
||||
Method found = workaroundClass.getDeclaredMethod(
|
||||
"asMemberOf",
|
||||
ProcessingEnvironment.class,
|
||||
DeclaredType.class,
|
||||
Element.class );
|
||||
|
||||
found.setAccessible( true );
|
||||
|
||||
asMemberOf = found;
|
||||
}
|
||||
|
||||
return asMemberOf;
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* 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.internal.util.workarounds;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
|
||||
/**
|
||||
* Contains workarounds for various quirks in specific compilers.
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
* @author Andreas Gudian
|
||||
*/
|
||||
public class SpecificCompilerWorkarounds {
|
||||
private SpecificCompilerWorkarounds() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether one type is assignable to another, checking for VOID first.
|
||||
*
|
||||
* @param types the type utils
|
||||
* @param t1 the first type
|
||||
* @param t2 the second type
|
||||
* @return {@code true} if and only if the first type is assignable to the second
|
||||
* @throws IllegalArgumentException if given an executable or package type
|
||||
*/
|
||||
static boolean isAssignable(Types types, TypeMirror t1, TypeMirror t2) {
|
||||
if ( t1.getKind() == TypeKind.VOID ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return types.isAssignable( t1, t2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param t2 the second type
|
||||
* @return {@code true} if and only if the first type is a subtype of the second
|
||||
* @throws IllegalArgumentException if given an executable or package type
|
||||
*/
|
||||
static boolean isSubtype(Types types, TypeMirror t1, TypeMirror 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. See the
|
||||
* JLS, section 4.6 Type Erasure, for reference.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
static TypeMirror erasure(Types types, TypeMirror t) {
|
||||
if ( t.getKind() == TypeKind.VOID || t.getKind() == TypeKind.NULL ) {
|
||||
return t;
|
||||
}
|
||||
else {
|
||||
return types.erasure( t );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When running during Eclipse Incremental Compilation, we might get a TypeElement that has an UnresolvedTypeBinding
|
||||
* and which is not automatically resolved. In that case, getEnclosedElements returns an empty list. We take that as
|
||||
* a hint to check if the TypeElement resolved by FQN might have any enclosed elements and, if so, return the
|
||||
* resolved element.
|
||||
*
|
||||
* @param elementUtils element utils
|
||||
* @param element the original element
|
||||
* @return the element freshly resolved using the qualified name, if the original element did not return any
|
||||
* enclosed elements, whereas the resolved element does return enclosed elements.
|
||||
*/
|
||||
public static TypeElement replaceTypeElementIfNecessary(Elements elementUtils, TypeElement element) {
|
||||
if ( element.getEnclosedElements().isEmpty() ) {
|
||||
TypeElement resolvedByName = elementUtils.getTypeElement( element.getQualifiedName() );
|
||||
if ( resolvedByName != null && !resolvedByName.getEnclosedElements().isEmpty() ) {
|
||||
return resolvedByName;
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for Bugs in the Eclipse implementation of {@link Types#asMemberOf(DeclaredType, Element)}.
|
||||
*
|
||||
* @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=382590">Eclipse Bug 382590 (fixed in Eclipse 4.6)</a>
|
||||
* @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=481555">Eclipse Bug 481555</a>
|
||||
*/
|
||||
static TypeMirror asMemberOf(Types typeUtils, ProcessingEnvironment env, VersionInformation versionInformation,
|
||||
DeclaredType containing, Element element) {
|
||||
TypeMirror result = null;
|
||||
Exception lastException = null;
|
||||
try {
|
||||
try {
|
||||
result = typeUtils.asMemberOf( containing, element );
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
lastException = e;
|
||||
if ( versionInformation.isEclipseJDTCompiler() ) {
|
||||
result = EclipseClassLoaderBridge.invokeAsMemberOfWorkaround( env, containing, element );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
lastException = e;
|
||||
}
|
||||
|
||||
if ( null == result ) {
|
||||
throw new RuntimeException( "Fallback implementation of asMemberOf didn't work for "
|
||||
+ element + " in " + containing, lastException );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -23,9 +23,9 @@ import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVisitor;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ -73,7 +73,12 @@ public class SelectionParametersTest {
|
||||
}
|
||||
}
|
||||
|
||||
private final Types typeUtils = new Types() {
|
||||
private final TypeUtils typeUtils = new TypeUtils() {
|
||||
@Override
|
||||
public boolean isSubtypeErased(TypeMirror t1, TypeMirror t2) {
|
||||
throw new UnsupportedOperationException( "isSubTypeErased is not supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element asElement(TypeMirror t) {
|
||||
throw new UnsupportedOperationException( "asElement is not supported" );
|
||||
|
Loading…
x
Reference in New Issue
Block a user