Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
package org.mapstruct.ap.internal.model;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
Expand Down Expand Up @@ -80,10 +80,12 @@ public Decorator build() {
Mapper.getFlatName( mapperElement ) );

Type decoratorType = typeFactory.getType( decorator.value().get() );
boolean delegateFieldNeeded = !methods.isEmpty();
DecoratorConstructor decoratorConstructor = new DecoratorConstructor(
implementationName,
implementationName + "_",
hasDelegateConstructor );
hasDelegateConstructor,
delegateFieldNeeded );


Type mapperType = typeFactory.getType( mapperElement );
Expand All @@ -97,6 +99,7 @@ public Decorator build() {
decoratorType,
mapperType,
methods,
delegateFieldNeeded,
options,
versionInformation,
suppressGeneratorTimestamp,
Expand All @@ -110,11 +113,12 @@ public Decorator build() {

private final Type decoratorType;
private final Type mapperType;
private final boolean delegateFieldNeeded;

@SuppressWarnings( "checkstyle:parameternumber" )
private Decorator(TypeFactory typeFactory, String packageName, String name, Type decoratorType,
Type mapperType,
List<MappingMethod> methods,
List<MappingMethod> methods, boolean delegateFieldNeeded,
Options options, VersionInformation versionInformation,
boolean suppressGeneratorTimestamp,
Accessibility accessibility, SortedSet<Type> extraImports,
Expand All @@ -126,7 +130,9 @@ private Decorator(TypeFactory typeFactory, String packageName, String name, Type
name,
decoratorType,
methods,
Arrays.asList( new Field( mapperType, "delegate", true ) ),
delegateFieldNeeded
? Collections.singletonList( new Field( mapperType, "delegate", true ) )
: Collections.emptyList(),
options,
versionInformation,
suppressGeneratorTimestamp,
Expand All @@ -137,6 +143,7 @@ private Decorator(TypeFactory typeFactory, String packageName, String name, Type

this.decoratorType = decoratorType;
this.mapperType = mapperType;
this.delegateFieldNeeded = delegateFieldNeeded;

// Add custom annotations
if ( customAnnotations != null ) {
Expand All @@ -163,9 +170,24 @@ public SortedSet<Type> getImportTypes() {
else {
importTypes.add( decoratorType );
}

if ( !delegateFieldNeeded && decoratorType.getTypeElement() != null &&
decoratorType.getTypeElement().getNestingKind().isNested() && !isMapperTypeUsedInAnnotations() ) {
importTypes.remove( mapperType );
}

return importTypes;
}

private boolean isMapperTypeUsedInAnnotations() {
for ( Annotation annotation : getAnnotations() ) {
if ( annotation.getImportTypes().contains( mapperType ) ) {
return true;
}
}
return false;
}

@Override
protected String getTemplateName() {
return getTemplateNameForClass( GeneratedType.class );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ public class DecoratorConstructor extends ModelElement implements Constructor {
private final String name;
private final String delegateName;
private final boolean invokeSuperConstructor;
private final boolean delegateFieldNeeded;

public DecoratorConstructor(String name, String delegateName, boolean invokeSuperConstructor) {
public DecoratorConstructor(String name, String delegateName, boolean invokeSuperConstructor,
boolean delegateFieldNeeded) {
this.name = name;
this.delegateName = delegateName;
this.invokeSuperConstructor = invokeSuperConstructor;
this.delegateFieldNeeded = delegateFieldNeeded;
}

@Override
Expand All @@ -45,4 +48,8 @@ public String getDelegateName() {
public boolean isInvokeSuperConstructor() {
return invokeSuperConstructor;
}

public boolean isDelegateFieldNeeded() {
return delegateFieldNeeded;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -304,25 +304,29 @@ else if ( constructor.getParameters().size() == 1 ) {
.versionInformation( versionInformation )
.implName( mapperOptions.implementationName() )
.implPackage( mapperOptions.implementationPackage() )
.extraImports( getExtraImports( element, mapperOptions ) )
.extraImports( getExtraImports( element, mapperOptions, !mappingMethods.isEmpty() ) )
.suppressGeneratorTimestamp( mapperOptions.suppressTimestampInGenerated() )
.additionalAnnotations( decoratorAnnotations )
.build();

return decorator;
}

private SortedSet<Type> getExtraImports(TypeElement element, MapperOptions mapperOptions) {
SortedSet<Type> extraImports = new TreeSet<>();
private SortedSet<Type> getExtraImports(TypeElement element, MapperOptions mapperOptions) {
return getExtraImports( element, mapperOptions, true );
}

private SortedSet<Type> getExtraImports(TypeElement element, MapperOptions mapperOptions,
boolean includeMapperType) {
SortedSet<Type> extraImports = new TreeSet<>();

for ( TypeMirror extraImport : mapperOptions.imports() ) {
Type type = typeFactory.getAlwaysImportedType( extraImport );
extraImports.add( type );
}

// Add original package if a dest package has been set
if ( !"default".equals( mapperOptions.implementationPackage() ) ) {
// Add the original mapper type if a destination package has been set
if ( includeMapperType && !"default".equals( mapperOptions.implementationPackage() ) ) {
extraImports.add( typeFactory.getType( element ) );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

-->
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.DecoratorConstructor" -->
<#if invokeSuperConstructor || delegateFieldNeeded>
public ${name}() {
this( new ${delegateName}() );
}
Expand All @@ -14,5 +15,11 @@ private ${name}(${delegateName} delegate) {
<#if invokeSuperConstructor>
super( delegate );
</#if>
<#if delegateFieldNeeded>
this.delegate = delegate;
}
</#if>
}
<#else>
public ${name}() {
}
</#if>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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._1519;

import org.mapstruct.DecoratedWith;
import org.mapstruct.Mapper;

@Mapper(implementationPackage = "<PACKAGE_NAME>.dest")
@DecoratedWith(Issue1519DefaultConstructorMapper.Decorator.class)
public interface Issue1519DefaultConstructorMapper {

Target map(Source source);

class Source {

private String value;

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

class Target {

private String value;

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

abstract class Decorator implements Issue1519DefaultConstructorMapper {

@Override
public Target map(Source source) {
Target target = new Target();
target.setValue( source.getValue() );
return target;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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._1519;

import org.mapstruct.DecoratedWith;
import org.mapstruct.Mapper;

@Mapper
@DecoratedWith(Issue1519Mapper.Decorator.class)
public interface Issue1519Mapper {

Target map(Source source);

class Source {

private String value;

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

class Target {

private String value;

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

abstract class Decorator implements Issue1519Mapper {

private final Issue1519Mapper delegate;

Decorator(Issue1519Mapper delegate) {
this.delegate = delegate;
}

@Override
public Target map(Source source) {
return delegate.map( source );
}
}
}
Original file line number Diff line number Diff line change
@@ -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._1519;

import org.junit.jupiter.api.extension.RegisterExtension;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest;
import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.GeneratedSource;

@IssueKey("1519")
@WithClasses({
Issue1519Mapper.class,
Issue1519DefaultConstructorMapper.class
})
class Issue1519Test {

@RegisterExtension
final GeneratedSource generatedSource = new GeneratedSource();

@ProcessorTest
void shouldNotGenerateUnusedDelegateField() {
generatedSource.forMapper( Issue1519Mapper.class ).content()
.contains( "super( delegate );" )
.doesNotContain( "Issue1519Mapper delegate;" )
.doesNotContain( "this.delegate = delegate;" );
}

@ProcessorTest
void shouldNotCreateDelegateForDefaultConstructorDecorator() {
generatedSource.forJavaFile(
"org/mapstruct/ap/test/bugs/_1519/dest/Issue1519DefaultConstructorMapperImpl.java"
).content()
.contains( "public Issue1519DefaultConstructorMapperImpl() {\n }" )
.doesNotContain( "delegate" )
.doesNotContain( "Issue1519DefaultConstructorMapperImpl_" )
.doesNotContain( "import org.mapstruct.ap.test.bugs._1519.Issue1519DefaultConstructorMapper;" );
}
}
Loading