#3711: Support generic @Context

Signed-off-by: TangYang <tangyang9464@163.com>
This commit is contained in:
Yang Tang 2025-05-31 17:10:24 +08:00 committed by GitHub
parent 6b6600c370
commit 5464c3cff8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 142 additions and 9 deletions

View File

@ -114,7 +114,12 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
}
List<SourceMethod> prototypeMethods = retrievePrototypeMethods( mapperTypeElement, mapperOptions );
return retrieveMethods( mapperTypeElement, mapperTypeElement, mapperOptions, prototypeMethods );
return retrieveMethods(
typeFactory.getType( mapperTypeElement.asType() ),
mapperTypeElement,
mapperOptions,
prototypeMethods
);
}
@Override
@ -166,19 +171,21 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
/**
* Retrieves the mapping methods declared by the given mapper type.
*
* @param usedMapper The type of interest (either the mapper to implement or a used mapper via @uses annotation)
* @param usedMapperType The type of interest (either the mapper to implement, a used mapper via @uses annotation,
* or a parameter type annotated with @Context)
* @param mapperToImplement the top level type (mapper) that requires implementation
* @param mapperOptions the mapper config
* @param prototypeMethods prototype methods defined in mapper config type
* @return All mapping methods declared by the given type
*/
private List<SourceMethod> retrieveMethods(TypeElement usedMapper, TypeElement mapperToImplement,
private List<SourceMethod> retrieveMethods(Type usedMapperType, TypeElement mapperToImplement,
MapperOptions mapperOptions, List<SourceMethod> prototypeMethods) {
List<SourceMethod> methods = new ArrayList<>();
TypeElement usedMapper = usedMapperType.getTypeElement();
for ( ExecutableElement executable : elementUtils.getAllEnclosedExecutableElements( usedMapper ) ) {
SourceMethod method = getMethod(
usedMapper,
usedMapperType,
executable,
mapperToImplement,
mapperOptions,
@ -195,7 +202,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
TypeElement usesMapperElement = asTypeElement( mapper );
if ( !mapperToImplement.equals( usesMapperElement ) ) {
methods.addAll( retrieveMethods(
usesMapperElement,
typeFactory.getType( mapper ),
mapperToImplement,
mapperOptions,
prototypeMethods ) );
@ -218,13 +225,13 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
return (TypeElement) type.asElement();
}
private SourceMethod getMethod(TypeElement usedMapper,
private SourceMethod getMethod(Type usedMapperType,
ExecutableElement method,
TypeElement mapperToImplement,
MapperOptions mapperOptions,
List<SourceMethod> prototypeMethods) {
ExecutableType methodType = typeFactory.getMethodType( (DeclaredType) usedMapper.asType(), method );
TypeElement usedMapper = usedMapperType.getTypeElement();
ExecutableType methodType = typeFactory.getMethodType( (DeclaredType) usedMapperType.getTypeMirror(), method );
List<Parameter> parameters = typeFactory.getParameters( methodType, method );
Type returnType = typeFactory.getReturnType( methodType );
@ -357,7 +364,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
continue;
}
List<SourceMethod> contextParamMethods = retrieveMethods(
contextParam.getType().getTypeElement(),
contextParam.getType(),
mapperToImplement,
mapperConfig,
Collections.emptyList() );

View File

@ -0,0 +1,12 @@
/*
* 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.test.bugs._3711;
import org.mapstruct.Context;
interface BaseMapper<T, E> {
E toEntity(T s, @Context JpaContext<E> ctx);
}

View File

@ -0,0 +1,31 @@
/*
* 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.test.bugs._3711;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
import org.mapstruct.ap.testutil.WithClasses;
import static org.assertj.core.api.Assertions.assertThat;
@WithClasses({
ParentEntity.class,
ParentDto.class,
JpaContext.class,
SourceTargetMapper.class,
BaseMapper.class,
})
@IssueKey("3711")
class Issue3711Test {
@ProcessorTest
void shouldGenerateContextMethod() {
JpaContext<ParentEntity> jpaContext = new JpaContext<>();
SourceTargetMapper.INSTANCE.toEntity( new ParentDto(), jpaContext );
assertThat( jpaContext.getInvokedMethods() )
.containsExactly( "beforeMapping", "afterMapping" );
}
}

View File

@ -0,0 +1,31 @@
/*
* 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.test.bugs._3711;
import java.util.ArrayList;
import java.util.List;
import org.mapstruct.AfterMapping;
import org.mapstruct.BeforeMapping;
import org.mapstruct.MappingTarget;
public class JpaContext<T> {
private final List<String> invokedMethods = new ArrayList<>();
@BeforeMapping
void beforeMapping(@MappingTarget T parentEntity) {
invokedMethods.add( "beforeMapping" );
}
@AfterMapping
void afterMapping(@MappingTarget T parentEntity) {
invokedMethods.add( "afterMapping" );
}
public List<String> getInvokedMethods() {
return invokedMethods;
}
}

View File

@ -0,0 +1,18 @@
/*
* 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.test.bugs._3711;
public class ParentDto {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,18 @@
/*
* 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.test.bugs._3711;
public class ParentEntity {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,16 @@
/*
* 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.test.bugs._3711;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SourceTargetMapper extends BaseMapper<ParentDto, ParentEntity> {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
ParentEntity toDTO(ParentDto dto);
}