mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#206 Moving canAccess() method to Type; Splitting up MethodRetrievalProcessor#getMethod()
This commit is contained in:
parent
a77a693d9d
commit
fc2bd954c6
@ -363,6 +363,24 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
return 1 + minDistanceOfSuperToTargetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this type can access the given method declared on the given type.
|
||||
*/
|
||||
public boolean canAccess(Type type, ExecutableElement method) {
|
||||
if ( method.getModifiers().contains( Modifier.PRIVATE ) ) {
|
||||
return false;
|
||||
}
|
||||
else if ( method.getModifiers().contains( Modifier.PROTECTED ) ) {
|
||||
return isAssignableTo( type ) || getPackageName().equals( type.getPackageName() );
|
||||
}
|
||||
else if ( !method.getModifiers().contains( Modifier.PUBLIC ) ) {
|
||||
// default
|
||||
return getPackageName().equals( type.getPackageName() );
|
||||
}
|
||||
// public
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
@ -18,13 +18,10 @@
|
||||
*/
|
||||
package org.mapstruct.ap.processor;
|
||||
|
||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.processing.Messager;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
@ -50,6 +47,8 @@ import org.mapstruct.ap.prism.MappingsPrism;
|
||||
import org.mapstruct.ap.util.AnnotationProcessingException;
|
||||
import org.mapstruct.ap.util.MapperConfig;
|
||||
|
||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -131,6 +130,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
|
||||
/**
|
||||
* @param element the type element to check
|
||||
*
|
||||
* @return <code>true</code>, iff the type has a super-class that is not java.lang.Object
|
||||
*/
|
||||
private boolean hasNonObjectSuperclass(TypeElement element) {
|
||||
@ -142,67 +142,78 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
ExecutableElement method,
|
||||
TypeElement mapperToImplement) {
|
||||
List<Parameter> parameters = typeFactory.getParameters( method );
|
||||
Type returnType = typeFactory.getReturnType( method );
|
||||
List<Type> exceptionTypes = typeFactory.getThrownTypes( method );
|
||||
|
||||
//add method with property mappings if an implementation needs to be generated
|
||||
boolean methodRequiresImplementation = method.getModifiers().contains( Modifier.ABSTRACT );
|
||||
boolean containsTargetTypeParameter = SourceMethod.containsTargetTypeParameter( parameters );
|
||||
|
||||
//add method with property mappings if an implementation needs to be generated
|
||||
if ( ( usedMapper.equals( mapperToImplement ) ) && methodRequiresImplementation ) {
|
||||
List<Parameter> sourceParameters = extractSourceParameters( parameters );
|
||||
Parameter targetParameter = extractTargetParameter( parameters );
|
||||
Type resultType = selectResultType( returnType, targetParameter );
|
||||
|
||||
boolean isValid =
|
||||
checkParameterAndReturnType(
|
||||
method,
|
||||
sourceParameters,
|
||||
targetParameter,
|
||||
resultType,
|
||||
returnType,
|
||||
containsTargetTypeParameter );
|
||||
|
||||
if ( isValid ) {
|
||||
return
|
||||
SourceMethod.forMethodRequiringImplementation(
|
||||
method,
|
||||
parameters,
|
||||
returnType,
|
||||
exceptionTypes,
|
||||
getMappings( method ),
|
||||
IterableMapping.fromPrism( IterableMappingPrism.getInstanceOn( method ) ),
|
||||
MapMapping.fromPrism( MapMappingPrism.getInstanceOn( method ) ),
|
||||
typeUtils
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return getMethodRequiringImplementation( method, parameters, containsTargetTypeParameter );
|
||||
}
|
||||
//otherwise add reference to existing mapper method
|
||||
else if ( isValidReferencedMethod( parameters ) || isValidFactoryMethod( parameters ) ) {
|
||||
Type usedMapperAsType = typeFactory.getType( usedMapper );
|
||||
Type mapperToImplementAsType = typeFactory.getType( mapperToImplement );
|
||||
if ( isAccessible( mapperToImplementAsType, usedMapperAsType, method ) ) {
|
||||
return SourceMethod.forReferencedMethod(
|
||||
usedMapper.equals( mapperToImplement ) ? null : usedMapperAsType,
|
||||
method,
|
||||
parameters,
|
||||
returnType,
|
||||
exceptionTypes,
|
||||
typeUtils
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return getReferencedMethod( usedMapper, method, mapperToImplement, parameters );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private SourceMethod getMethodRequiringImplementation(ExecutableElement method, List<Parameter> parameters,
|
||||
boolean containsTargetTypeParameter) {
|
||||
Type returnType = typeFactory.getReturnType( method );
|
||||
List<Type> exceptionTypes = typeFactory.getThrownTypes( method );
|
||||
List<Parameter> sourceParameters = extractSourceParameters( parameters );
|
||||
Parameter targetParameter = extractTargetParameter( parameters );
|
||||
Type resultType = selectResultType( returnType, targetParameter );
|
||||
|
||||
boolean isValid = checkParameterAndReturnType(
|
||||
method,
|
||||
sourceParameters,
|
||||
targetParameter,
|
||||
resultType,
|
||||
returnType,
|
||||
containsTargetTypeParameter
|
||||
);
|
||||
|
||||
if ( !isValid ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SourceMethod.forMethodRequiringImplementation(
|
||||
method,
|
||||
parameters,
|
||||
returnType,
|
||||
exceptionTypes,
|
||||
getMappings( method ),
|
||||
IterableMapping.fromPrism( IterableMappingPrism.getInstanceOn( method ) ),
|
||||
MapMapping.fromPrism( MapMappingPrism.getInstanceOn( method ) ),
|
||||
typeUtils
|
||||
);
|
||||
}
|
||||
|
||||
private SourceMethod getReferencedMethod(TypeElement usedMapper, ExecutableElement method,
|
||||
TypeElement mapperToImplement, List<Parameter> parameters) {
|
||||
Type returnType = typeFactory.getReturnType( method );
|
||||
List<Type> exceptionTypes = typeFactory.getThrownTypes( method );
|
||||
Type usedMapperAsType = typeFactory.getType( usedMapper );
|
||||
Type mapperToImplementAsType = typeFactory.getType( mapperToImplement );
|
||||
|
||||
if ( !mapperToImplementAsType.canAccess( usedMapperAsType, method ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SourceMethod.forReferencedMethod(
|
||||
usedMapper.equals( mapperToImplement ) ? null : usedMapperAsType,
|
||||
method,
|
||||
parameters,
|
||||
returnType,
|
||||
exceptionTypes,
|
||||
typeUtils
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private boolean isValidReferencedMethod(List<Parameter> parameters) {
|
||||
return isValidReferencedOrFactoryMethod( 1, parameters );
|
||||
}
|
||||
@ -233,24 +244,6 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
&& parameters.size() == validSourceParameters + targetParameters + targetTypeParameters;
|
||||
}
|
||||
|
||||
|
||||
private boolean isAccessible( Type mapperToImplement, Type usedMapper, ExecutableElement method ) {
|
||||
|
||||
if ( method.getModifiers().contains( Modifier.PRIVATE ) ) {
|
||||
return false;
|
||||
}
|
||||
else if ( method.getModifiers().contains( Modifier.PROTECTED ) ) {
|
||||
return mapperToImplement.isAssignableTo( usedMapper ) ||
|
||||
mapperToImplement.getPackageName().equals( usedMapper.getPackageName() );
|
||||
}
|
||||
else if ( !method.getModifiers().contains( Modifier.PUBLIC ) ) {
|
||||
// default
|
||||
return mapperToImplement.getPackageName().equals( usedMapper.getPackageName() );
|
||||
}
|
||||
// public
|
||||
return true;
|
||||
}
|
||||
|
||||
private Parameter extractTargetParameter(List<Parameter> parameters) {
|
||||
for ( Parameter param : parameters ) {
|
||||
if ( param.isMappingTarget() ) {
|
||||
@ -328,7 +321,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
messager.printMessage(
|
||||
Kind.ERROR,
|
||||
"Can't generate mapping method that has a parameter annotated with @TargetType.",
|
||||
method );
|
||||
method
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,6 @@ public class ReferencedAccessibilityTest {
|
||||
@WithClasses( { AbstractSourceTargetMapperProtected.class, SourceTargetmapperProtectedBase.class } )
|
||||
public void shouldBeAbleToAccessProtectedMethodInBase() throws Exception { }
|
||||
|
||||
|
||||
@Test
|
||||
@IssueKey( "206" )
|
||||
@WithClasses( { AbstractSourceTargetMapperPrivate.class, SourceTargetmapperPrivateBase.class } )
|
||||
|
@ -19,12 +19,12 @@
|
||||
package org.mapstruct.ap.test.accessibility.referenced;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
public class ReferencedMapperPrivate {
|
||||
|
||||
private ReferencedTarget sourceToTarget( ReferencedSource source ) {
|
||||
@SuppressWarnings("unused")
|
||||
private ReferencedTarget sourceToTarget(ReferencedSource source) {
|
||||
ReferencedTarget target = new ReferencedTarget();
|
||||
target.setFoo( source.getFoo() );
|
||||
return target;
|
||||
|
@ -19,12 +19,12 @@
|
||||
package org.mapstruct.ap.test.accessibility.referenced;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
public class SourceTargetmapperPrivateBase {
|
||||
|
||||
private ReferencedTarget sourceToTarget( ReferencedSource source ) {
|
||||
@SuppressWarnings("unused")
|
||||
private ReferencedTarget sourceToTarget(ReferencedSource source) {
|
||||
ReferencedTarget target = new ReferencedTarget();
|
||||
target.setFoo( source.getFoo() );
|
||||
return target;
|
||||
|
Loading…
x
Reference in New Issue
Block a user