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