mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1640 Add init method with MapStructProcessingEnvironment to the BuilderProvider for initializing the Elements and Types
This commit is contained in:
parent
1266796921
commit
3ff4ebd60a
@ -522,7 +522,7 @@ public class TypeFactory {
|
||||
try {
|
||||
return roundContext.getAnnotationProcessorContext()
|
||||
.getBuilderProvider()
|
||||
.findBuilderInfo( type, elementUtils, typeUtils );
|
||||
.findBuilderInfo( type );
|
||||
}
|
||||
catch ( MoreThanOneBuilderCreationMethodException ex ) {
|
||||
messager.printMessage(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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}.
|
||||
* <p>
|
||||
* 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}.
|
||||
* <p>
|
||||
* 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<ExecutableElement> methods = ElementFilter.methodsIn( typeElement.getEnclosedElements() );
|
||||
List<BuilderInfo> builderInfo = new ArrayList<>();
|
||||
for ( ExecutableElement method : methods ) {
|
||||
if ( isPossibleBuilderCreationMethod( method, typeElement, types ) ) {
|
||||
if ( isPossibleBuilderCreationMethod( method, typeElement ) ) {
|
||||
TypeElement builderElement = getTypeElement( method.getReturnType() );
|
||||
Collection<ExecutableElement> buildMethods = findBuildMethods( builderElement, typeElement, types );
|
||||
Collection<ExecutableElement> 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}.
|
||||
* <p>
|
||||
* 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}.
|
||||
* <p>
|
||||
* The default implementation uses {@link DefaultBuilderProvider#shouldIgnore(TypeElement)} to check if the
|
||||
* {@code builderElement} should be ignored, i.e. not checked for build elements.
|
||||
* <p>
|
||||
* 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<ExecutableElement> findBuildMethods(TypeElement builderElement, TypeElement typeElement,
|
||||
Types types) {
|
||||
protected Collection<ExecutableElement> findBuildMethods(TypeElement builderElement, TypeElement typeElement) {
|
||||
if ( shouldIgnore( builderElement ) ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@ -232,7 +233,7 @@ public class DefaultBuilderProvider implements BuilderProvider {
|
||||
List<ExecutableElement> builderMethods = ElementFilter.methodsIn( builderElement.getEnclosedElements() );
|
||||
List<ExecutableElement> 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() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user