Skip to content

Commit

Permalink
mapstruct#1742 move BuilderType out of Type
Browse files Browse the repository at this point in the history
  • Loading branch information
sjaakd committed May 10, 2019
1 parent 70a0906 commit 6990b69
Show file tree
Hide file tree
Showing 30 changed files with 350 additions and 229 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import javax.lang.model.element.AnnotationMirror;
import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.BuilderType;
import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.common.SourceRHS;
import org.mapstruct.ap.internal.model.common.Type;
Expand Down Expand Up @@ -73,7 +74,7 @@ private boolean isDisableSubMappingMethodsGeneration() {
*
* @return See above
*/
Assignment createForgedAssignment(SourceRHS sourceRHS, ForgedMethod forgedMethod) {
Assignment createForgedAssignment(SourceRHS sourceRHS, BuilderType builderType, ForgedMethod forgedMethod) {

if ( ctx.getForgedMethodsUnderCreation().containsKey( forgedMethod ) ) {
return createAssignment( sourceRHS, ctx.getForgedMethodsUnderCreation().get( forgedMethod ) );
Expand All @@ -93,6 +94,7 @@ Assignment createForgedAssignment(SourceRHS sourceRHS, ForgedMethod forgedMethod
else {
forgedMappingMethod = new BeanMappingMethod.Builder()
.forgedMethod( forgedMethod )
.returnTypeBuilder( builderType )
.mappingContext( ctx )
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Assignment forgeMapping(SourceRHS sourceRHS, Type sourceType, Type targetType) {
true
);

return createForgedAssignment( sourceRHS, forgedMethod );
return createForgedAssignment( sourceRHS, ctx.getTypeFactory().builderTypeFor( targetType ), forgedMethod );
}

private String getName(Type sourceType, Type targetType) {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public final M build() {

MethodReference factoryMethod = null;
if ( !method.isUpdateMethod() ) {
factoryMethod = ObjectFactoryMethodResolver.getFactoryMethod( method, method.getResultType(), null, ctx );
factoryMethod = ObjectFactoryMethodResolver.getFactoryMethod( method, null, ctx );
}

Set<String> existingVariables = new HashSet<>( method.getParameterNames() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.lang.model.element.ExecutableElement;

import org.mapstruct.ap.internal.model.common.Accessibility;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,60 @@ private LifecycleMethodResolver() {

/**
* @param method the method to obtain the beforeMapping methods for
* @param alternativeTarget alternative to {@link Method#getResultType()} e.g. when target is abstract
* @param selectionParameters method selectionParameters
* @param ctx the builder context
* @param existingVariableNames the existing variable names in the mapping method
* @return all applicable {@code @BeforeMapping} methods for the given method
*/
public static List<LifecycleCallbackMethodReference> beforeMappingMethods(Method method,
Type alternativeTarget,
SelectionParameters selectionParameters,
MappingBuilderContext ctx,
Set<String> existingVariableNames) {
return collectLifecycleCallbackMethods( method,
alternativeTarget,
selectionParameters,
filterBeforeMappingMethods( getAllAvailableMethods( method, ctx.getSourceModel() ) ),
ctx,
existingVariableNames );
}

/**
* @param method the method to obtain the afterMapping methods for
* @param alternativeTarget alternative to {@link Method#getResultType()} e.g. when target is abstract
* @param selectionParameters method selectionParameters
* @param ctx the builder context
* @param existingVariableNames list of already used variable names
* @return all applicable {@code @AfterMapping} methods for the given method
*/
public static List<LifecycleCallbackMethodReference> afterMappingMethods(Method method,
Type alternativeTarget,
SelectionParameters selectionParameters,
MappingBuilderContext ctx,
Set<String> existingVariableNames) {
return collectLifecycleCallbackMethods( method,
alternativeTarget,
selectionParameters,
filterAfterMappingMethods( getAllAvailableMethods( method, ctx.getSourceModel() ) ),
ctx,
existingVariableNames );
}


/**
* @param method the method to obtain the beforeMapping methods for
* @param selectionParameters method selectionParameters
* @param ctx the builder context
* @param existingVariableNames the existing variable names in the mapping method
* @return all applicable {@code @BeforeMapping} methods for the given method
*/
public static List<LifecycleCallbackMethodReference> beforeMappingMethods(Method method,
SelectionParameters selectionParameters,
MappingBuilderContext ctx,
Set<String> existingVariableNames) {
return collectLifecycleCallbackMethods( method,
method.getResultType(),
selectionParameters,
filterBeforeMappingMethods( getAllAvailableMethods( method, ctx.getSourceModel() ) ),
ctx,
Expand All @@ -60,6 +104,7 @@ public static List<LifecycleCallbackMethodReference> afterMappingMethods(Method
MappingBuilderContext ctx,
Set<String> existingVariableNames) {
return collectLifecycleCallbackMethods( method,
method.getResultType(),
selectionParameters,
filterAfterMappingMethods( getAllAvailableMethods( method, ctx.getSourceModel() ) ),
ctx,
Expand Down Expand Up @@ -87,18 +132,12 @@ private static List<SourceMethod> getAllAvailableMethods(Method method, List<Sou
}

private static List<LifecycleCallbackMethodReference> collectLifecycleCallbackMethods(
Method method, SelectionParameters selectionParameters, List<SourceMethod> callbackMethods,
Method method, Type targetType, SelectionParameters selectionParameters, List<SourceMethod> callbackMethods,
MappingBuilderContext ctx, Set<String> existingVariableNames) {

MethodSelectors selectors =
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getTypeFactory(), ctx.getMessager() );

Type targetType = method.getResultType();

if ( !method.isUpdateMethod() ) {
targetType = targetType.getEffectiveType();
}

List<SelectedMethod<SourceMethod>> matchingMethods = selectors.getMatchingMethods(
method,
callbackMethods,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public MapMappingMethod build() {
MethodReference factoryMethod = null;
if ( !method.isUpdateMethod() ) {
factoryMethod = ObjectFactoryMethodResolver
.getFactoryMethod( method, method.getResultType(), null, ctx );
.getFactoryMethod( method, null, ctx );
}

keyAssignment = new LocalVarWrapper( keyAssignment, method.getThrownTypes(), keyTargetType, false );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public void setAssignment( Assignment assignment ) {

@Override
public String getSourceReference() {
return assignment.getSourceReference();
return assignment != null ? assignment.getSourceReference() : null;
}

@Override
Expand Down Expand Up @@ -353,7 +353,8 @@ public static MethodReference forMethodCall(String methodName) {
@Override
public String toString() {
String mapper = declaringMapper != null ? declaringMapper.getType().getName().toString() : "";
String argument = getAssignment() != null ? getAssignment().toString() : getSourceReference();
String argument = getAssignment() != null ? getAssignment().toString() :
( getSourceReference() != null ? getSourceReference() : "" );
String returnTypeAsString = returnType != null ? returnType.toString() : "";
List<String> arguments = sourceParameters.stream()
.map( p -> p.isMappingContext() || p.isMappingTarget() || p.isTargetType() ? p.getName() : argument )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,36 @@ private ObjectFactoryMethodResolver() {
* returns a no arg factory method
*
* @param method target mapping method
* @param targetType return type to match
* @param selectionParameters parameters used in the selection process
* @param ctx
*
* @return a method reference to the factory method, or null if no suitable, or ambiguous method found
*
*/
public static MethodReference getFactoryMethod( Method method,
Type targetType,
SelectionParameters selectionParameters,
MappingBuilderContext ctx) {
return getFactoryMethod( method, method.getResultType(), selectionParameters, ctx );
}



/**
* returns a no arg factory method
*
* @param method target mapping method
* @param alternativeTarget alternative to {@link Method#getResultType()} e.g. when target is abstract
* @param selectionParameters parameters used in the selection process
* @param ctx
*
* @return a method reference to the factory method, or null if no suitable, or ambiguous method found
*
*/
public static MethodReference getFactoryMethod( Method method,
Type alternativeTarget,
SelectionParameters selectionParameters,
MappingBuilderContext ctx) {


MethodSelectors selectors =
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getTypeFactory(), ctx.getMessager() );
Expand All @@ -58,18 +77,18 @@ public static MethodReference getFactoryMethod( Method method,
method,
getAllAvailableMethods( method, ctx.getSourceModel() ),
java.util.Collections.<Type> emptyList(),
targetType.getEffectiveType(),
alternativeTarget,
SelectionCriteria.forFactoryMethods( selectionParameters ) );

if (matchingFactoryMethods.isEmpty()) {
return findBuilderFactoryMethod( targetType );
return null;
}

if ( matchingFactoryMethods.size() > 1 ) {
ctx.getMessager().printMessage(
method.getExecutable(),
Message.GENERAL_AMBIGIOUS_FACTORY_METHOD,
targetType.getEffectiveType(),
alternativeTarget,
Strings.join( matchingFactoryMethods, ", " ) );

return null;
Expand Down Expand Up @@ -98,8 +117,7 @@ java.util.Collections.<Type> emptyList(),
}
}

private static MethodReference findBuilderFactoryMethod(Type targetType) {
BuilderType builder = targetType.getBuilderType();
public static MethodReference getBuilderFactoryMethod(Method method, BuilderType builder ) {
if ( builder == null ) {
return null;
}
Expand All @@ -110,7 +128,7 @@ private static MethodReference findBuilderFactoryMethod(Type targetType) {
return null;
}

if ( !builder.getBuildingType().isAssignableTo( targetType ) ) {
if ( !builder.getBuildingType().isAssignableTo( method.getReturnType() ) ) {
//TODO print error message
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.DeclaredType;

import org.mapstruct.ap.internal.model.assignment.AdderWrapper;
import org.mapstruct.ap.internal.model.assignment.ArrayCopyWrapper;
Expand Down Expand Up @@ -41,8 +40,6 @@
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.NativeTypes;
Expand Down Expand Up @@ -75,7 +72,6 @@ public class PropertyMapping extends ModelElement {
private final List<String> dependsOn;
private final Assignment defaultValueAssignment;


@SuppressWarnings("unchecked")
private static class MappingBuilderBase<T extends MappingBuilderBase<T>> extends AbstractBaseBuilder<T> {

Expand Down Expand Up @@ -115,9 +111,9 @@ public T targetReadAccessor(Accessor targetReadAccessor) {

public T targetWriteAccessor(Accessor targetWriteAccessor) {
this.targetWriteAccessor = targetWriteAccessor;
this.targetType = ctx.getTypeFactory().getType( targetWriteAccessor.getAccessedType() );
this.targetBuilderType = ctx.getTypeFactory().builderTypeFor( this.targetType );
this.targetWriteAccessorType = targetWriteAccessor.getAccessorType();
this.targetType = determineTargetType();

return (T) this;
}

Expand All @@ -126,10 +122,6 @@ T mirror(AnnotationMirror mirror) {
return (T) this;
}

private Type determineTargetType() {
return ctx.getTypeFactory().getType( targetWriteAccessor.getAccessedType() );
}

public T targetPropertyName(String targetPropertyName) {
this.targetPropertyName = targetPropertyName;
return (T) this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
Expand Down Expand Up @@ -93,6 +92,7 @@ public class Type extends ModelElement implements Comparable<Type> {

private List<ExecutableElement> allMethods = null;
private List<VariableElement> allFields = null;

private List<Accessor> setters = null;
private List<Accessor> adders = null;
private List<Accessor> alternativeTargetAccessors = null;
Expand Down Expand Up @@ -501,7 +501,7 @@ public Map<String, Accessor> getPropertyReadAccessors() {
// In the DefaultAccessorNamingStrategy, this can only be the case for Booleans: isFoo() and
// getFoo(); The latter is preferred.
if ( !getter.getSimpleName().toString().startsWith( "is" ) ) {
modifiableGetters.put( getPropertyName( getter ),getter );
modifiableGetters.put( getPropertyName( getter ), getter );
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ private Type getType(TypeMirror mirror, boolean isLiteral) {
}

ImplementationType implementationType = getImplementationType( mirror );
BuilderInfo builderInfo = findBuilder( mirror );

boolean isIterableType = typeUtils.isSubtype( mirror, iterableType );
boolean isCollectionType = typeUtils.isSubtype( mirror, collectionType );
Expand Down Expand Up @@ -281,7 +280,6 @@ else if (componentTypeMirror.getKind().isPrimitive()) {
getTypeParameters( mirror, false ),
implementationType,
componentType,
builderInfo,
packageName,
name,
qualifiedName,
Expand Down Expand Up @@ -503,7 +501,6 @@ private ImplementationType getImplementationType(TypeMirror mirror) {
getTypeParameters( mirror, true ),
null,
null,
null,
implementationType.getPackageName(),
implementationType.getName(),
implementationType.getFullyQualifiedName(),
Expand All @@ -524,19 +521,21 @@ private ImplementationType getImplementationType(TypeMirror mirror) {
return null;
}

private BuilderInfo findBuilder(TypeMirror type) {
private BuilderInfo findBuilder(TypeMirror type, boolean report) {
try {
return roundContext.getAnnotationProcessorContext()
.getBuilderProvider()
.findBuilderInfo( type );
}
catch ( MoreThanOneBuilderCreationMethodException ex ) {
messager.printMessage(
typeUtils.asElement( type ),
Message.BUILDER_MORE_THAN_ONE_BUILDER_CREATION_METHOD,
type,
Strings.join( ex.getBuilderInfo(), ", ", BUILDER_INFO_CREATION_METHOD_EXTRACTOR )
);
if ( report ) {
messager.printMessage(
typeUtils.asElement( type ),
Message.BUILDER_MORE_THAN_ONE_BUILDER_CREATION_METHOD,
type,
Strings.join( ex.getBuilderInfo(), ", ", BUILDER_INFO_CREATION_METHOD_EXTRACTOR )
);
}
}

return null;
Expand Down Expand Up @@ -664,4 +663,21 @@ private boolean canBeProcessed(TypeMirror type) {

return true;
}

public BuilderType builderTypeFor( Type type ) {
if ( type != null ) {
BuilderInfo builderInfo = findBuilder( type.getTypeMirror(), true );
return BuilderType.create( builderInfo, type, this, this.typeUtils );
}
return null;
}

public Type effectiveResultTypeFor( Type type ) {
if ( type != null ) {
BuilderInfo builderInfo = findBuilder( type.getTypeMirror(), false );
BuilderType builderType = BuilderType.create( builderInfo, type, this, this.typeUtils );
return builderType != null ? builderType.getBuilder() : type;
}
return type;
}
}
Loading

0 comments on commit 6990b69

Please sign in to comment.