diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java index 981bd1957..6f46f073e 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java @@ -522,7 +522,7 @@ public class TypeFactory { try { return roundContext.getAnnotationProcessorContext() .getBuilderProvider() - .findBuilderInfo( type, elementUtils, typeUtils ); + .findBuilderInfo( type ); } catch ( MoreThanOneBuilderCreationMethodException ex ) { messager.printMessage( diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java index d46ca6f02..ed70cd9f9 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java @@ -76,6 +76,7 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen this.accessorNamingStrategy = Services.get( AccessorNamingStrategy.class, defaultAccessorNamingStrategy ); this.accessorNamingStrategy.init( this ); this.builderProvider = Services.get( BuilderProvider.class, defaultBuilderProvider ); + this.builderProvider.init( this ); this.accessorNaming = new AccessorNamingUtils( this.accessorNamingStrategy ); this.initialized = true; } diff --git a/processor/src/main/java/org/mapstruct/ap/spi/BuilderProvider.java b/processor/src/main/java/org/mapstruct/ap/spi/BuilderProvider.java index 6140d7a3a..c755c63f2 100644 --- a/processor/src/main/java/org/mapstruct/ap/spi/BuilderProvider.java +++ b/processor/src/main/java/org/mapstruct/ap/spi/BuilderProvider.java @@ -6,8 +6,6 @@ package org.mapstruct.ap.spi; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; /** * A service provider interface that is used to detect types that require a builder for mapping. This interface could @@ -16,13 +14,19 @@ import javax.lang.model.util.Types; */ public interface BuilderProvider { + /** + * Initializes the builder provider with the MapStruct processing environment. + * + * @param processingEnvironment environment for facilities + */ + default void init(MapStructProcessingEnvironment processingEnvironment) { + + } + /** * Find the builder information, if any, for the {@code type}. * * @param type the type for which a builder should be found - * @param elements the util elements that can be used for operations on program elements - * @param types the util types that can be used for operations on {@link TypeMirror}(s) - * * @return the builder info for the {@code type} if it exists, or {@code null} if there is no builder * * @throws TypeHierarchyErroneousException if the type that needs to be visited is not ready yet, this signals the @@ -30,5 +34,5 @@ public interface BuilderProvider { * @throws MoreThanOneBuilderCreationMethodException if {@code type} has more than one method that can create the * builder */ - BuilderInfo findBuilderInfo(TypeMirror type, Elements elements, Types types); + BuilderInfo findBuilderInfo(TypeMirror type); } diff --git a/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java b/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java index 23e6db350..9921ad2f0 100644 --- a/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java +++ b/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java @@ -77,14 +77,23 @@ public class DefaultBuilderProvider implements BuilderProvider { private static final Pattern JAVA_JAVAX_PACKAGE = Pattern.compile( "^javax?\\..*" ); + protected Elements elementUtils; + protected Types typeUtils; + @Override - public BuilderInfo findBuilderInfo(TypeMirror type, Elements elements, Types types) { + public void init(MapStructProcessingEnvironment processingEnvironment) { + this.elementUtils = processingEnvironment.getElementUtils(); + this.typeUtils = processingEnvironment.getTypeUtils(); + } + + @Override + public BuilderInfo findBuilderInfo(TypeMirror type) { TypeElement typeElement = getTypeElement( type ); if ( typeElement == null ) { return null; } - return findBuilderInfo( typeElement, elements, types ); + return findBuilderInfo( typeElement ); } /** @@ -130,8 +139,8 @@ public class DefaultBuilderProvider implements BuilderProvider { * Find the {@link BuilderInfo} for the given {@code typeElement}. *

* The default implementation iterates over all the methods in {@code typeElement} and uses - * {@link DefaultBuilderProvider#isPossibleBuilderCreationMethod(ExecutableElement, TypeElement, Types)} and - * {@link DefaultBuilderProvider#findBuildMethods(TypeElement, TypeElement, Types)} to create the + * {@link DefaultBuilderProvider#isPossibleBuilderCreationMethod(ExecutableElement, TypeElement)} and + * {@link DefaultBuilderProvider#findBuildMethods(TypeElement, TypeElement)} to create the * {@link BuilderInfo}. *

* The default implementation uses {@link DefaultBuilderProvider#shouldIgnore(TypeElement)} to check if the @@ -141,14 +150,11 @@ public class DefaultBuilderProvider implements BuilderProvider { * thrown. * * @param typeElement the type element for which a builder searched - * @param elements the util elements that can be used for operating on the type element - * @param types the util types that can be used for operation on {@link TypeMirror}(s) - * * @return the {@link BuilderInfo} or {@code null} if no builder was found for the type - * {@link DefaultBuilderProvider#findBuildMethods(TypeElement, TypeElement, Types)} + * {@link DefaultBuilderProvider#findBuildMethods(TypeElement, TypeElement)} * @throws MoreThanOneBuilderCreationMethodException if there are multiple builder creation methods */ - protected BuilderInfo findBuilderInfo(TypeElement typeElement, Elements elements, Types types) { + protected BuilderInfo findBuilderInfo(TypeElement typeElement) { if ( shouldIgnore( typeElement ) ) { return null; } @@ -156,9 +162,9 @@ public class DefaultBuilderProvider implements BuilderProvider { List methods = ElementFilter.methodsIn( typeElement.getEnclosedElements() ); List builderInfo = new ArrayList<>(); for ( ExecutableElement method : methods ) { - if ( isPossibleBuilderCreationMethod( method, typeElement, types ) ) { + if ( isPossibleBuilderCreationMethod( method, typeElement ) ) { TypeElement builderElement = getTypeElement( method.getReturnType() ); - Collection buildMethods = findBuildMethods( builderElement, typeElement, types ); + Collection buildMethods = findBuildMethods( builderElement, typeElement ); if ( !buildMethods.isEmpty() ) { builderInfo.add( new BuilderInfo.Builder() .builderCreationMethod( method ) @@ -176,7 +182,7 @@ public class DefaultBuilderProvider implements BuilderProvider { throw new MoreThanOneBuilderCreationMethodException( typeElement.asType(), builderInfo ); } - return findBuilderInfo( typeElement.getSuperclass(), elements, types ); + return findBuilderInfo( typeElement.getSuperclass() ); } /** @@ -192,39 +198,34 @@ public class DefaultBuilderProvider implements BuilderProvider { * * @param method The method that needs to be checked * @param typeElement the enclosing element of the method, i.e. the type in which the method is located in - * @param types the util types that can be used for operations on {@link TypeMirror}(s) - * * @return {@code true} if the {@code method} is a possible builder creation method, {@code false} otherwise */ - protected boolean isPossibleBuilderCreationMethod(ExecutableElement method, TypeElement typeElement, Types types) { + protected boolean isPossibleBuilderCreationMethod(ExecutableElement method, TypeElement typeElement) { return method.getParameters().isEmpty() && method.getModifiers().contains( Modifier.PUBLIC ) && method.getModifiers().contains( Modifier.STATIC ) - && !types.isSameType( method.getReturnType(), typeElement.asType() ); + && !typeUtils.isSameType( method.getReturnType(), typeElement.asType() ); } /** * Searches for a build method for {@code typeElement} within the {@code builderElement}. *

* The default implementation iterates over each method in {@code builderElement} and uses - * {@link DefaultBuilderProvider#isBuildMethod(ExecutableElement, TypeElement, Types)} to check if the method is a + * {@link DefaultBuilderProvider#isBuildMethod(ExecutableElement, TypeElement)} to check if the method is a * build method for {@code typeElement}. *

* The default implementation uses {@link DefaultBuilderProvider#shouldIgnore(TypeElement)} to check if the * {@code builderElement} should be ignored, i.e. not checked for build elements. *

* If there are multiple methods that satisfy - * {@link DefaultBuilderProvider#isBuildMethod(ExecutableElement, TypeElement, Types)} and one of those methods + * {@link DefaultBuilderProvider#isBuildMethod(ExecutableElement, TypeElement)} and one of those methods * is names {@code build} that that method would be considered as a build method. * @param builderElement the element for the builder * @param typeElement the element for the type that is being built - * @param types the util types tat can be used for operations on {@link TypeMirror}(s) - * * @return the build method for the {@code typeElement} if it exists, or {@code null} if it does not * {@code build} */ - protected Collection findBuildMethods(TypeElement builderElement, TypeElement typeElement, - Types types) { + protected Collection findBuildMethods(TypeElement builderElement, TypeElement typeElement) { if ( shouldIgnore( builderElement ) ) { return Collections.emptyList(); } @@ -232,7 +233,7 @@ public class DefaultBuilderProvider implements BuilderProvider { List builderMethods = ElementFilter.methodsIn( builderElement.getEnclosedElements() ); List buildMethods = new ArrayList<>(); for ( ExecutableElement buildMethod : builderMethods ) { - if ( isBuildMethod( buildMethod, typeElement, types ) ) { + if ( isBuildMethod( buildMethod, typeElement ) ) { buildMethods.add( buildMethod ); } } @@ -240,8 +241,7 @@ public class DefaultBuilderProvider implements BuilderProvider { if ( buildMethods.isEmpty() ) { return findBuildMethods( getTypeElement( builderElement.getSuperclass() ), - typeElement, - types + typeElement ); } @@ -260,15 +260,13 @@ public class DefaultBuilderProvider implements BuilderProvider { * * @param buildMethod the method that should be checked * @param typeElement the type element that needs to be built - * @param types the util types that can be used for operations on {@link TypeMirror}(s) - * * @return {@code true} if the {@code buildMethod} is a build method for {@code typeElement}, {@code false} * otherwise */ - protected boolean isBuildMethod(ExecutableElement buildMethod, TypeElement typeElement, Types types) { + protected boolean isBuildMethod(ExecutableElement buildMethod, TypeElement typeElement) { return buildMethod.getParameters().isEmpty() && buildMethod.getModifiers().contains( Modifier.PUBLIC ) - && types.isAssignable( buildMethod.getReturnType(), typeElement.asType() ); + && typeUtils.isAssignable( buildMethod.getReturnType(), typeElement.asType() ); } /** diff --git a/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java b/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java index 531b92f57..0da8b0316 100644 --- a/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java +++ b/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java @@ -12,8 +12,6 @@ import javax.lang.model.element.ElementKind; import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; /** * Builder provider for Immutables. A custom provider is needed because Immutables creates an implementation of an @@ -29,34 +27,32 @@ public class ImmutablesBuilderProvider extends DefaultBuilderProvider { private static final String IMMUTABLE_FQN = "org.immutables.value.Value.Immutable"; @Override - protected BuilderInfo findBuilderInfo(TypeElement typeElement, Elements elements, Types types) { + protected BuilderInfo findBuilderInfo(TypeElement typeElement) { Name name = typeElement.getQualifiedName(); if ( name.length() == 0 || JAVA_JAVAX_PACKAGE.matcher( name ).matches() ) { return null; } - TypeElement immutableAnnotation = elements.getTypeElement( IMMUTABLE_FQN ); + TypeElement immutableAnnotation = elementUtils.getTypeElement( IMMUTABLE_FQN ); if ( immutableAnnotation != null ) { BuilderInfo info = findBuilderInfoForImmutables( typeElement, - immutableAnnotation, - elements, - types + immutableAnnotation ); if ( info != null ) { return info; } } - return super.findBuilderInfo( typeElement, elements, types ); + return super.findBuilderInfo( typeElement ); } protected BuilderInfo findBuilderInfoForImmutables(TypeElement typeElement, - TypeElement immutableAnnotation, Elements elements, Types types) { - for ( AnnotationMirror annotationMirror : elements.getAllAnnotationMirrors( typeElement ) ) { - if ( types.isSameType( annotationMirror.getAnnotationType(), immutableAnnotation.asType() ) ) { - TypeElement immutableElement = asImmutableElement( typeElement, elements ); + TypeElement immutableAnnotation) { + for ( AnnotationMirror annotationMirror : elementUtils.getAllAnnotationMirrors( typeElement ) ) { + if ( typeUtils.isSameType( annotationMirror.getAnnotationType(), immutableAnnotation.asType() ) ) { + TypeElement immutableElement = asImmutableElement( typeElement ); if ( immutableElement != null ) { - return super.findBuilderInfo( immutableElement, elements, types ); + return super.findBuilderInfo( immutableElement ); } else { // Immutables processor has not run yet. Trigger a postpone to the next round for MapStruct @@ -67,7 +63,7 @@ public class ImmutablesBuilderProvider extends DefaultBuilderProvider { return null; } - protected TypeElement asImmutableElement(TypeElement typeElement, Elements elements) { + protected TypeElement asImmutableElement(TypeElement typeElement) { Element enclosingElement = typeElement.getEnclosingElement(); StringBuilder builderQualifiedName = new StringBuilder( typeElement.getQualifiedName().length() + 17 ); if ( enclosingElement.getKind() == ElementKind.PACKAGE ) { @@ -82,6 +78,6 @@ public class ImmutablesBuilderProvider extends DefaultBuilderProvider { } builderQualifiedName.append( "Immutable" ).append( typeElement.getSimpleName() ); - return elements.getTypeElement( builderQualifiedName ); + return elementUtils.getTypeElement( builderQualifiedName ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java b/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java index e38e86d91..fae086ab1 100644 --- a/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java +++ b/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java @@ -8,8 +8,6 @@ package org.mapstruct.ap.spi; // tag::documentation[] import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; // end::documentation[] @@ -22,7 +20,7 @@ import javax.lang.model.util.Types; public class NoOpBuilderProvider implements BuilderProvider { @Override - public BuilderInfo findBuilderInfo(TypeMirror type, Elements elements, Types types) { + public BuilderInfo findBuilderInfo(TypeMirror type) { return null; } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1596/Issue1569BuilderProvider.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1596/Issue1569BuilderProvider.java index c3df53443..92676f9ae 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1596/Issue1569BuilderProvider.java +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1596/Issue1569BuilderProvider.java @@ -7,8 +7,6 @@ package org.mapstruct.ap.test.bugs._1596; import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; import org.mapstruct.ap.spi.BuilderInfo; import org.mapstruct.ap.spi.BuilderProvider; @@ -17,22 +15,22 @@ import org.mapstruct.ap.spi.ImmutablesBuilderProvider; public class Issue1569BuilderProvider extends ImmutablesBuilderProvider implements BuilderProvider { @Override - protected BuilderInfo findBuilderInfo(TypeElement typeElement, Elements elements, Types types) { + protected BuilderInfo findBuilderInfo(TypeElement typeElement) { Name name = typeElement.getQualifiedName(); if ( name.toString().endsWith( ".Item" ) ) { - BuilderInfo info = findBuilderInfoForImmutables( typeElement, elements, types ); + BuilderInfo info = findBuilderInfoForImmutables( typeElement ); if ( info != null ) { return info; } } - return super.findBuilderInfo( typeElement, elements, types ); + return super.findBuilderInfo( typeElement ); } - protected BuilderInfo findBuilderInfoForImmutables(TypeElement typeElement, Elements elements, Types types) { - TypeElement immutableElement = asImmutableElement( typeElement, elements ); + protected BuilderInfo findBuilderInfoForImmutables(TypeElement typeElement) { + TypeElement immutableElement = asImmutableElement( typeElement ); if ( immutableElement != null ) { - return super.findBuilderInfo( immutableElement, elements, types ); + return super.findBuilderInfo( immutableElement ); } return null; }