mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#2393 Use includeModel when generating GeneratedType
With this we make sure that the implementation type will have a correct import in case of a clash with another mapper named the same
This commit is contained in:
parent
85d3b310f7
commit
c9199b7068
@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.model;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Accessibility;
|
||||
@ -74,7 +73,8 @@ public class Decorator extends GeneratedType {
|
||||
hasDelegateConstructor );
|
||||
|
||||
|
||||
String elementPackage = elementUtils.getPackageOf( mapperElement ).getQualifiedName().toString();
|
||||
Type mapperType = typeFactory.getType( mapperElement );
|
||||
String elementPackage = mapperType.getPackageName();
|
||||
String packageName = implPackage.replace( Mapper.PACKAGE_NAME_PLACEHOLDER, elementPackage );
|
||||
|
||||
return new Decorator(
|
||||
@ -82,10 +82,8 @@ public class Decorator extends GeneratedType {
|
||||
packageName,
|
||||
implementationName,
|
||||
decoratorType,
|
||||
elementPackage,
|
||||
mapperElement.getKind() == ElementKind.INTERFACE ? mapperElement.getSimpleName().toString() : null,
|
||||
mapperType,
|
||||
methods,
|
||||
Arrays.asList( new Field( typeFactory.getType( mapperElement ), "delegate", true ) ),
|
||||
options,
|
||||
versionInformation,
|
||||
Accessibility.fromModifiers( mapperElement.getModifiers() ),
|
||||
@ -96,22 +94,22 @@ public class Decorator extends GeneratedType {
|
||||
}
|
||||
|
||||
private final Type decoratorType;
|
||||
private final Type mapperType;
|
||||
|
||||
@SuppressWarnings( "checkstyle:parameternumber" )
|
||||
private Decorator(TypeFactory typeFactory, String packageName, String name, Type decoratorType,
|
||||
String interfacePackage, String interfaceName, List<MappingMethod> methods,
|
||||
List<Field> fields, Options options, VersionInformation versionInformation,
|
||||
Type mapperType,
|
||||
List<MappingMethod> methods,
|
||||
Options options, VersionInformation versionInformation,
|
||||
Accessibility accessibility, SortedSet<Type> extraImports,
|
||||
DecoratorConstructor decoratorConstructor) {
|
||||
super(
|
||||
typeFactory,
|
||||
packageName,
|
||||
name,
|
||||
decoratorType.getName(),
|
||||
interfacePackage,
|
||||
interfaceName,
|
||||
decoratorType,
|
||||
methods,
|
||||
fields,
|
||||
Arrays.asList( new Field( mapperType, "delegate", true ) ),
|
||||
options,
|
||||
versionInformation,
|
||||
accessibility,
|
||||
@ -120,6 +118,7 @@ public class Decorator extends GeneratedType {
|
||||
);
|
||||
|
||||
this.decoratorType = decoratorType;
|
||||
this.mapperType = mapperType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -148,4 +147,8 @@ public class Decorator extends GeneratedType {
|
||||
protected String getTemplateName() {
|
||||
return getTemplateNameForClass( GeneratedType.class );
|
||||
}
|
||||
|
||||
public Type getMapperType() {
|
||||
return mapperType;
|
||||
}
|
||||
}
|
||||
|
@ -80,9 +80,7 @@ public abstract class GeneratedType extends ModelElement {
|
||||
|
||||
private final String packageName;
|
||||
private final String name;
|
||||
private final String superClassName;
|
||||
private final String interfacePackage;
|
||||
private final String interfaceName;
|
||||
private final Type mapperDefinitionType;
|
||||
|
||||
private final List<Annotation> annotations;
|
||||
private final List<MappingMethod> methods;
|
||||
@ -102,15 +100,13 @@ public abstract class GeneratedType extends ModelElement {
|
||||
private final boolean generatedTypeAvailable;
|
||||
|
||||
// CHECKSTYLE:OFF
|
||||
protected GeneratedType(TypeFactory typeFactory, String packageName, String name, String superClassName,
|
||||
String interfacePackage, String interfaceName, List<MappingMethod> methods,
|
||||
protected GeneratedType(TypeFactory typeFactory, String packageName, String name,
|
||||
Type mapperDefinitionType, List<MappingMethod> methods,
|
||||
List<Field> fields, Options options, VersionInformation versionInformation,
|
||||
Accessibility accessibility, SortedSet<Type> extraImportedTypes, Constructor constructor) {
|
||||
this.packageName = packageName;
|
||||
this.name = name;
|
||||
this.superClassName = superClassName;
|
||||
this.interfacePackage = interfacePackage;
|
||||
this.interfaceName = interfaceName;
|
||||
this.mapperDefinitionType = mapperDefinitionType;
|
||||
this.extraImportedTypes = extraImportedTypes;
|
||||
|
||||
this.annotations = new ArrayList<>();
|
||||
@ -153,16 +149,8 @@ public abstract class GeneratedType extends ModelElement {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSuperClassName() {
|
||||
return superClassName;
|
||||
}
|
||||
|
||||
public String getInterfacePackage() {
|
||||
return interfacePackage;
|
||||
}
|
||||
|
||||
public String getInterfaceName() {
|
||||
return interfaceName;
|
||||
public Type getMapperDefinitionType() {
|
||||
return mapperDefinitionType;
|
||||
}
|
||||
|
||||
public List<Annotation> getAnnotations() {
|
||||
@ -214,6 +202,8 @@ public abstract class GeneratedType extends ModelElement {
|
||||
SortedSet<Type> importedTypes = new TreeSet<>();
|
||||
addIfImportRequired( importedTypes, generatedType );
|
||||
|
||||
addIfImportRequired( importedTypes, mapperDefinitionType );
|
||||
|
||||
for ( MappingMethod mappingMethod : methods ) {
|
||||
for ( Type type : mappingMethod.getImportTypes() ) {
|
||||
addIfImportRequired( importedTypes, type );
|
||||
|
@ -10,7 +10,6 @@ import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Accessibility;
|
||||
@ -90,13 +89,14 @@ public class Mapper extends GeneratedType {
|
||||
if ( !fragments.isEmpty() ) {
|
||||
constructor = new NoArgumentConstructor( implementationName, fragments );
|
||||
}
|
||||
|
||||
Type definitionType = typeFactory.getType( element );
|
||||
|
||||
return new Mapper(
|
||||
typeFactory,
|
||||
packageName,
|
||||
implementationName,
|
||||
element.getKind() != ElementKind.INTERFACE ? element.getSimpleName().toString() : null,
|
||||
elementPackage,
|
||||
element.getKind() == ElementKind.INTERFACE ? element.getSimpleName().toString() : null,
|
||||
definitionType,
|
||||
customPackage,
|
||||
customName,
|
||||
methods,
|
||||
@ -117,8 +117,9 @@ public class Mapper extends GeneratedType {
|
||||
private Decorator decorator;
|
||||
|
||||
@SuppressWarnings( "checkstyle:parameternumber" )
|
||||
private Mapper(TypeFactory typeFactory, String packageName, String name, String superClassName,
|
||||
String interfacePackage, String interfaceName, boolean customPackage, boolean customImplName,
|
||||
private Mapper(TypeFactory typeFactory, String packageName, String name,
|
||||
Type mapperDefinitionType,
|
||||
boolean customPackage, boolean customImplName,
|
||||
List<MappingMethod> methods, Options options, VersionInformation versionInformation,
|
||||
Accessibility accessibility, List<Field> fields, Constructor constructor,
|
||||
Decorator decorator, SortedSet<Type> extraImportedTypes ) {
|
||||
@ -127,9 +128,7 @@ public class Mapper extends GeneratedType {
|
||||
typeFactory,
|
||||
packageName,
|
||||
name,
|
||||
superClassName,
|
||||
interfacePackage,
|
||||
interfaceName,
|
||||
mapperDefinitionType,
|
||||
methods,
|
||||
fields,
|
||||
options,
|
||||
|
@ -12,9 +12,11 @@ import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.MappingConstantsGem;
|
||||
import org.mapstruct.ap.internal.model.Decorator;
|
||||
import org.mapstruct.ap.internal.model.GeneratedType;
|
||||
import org.mapstruct.ap.internal.model.Mapper;
|
||||
import org.mapstruct.ap.internal.model.ServicesEntry;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.MapperOptions;
|
||||
import org.mapstruct.ap.internal.writer.ModelWriter;
|
||||
|
||||
@ -55,15 +57,28 @@ public class MapperServiceProcessor implements ModelElementProcessor<Mapper, Vo
|
||||
|
||||
private void writeToSourceFile(Filer filer, Mapper model) {
|
||||
ModelWriter modelWriter = new ModelWriter();
|
||||
ServicesEntry servicesEntry = getServicesEntry( model.getDecorator() == null ? model : model.getDecorator() );
|
||||
ServicesEntry servicesEntry = getServicesEntry( model );
|
||||
|
||||
createSourceFile( servicesEntry, modelWriter, filer );
|
||||
}
|
||||
|
||||
private ServicesEntry getServicesEntry(GeneratedType model) {
|
||||
String mapperName = model.getInterfaceName() != null ? model.getInterfaceName() : model.getSuperClassName();
|
||||
private ServicesEntry getServicesEntry(Mapper mapper) {
|
||||
if ( mapper.getDecorator() != null ) {
|
||||
return getServicesEntry( mapper.getDecorator() );
|
||||
}
|
||||
|
||||
return new ServicesEntry(model.getInterfacePackage(), mapperName,
|
||||
return getServicesEntry( mapper.getMapperDefinitionType(), mapper );
|
||||
}
|
||||
|
||||
private ServicesEntry getServicesEntry(Decorator decorator) {
|
||||
return getServicesEntry( decorator.getMapperType(), decorator );
|
||||
}
|
||||
|
||||
private ServicesEntry getServicesEntry(Type mapperType, GeneratedType model) {
|
||||
String mapperName = mapperType.getName();
|
||||
String mapperPackageName = mapperType.getPackageName();
|
||||
|
||||
return new ServicesEntry(mapperPackageName, mapperName,
|
||||
model.getPackageName(), model.getName());
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ import ${importedType};
|
||||
<#list annotations as annotation>
|
||||
<#nt><@includeModel object=annotation/>
|
||||
</#list>
|
||||
<#lt>${accessibility.keyword} class ${name}<#if superClassName??> extends ${superClassName}</#if><#if interfaceName??> implements ${interfaceName}</#if> {
|
||||
<#lt>${accessibility.keyword} class ${name} <#if mapperDefinitionType.interface>implements<#else>extends</#if> <@includeModel object=mapperDefinitionType/> {
|
||||
|
||||
<#list fields as field><#if field.used><#nt> <@includeModel object=field/>
|
||||
</#if></#list>
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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._2393;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class Address {
|
||||
|
||||
private final String city;
|
||||
private final Country country;
|
||||
|
||||
public Address(String city, Country country) {
|
||||
this.city = city;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public Country getCountry() {
|
||||
return country;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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._2393;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class AddressDto {
|
||||
|
||||
private String city;
|
||||
private CountryDto country;
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public CountryDto getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(CountryDto country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
@Mapper(uses = CountryDto.Converter.class)
|
||||
public interface Converter {
|
||||
|
||||
Converter INSTANCE = Mappers.getMapper( Converter.class );
|
||||
|
||||
AddressDto convert(Address address);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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._2393;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class Country {
|
||||
|
||||
private final String name;
|
||||
|
||||
public Country(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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._2393;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class CountryDto {
|
||||
|
||||
private String name;
|
||||
private String code;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Mapper
|
||||
public interface Converter {
|
||||
|
||||
@Mapping(target = "code", constant = "UNKNOWN")
|
||||
CountryDto convert(Country from);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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._2393;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.testutil.IssueKey;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@IssueKey("2393")
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
@WithClasses({
|
||||
Address.class,
|
||||
AddressDto.class,
|
||||
Country.class,
|
||||
CountryDto.class,
|
||||
})
|
||||
public class Issue2393Test {
|
||||
|
||||
@Test
|
||||
public void shouldUseCorrectImport() {
|
||||
AddressDto dto = AddressDto.Converter.INSTANCE.convert( new Address(
|
||||
"Zurich",
|
||||
new Country( "Switzerland" )
|
||||
) );
|
||||
|
||||
assertThat( dto.getCity() ).isEqualTo( "Zurich" );
|
||||
assertThat( dto.getCountry().getName() ).isEqualTo( "Switzerland" );
|
||||
assertThat( dto.getCountry().getCode() ).isEqualTo( "UNKNOWN" );
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user