From c2e803403027f3fae92bd15b0ba50ab7df5063e6 Mon Sep 17 00:00:00 2001 From: Sjaak Derksen Date: Wed, 21 Oct 2020 20:02:28 +0200 Subject: [PATCH] 861 remove compiler specific workarounds (#2227) --- .../ap/internal/model/GeneratedType.java | 6 +- .../internal/model/MappingBuilderContext.java | 16 +- .../ap/internal/model/ValueMappingMethod.java | 4 +- .../ap/internal/model/common/BuilderType.java | 4 +- .../ap/internal/model/common/Type.java | 25 +- .../ap/internal/model/common/TypeFactory.java | 20 +- .../model/source/BeanMappingOptions.java | 8 +- .../internal/model/source/DefaultOptions.java | 4 +- .../model/source/DelegatingOptions.java | 4 +- .../model/source/IterableMappingOptions.java | 8 +- .../model/source/MapMappingOptions.java | 11 +- .../model/source/MapperConfigOptions.java | 4 +- .../internal/model/source/MapperOptions.java | 4 +- .../internal/model/source/MappingControl.java | 8 +- .../internal/model/source/MappingOptions.java | 11 +- .../internal/model/source/MethodMatcher.java | 16 +- .../model/source/SelectionParameters.java | 8 +- .../internal/model/source/SourceMethod.java | 8 +- .../source/selector/MethodSelectors.java | 6 +- .../source/selector/QualifierSelector.java | 8 +- .../source/selector/TargetTypeSelector.java | 6 +- .../selector/XmlElementDeclSelector.java | 6 +- .../DefaultModelElementProcessorContext.java | 19 +- .../processor/MapperCreationProcessor.java | 8 +- .../processor/MethodRetrievalProcessor.java | 30 +- .../processor/ModelElementProcessor.java | 10 +- .../creation/MappingResolverImpl.java | 8 +- .../util/AbstractElementUtilsDecorator.java | 286 ++++++++++++++++++ ...r.java => AbstractTypeUtilsDecorator.java} | 38 +-- .../ap/internal/util/ClassUtils.java | 4 +- .../util/EclipseElementUtilsDecorator.java | 40 +++ .../util/EclipseTypeUtilsDecorator.java | 15 + .../ap/internal/util/ElementUtils.java | 46 +++ .../ap/internal/util/Executables.java | 157 ---------- .../mapstruct/ap/internal/util/Fields.java | 53 ---- .../mapstruct/ap/internal/util/Filters.java | 5 +- .../util/JavacElementUtilsDecorator.java | 21 ++ .../util/JavacTypeUtilsDecorator.java | 15 + .../mapstruct/ap/internal/util/TypeUtils.java | 26 ++ .../EclipseAsMemberOfWorkaround.java | 182 ----------- .../workarounds/EclipseClassLoaderBridge.java | 75 ----- .../SpecificCompilerWorkarounds.java | 140 --------- .../model/source/SelectionParametersTest.java | 9 +- 43 files changed, 611 insertions(+), 771 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/AbstractElementUtilsDecorator.java rename processor/src/main/java/org/mapstruct/ap/internal/util/{workarounds/TypesDecorator.java => AbstractTypeUtilsDecorator.java} (75%) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/EclipseElementUtilsDecorator.java create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/EclipseTypeUtilsDecorator.java create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/ElementUtils.java create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/JavacElementUtilsDecorator.java create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/JavacTypeUtilsDecorator.java create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/TypeUtils.java delete mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseAsMemberOfWorkaround.java delete mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseClassLoaderBridge.java delete mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/SpecificCompilerWorkarounds.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java index a03f9af9a..a6f573d4f 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java @@ -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 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; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java index 8da5cb508..46e1d4ee4 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java @@ -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; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java index 9c7272f2b..c26dd5df6 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/ValueMappingMethod.java @@ -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 qualifiers = beanMapping.qualifiedBy().get(); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/BuilderType.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/BuilderType.java index 1b34f4698..b94bb82ef 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/BuilderType.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/BuilderType.java @@ -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; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java index b2b12b8a2..910af60d4 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java @@ -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 { - 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 { 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 typeParameters, ImplementationType implementationType, Type componentType, @@ -662,7 +661,7 @@ public class Type extends ModelElement implements Comparable { private List 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 { private List 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 { 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 { 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 { private static class TypeVarMatcher extends SimpleTypeVisitor8 { 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; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java index ba1dcc192..8d3d215c5 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java @@ -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 notToBeImportedTypes, boolean loggingVerbose) { + public TypeFactory(ElementUtils elementUtils, TypeUtils typeUtils, FormattingMessager messager, + RoundContext roundContext, Map 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; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java index d8fd67510..d600ed0fc 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java @@ -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 ) diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/DefaultOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/DefaultOptions.java index 81f870e25..4d80bf57b 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/DefaultOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/DefaultOptions.java @@ -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 ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java index c45868198..564358ec9 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java @@ -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 ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMappingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMappingOptions.java index 73ae1907c..40b5b2535 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMappingOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMappingOptions.java @@ -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 ) diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMappingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMappingOptions.java index 96ff577f4..c35a8e363 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMappingOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMappingOptions.java @@ -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 ) diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperConfigOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperConfigOptions.java index 07f668e65..7f8df7bf4 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperConfigOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperConfigOptions.java @@ -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 ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperOptions.java index b054c628a..b916cd2de 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapperOptions.java @@ -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 ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingControl.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingControl.java index fc896bb52..ab2957086 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingControl.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingControl.java @@ -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 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() ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingOptions.java index b826295f7..9db1b1c04 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingOptions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingOptions.java @@ -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 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 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 ) diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java index 2c509924c..ea3f72044 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java @@ -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: 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; } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java index ed6851d9a..a78409582 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java @@ -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 qualifiers; private final List 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 qualifiers, List qualifyingNames, TypeMirror resultType, - Types typeUtils) { + TypeUtils typeUtils) { this( qualifiers, qualifyingNames, resultType, typeUtils, null ); } private SelectionParameters(List qualifiers, List qualifyingNames, TypeMirror resultType, - Types typeUtils, SourceRHS sourceRHS) { + TypeUtils typeUtils, SourceRHS sourceRHS) { this.qualifiers = qualifiers; this.qualifyingNames = qualifyingNames; this.resultType = resultType; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java index 98cffb4c3..bac1346d9 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java @@ -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 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; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java index 5bfbe8449..74fedcb75 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java @@ -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 selectors; - public MethodSelectors(Types typeUtils, Elements elementUtils, TypeFactory typeFactory, + public MethodSelectors(TypeUtils typeUtils, ElementUtils elementUtils, TypeFactory typeFactory, FormattingMessager messager) { selectors = Arrays.asList( new MethodFamilySelector(), diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/QualifierSelector.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/QualifierSelector.java index 27ad9eb60..bca471f9c 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/QualifierSelector.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/QualifierSelector.java @@ -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(); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/TargetTypeSelector.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/TargetTypeSelector.java index 1cbcb6927..ad1a5d47b 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/TargetTypeSelector.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/TargetTypeSelector.java @@ -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; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java index c3c394aef..ecf665799 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java @@ -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; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java index 1514f4f5e..d6a05cec3 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java @@ -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 diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java index 25632350b..a0014f593 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java @@ -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, Mapper> { - private Elements elementUtils; - private Types typeUtils; + private ElementUtils elementUtils; + private TypeUtils typeUtils; private FormattingMessager messager; private Options options; private VersionInformation versionInformation; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/MethodRetrievalProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/MethodRetrievalProcessor.java index 059a000bc..693741bcd 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/MethodRetrievalProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/MethodRetrievalProcessor.java @@ -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 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 methods = new ArrayList<>(); - for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, typeElement ) ) { + for ( ExecutableElement executable : elementUtils.getAllEnclosedExecutableElements( typeElement ) ) { ExecutableType methodType = typeFactory.getMethodType( mapperAnnotation.mapperConfigType(), executable ); List parameters = typeFactory.getParameters( methodType, executable ); @@ -160,7 +158,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor prototypeMethods) { List methods = new ArrayList<>(); - for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, usedMapper ) ) { + for ( ExecutableElement executable : elementUtils.getAllEnclosedExecutableElements( usedMapper ) ) { SourceMethod method = getMethod( usedMapper, executable, diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/ModelElementProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/ModelElementProcessor.java index ac0a161a2..d43b52953 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/ModelElementProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/ModelElementProcessor.java @@ -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 { /** * 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 { Filer getFiler(); - Types getTypeUtils(); + TypeUtils getTypeUtils(); - Elements getElementUtils(); + ElementUtils getElementUtils(); TypeFactory getTypeFactory(); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java index 73392a00f..debe8f30d 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java @@ -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 sourceModel; @@ -98,7 +98,7 @@ public class MappingResolverImpl implements MappingResolver { */ private final Set usedSupportedMappings = new HashSet<>(); - public MappingResolverImpl(FormattingMessager messager, Elements elementUtils, Types typeUtils, + public MappingResolverImpl(FormattingMessager messager, ElementUtils elementUtils, TypeUtils typeUtils, TypeFactory typeFactory, List sourceModel, List mapperReferences, boolean verboseLogging) { this.messager = messager; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/AbstractElementUtilsDecorator.java b/processor/src/main/java/org/mapstruct/ap/internal/util/AbstractElementUtilsDecorator.java new file mode 100644 index 000000000..8239dcb41 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/AbstractElementUtilsDecorator.java @@ -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 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 getAllMembers(TypeElement type) { + return delegate.getAllMembers( type ); + } + + @Override + public List 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 getAllEnclosedExecutableElements(TypeElement element) { + List enclosedElements = new ArrayList<>(); + element = replaceTypeElementIfNecessary( element ); + addEnclosedMethodsInHierarchy( enclosedElements, element, element ); + + return enclosedElements; + } + + @Override + public List getAllEnclosedFields( TypeElement element) { + List enclosedElements = new ArrayList<>(); + element = replaceTypeElementIfNecessary( element ); + addEnclosedFieldsInHierarchy( enclosedElements, element, element ); + + return enclosedElements; + } + + private void addEnclosedMethodsInHierarchy(List 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 alreadyCollected, + List methodsToAdd, + TypeElement parentType) { + List 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 alreadyCollected, + ExecutableElement executable, TypeElement parentType) { + for ( ListIterator 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 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 alreadyCollected, List variablesToAdd) { + List 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); + +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/TypesDecorator.java b/processor/src/main/java/org/mapstruct/ap/internal/util/AbstractTypeUtilsDecorator.java similarity index 75% rename from processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/TypesDecorator.java rename to processor/src/main/java/org/mapstruct/ap/internal/util/AbstractTypeUtilsDecorator.java index 097ab5263..2f7c4d604 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/TypesDecorator.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/AbstractTypeUtilsDecorator.java @@ -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 ) ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/ClassUtils.java b/processor/src/main/java/org/mapstruct/ap/internal/util/ClassUtils.java index 889b72931..d66d81f9b 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/ClassUtils.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/ClassUtils.java @@ -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 diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/EclipseElementUtilsDecorator.java b/processor/src/main/java/org/mapstruct/ap/internal/util/EclipseElementUtilsDecorator.java new file mode 100644 index 000000000..aaf1bb7e2 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/EclipseElementUtilsDecorator.java @@ -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; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/EclipseTypeUtilsDecorator.java b/processor/src/main/java/org/mapstruct/ap/internal/util/EclipseTypeUtilsDecorator.java new file mode 100644 index 000000000..ce01d99de --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/EclipseTypeUtilsDecorator.java @@ -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 ); + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/ElementUtils.java b/processor/src/main/java/org/mapstruct/ap/internal/util/ElementUtils.java new file mode 100644 index 000000000..fdd221c1a --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/ElementUtils.java @@ -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 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 getAllEnclosedFields(TypeElement element); +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java index b6de4662b..1592a39fd 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java @@ -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 getAllEnclosedExecutableElements(Elements elementUtils, TypeElement element) { - List enclosedElements = new ArrayList<>(); - element = replaceTypeElementIfNecessary( elementUtils, element ); - addEnclosedElementsInHierarchy( elementUtils, enclosedElements, element, element ); - - return enclosedElements; - } - - private static void addEnclosedElementsInHierarchy(Elements elementUtils, List 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 alreadyCollected, - List methodsToAdd, TypeElement parentType) { - List 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 alreadyCollected, - ExecutableElement executable, TypeElement parentType) { - for ( ListIterator 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 diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Fields.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Fields.java index f394f4e8f..8e16a9527 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Fields.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Fields.java @@ -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 getAllEnclosedFields(Elements elementUtils, TypeElement element) { - List enclosedElements = new ArrayList<>(); - element = replaceTypeElementIfNecessary( elementUtils, element ); - addEnclosedElementsInHierarchy( elementUtils, enclosedElements, element, element ); - - return enclosedElements; - } - - private static void addEnclosedElementsInHierarchy(Elements elementUtils, List 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 alreadyCollected, List variablesToAdd) { - List safeToAdd = new ArrayList<>( variablesToAdd.size() ); - safeToAdd.addAll( variablesToAdd ); - - alreadyCollected.addAll( 0, safeToAdd ); - } - private static TypeElement asTypeElement(TypeMirror mirror) { return (TypeElement) ( (DeclaredType) mirror ).asElement(); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java index f4d52d709..9cb923b3c 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java @@ -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; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/JavacElementUtilsDecorator.java b/processor/src/main/java/org/mapstruct/ap/internal/util/JavacElementUtilsDecorator.java new file mode 100644 index 000000000..ad035743c --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/JavacElementUtilsDecorator.java @@ -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; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/JavacTypeUtilsDecorator.java b/processor/src/main/java/org/mapstruct/ap/internal/util/JavacTypeUtilsDecorator.java new file mode 100644 index 000000000..8b3454e87 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/JavacTypeUtilsDecorator.java @@ -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 ); + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/TypeUtils.java b/processor/src/main/java/org/mapstruct/ap/internal/util/TypeUtils.java new file mode 100644 index 000000000..926cd5eef --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/TypeUtils.java @@ -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); +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseAsMemberOfWorkaround.java b/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseAsMemberOfWorkaround.java deleted file mode 100644 index ab0d68172..000000000 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseAsMemberOfWorkaround.java +++ /dev/null @@ -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. - *

- * This class may only be accessed through {@link EclipseClassLoaderBridge} when running within Eclipse - * - * @author Andreas Gudian - */ -final class EclipseAsMemberOfWorkaround { - private EclipseAsMemberOfWorkaround() { - } - - /** - * Eclipse-specific implementation of {@link Types#asMemberOf(DeclaredType, Element)}. - *

- * 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 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 tryCast(Object instance, Class type) { - if ( type.isInstance( instance ) ) { - return type.cast( instance ); - } - - return null; - } - - private static void collectFromInterfaces(MethodBinding methodBinding, ReferenceBinding typeBinding, - Set visitedTypes, List 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 lower. - * - * @author Andreas Gudian - */ - private static final class MostSpecificMethodBindingComparator implements Comparator { - 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; - } - } -} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseClassLoaderBridge.java b/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseClassLoaderBridge.java deleted file mode 100644 index d7dee52fb..000000000 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/EclipseClassLoaderBridge.java +++ /dev/null @@ -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; - } -} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/SpecificCompilerWorkarounds.java b/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/SpecificCompilerWorkarounds.java deleted file mode 100644 index 69b45c1ca..000000000 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/workarounds/SpecificCompilerWorkarounds.java +++ /dev/null @@ -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 JLS section 4.10, Subtyping. - *

- * Work-around for a bug related to sub-typing in the Eclipse JSR 269 implementation. - * - * @param types the type utils - * @param t1 the first type - * @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. - *

- * 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 Eclipse Bug 382590 (fixed in Eclipse 4.6) - * @see Eclipse Bug 481555 - */ - 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; - } -} diff --git a/processor/src/test/java/org/mapstruct/ap/internal/model/source/SelectionParametersTest.java b/processor/src/test/java/org/mapstruct/ap/internal/model/source/SelectionParametersTest.java index 7f57ae75c..19e194a76 100644 --- a/processor/src/test/java/org/mapstruct/ap/internal/model/source/SelectionParametersTest.java +++ b/processor/src/test/java/org/mapstruct/ap/internal/model/source/SelectionParametersTest.java @@ -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" );