#1700 Optimizing code for adders and stream adders (#1701)

This commit is contained in:
Sjaak Derksen 2019-01-29 20:02:23 +01:00 committed by GitHub
parent 0981959ff0
commit 07c7a29adc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 233 additions and 38 deletions

View File

@ -169,8 +169,8 @@ public class MethodReference extends ModelElement implements Assignment {
}
@Override
public String createLocalVarName( String desiredName ) {
return assignment.createLocalVarName( desiredName );
public String createUniqueVarName(String desiredName ) {
return assignment.createUniqueVarName( desiredName );
}
@Override
@ -183,6 +183,16 @@ public class MethodReference extends ModelElement implements Assignment {
assignment.setSourceLocalVarName( sourceLocalVarName );
}
@Override
public String getSourceLoopVarName() {
return assignment.getSourceLoopVarName();
}
@Override
public void setSourceLoopVarName(String sourceLoopVarName) {
assignment.setSourceLoopVarName( sourceLoopVarName );
}
@Override
public String getSourceParameterName() {
return assignment.getSourceParameterName();

View File

@ -621,7 +621,7 @@ public class PropertyMapping extends ModelElement {
// create a local variable to which forged method can be assigned.
String desiredName = last( sourceReference.getPropertyEntries() ).getName();
sourceRhs.setSourceLocalVarName( sourceRhs.createLocalVarName( desiredName ) );
sourceRhs.setSourceLocalVarName( sourceRhs.createUniqueVarName( desiredName ) );
return sourceRhs;

View File

@ -89,8 +89,8 @@ public class TypeConversion extends ModelElement implements Assignment {
}
@Override
public String createLocalVarName( String desiredName ) {
return assignment.createLocalVarName( desiredName );
public String createUniqueVarName(String desiredName ) {
return assignment.createUniqueVarName( desiredName );
}
@Override
@ -103,6 +103,16 @@ public class TypeConversion extends ModelElement implements Assignment {
assignment.setSourceLocalVarName( sourceLocalVarName );
}
@Override
public String getSourceLoopVarName() {
return assignment.getSourceLoopVarName();
}
@Override
public void setSourceLoopVarName(String sourceLoopVarName) {
assignment.setSourceLoopVarName( sourceLoopVarName );
}
@Override
public String getSourceParameterName() {
return assignment.getSourceParameterName();

View File

@ -33,8 +33,12 @@ public class AdderWrapper extends AssignmentWrapper {
String adderIteratorName ) {
super( rhs, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
// a method local var has been added earlier.
// localVar is iteratorVariable
String desiredName = Nouns.singularize( adderIteratorName );
rhs.setSourceLocalVarName( rhs.createLocalVarName( desiredName ) );
rhs.setSourceLoopVarName( rhs.createUniqueVarName( desiredName ) );
adderType = first( getSourceType().determineTypeArguments( Collection.class ) );
}
@ -56,6 +60,18 @@ public class AdderWrapper extends AssignmentWrapper {
return adderType;
}
public boolean isIncludeSourceNullCheck() {
return true;
}
public boolean isSetExplicitlyToNull() {
return false;
}
public boolean isSetExplicitlyToDefault() {
return false;
}
@Override
public Set<Type> getImportTypes() {
Set<Type> imported = new HashSet<>();

View File

@ -33,7 +33,7 @@ public class ArrayCopyWrapper extends AssignmentWrapper {
super( rhs, fieldAssignment );
this.arraysType = arraysType;
this.targetType = targetType;
rhs.setSourceLocalVarName( rhs.createLocalVarName( targetPropertyName ) );
rhs.setSourceLocalVarName( rhs.createUniqueVarName( targetPropertyName ) );
this.setExplicitlyToDefault = setExplicitlyToDefault;
this.setExplicitlyToNull = setExplicitlyToNull;
}

View File

@ -76,6 +76,16 @@ public abstract class AssignmentWrapper extends ModelElement implements Assignme
decoratedAssignment.setSourceLocalVarName( sourceLocalVarName );
}
@Override
public String getSourceLoopVarName() {
return decoratedAssignment.getSourceLoopVarName();
}
@Override
public void setSourceLoopVarName(String sourceLoopVarName) {
decoratedAssignment.setSourceLoopVarName( sourceLoopVarName );
}
@Override
public String getSourceParameterName() {
return decoratedAssignment.getSourceParameterName();
@ -92,8 +102,8 @@ public abstract class AssignmentWrapper extends ModelElement implements Assignme
}
@Override
public String createLocalVarName( String desiredName ) {
return decoratedAssignment.createLocalVarName( desiredName );
public String createUniqueVarName(String desiredName ) {
return decoratedAssignment.createUniqueVarName( desiredName );
}
/**

View File

@ -34,7 +34,7 @@ public class StreamAdderWrapper extends AssignmentWrapper {
super( rhs, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
String desiredName = Nouns.singularize( targetPropertyName );
rhs.setSourceLocalVarName( rhs.createLocalVarName( desiredName ) );
rhs.setSourceLocalVarName( rhs.createUniqueVarName( desiredName ) );
adderType = first( getSourceType().determineTypeArguments( Stream.class ) );
}
@ -56,6 +56,18 @@ public class StreamAdderWrapper extends AssignmentWrapper {
return adderType;
}
public boolean isIncludeSourceNullCheck() {
return true;
}
public boolean isSetExplicitlyToNull() {
return false;
}
public boolean isSetExplicitlyToDefault() {
return false;
}
@Override
public Set<Type> getImportTypes() {
Set<Type> imported = new HashSet<>();

View File

@ -37,7 +37,7 @@ public class WrapperForCollectionsAndMaps extends AssignmentWrapper {
else {
this.nullCheckLocalVarType = targetType;
}
this.nullCheckLocalVarName = rhs.createLocalVarName( nullCheckLocalVarType.getName() );
this.nullCheckLocalVarName = rhs.createUniqueVarName( nullCheckLocalVarType.getName() );
}
@Override

View File

@ -106,7 +106,7 @@ public interface Assignment {
*
* @return the desired name, made unique in the scope of the bean mapping.
*/
String createLocalVarName( String desiredName );
String createUniqueVarName(String desiredName );
/**
* See {@link #setSourceLocalVarName(java.lang.String) }
@ -131,6 +131,23 @@ public interface Assignment {
*/
void setSourceLocalVarName(String sourceLocalVarName);
/**
* See {@link #getSourceLoopVarName()} (java.lang.String) }
*
* @return loop variable (can be null if not set)
*/
String getSourceLoopVarName();
/**
* Replaces the sourceLocalVar or sourceReference at the call site in the assignment in the template with this
* sourceLoopVarName.
* The sourceLocalVar can subsequently be used for e.g. null checking.
*
* @param sourceLoopVarName loop variable
*/
void setSourceLoopVarName(String sourceLoopVarName);
/**
* Returns whether the type of assignment
*

View File

@ -27,6 +27,7 @@ public class SourceRHS extends ModelElement implements Assignment {
private final String sourceReference;
private final Type sourceType;
private String sourceLocalVarName;
private String sourceLoopVarName;
private final Set<String> existingVariableNames;
private final String sourceErrorMessagePart;
private final String sourcePresenceCheckerReference;
@ -69,7 +70,7 @@ public class SourceRHS extends ModelElement implements Assignment {
}
@Override
public String createLocalVarName(String desiredName) {
public String createUniqueVarName(String desiredName) {
String result = Strings.getSafeVariableName( desiredName, existingVariableNames );
existingVariableNames.add( result );
return result;
@ -85,6 +86,14 @@ public class SourceRHS extends ModelElement implements Assignment {
this.sourceLocalVarName = sourceLocalVarName;
}
public String getSourceLoopVarName() {
return sourceLoopVarName;
}
public void setSourceLoopVarName(String sourceLoopVarName) {
this.sourceLoopVarName = sourceLoopVarName;
}
@Override
public Set<Type> getImportTypes() {
return Collections.emptySet();

View File

@ -8,9 +8,10 @@
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.assignment.AdderWrapper" -->
<#import "../macro/CommonMacros.ftl" as lib>
<@lib.handleExceptions>
if ( ${sourceReference} != null ) {
for ( <@includeModel object=adderType.typeBound/> ${sourceLocalVarName} : ${sourceReference} ) {
<@lib.sourceLocalVarAssignment/>
<@lib.handleSourceReferenceNullCheck>
for ( <@includeModel object=adderType.typeBound/> ${sourceLoopVarName} : <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference}</#if> ) {
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><@lib.handleAssignment/></@lib.handleWrite>;
}
}
</@lib.handleSourceReferenceNullCheck>
</@lib.handleExceptions>

View File

@ -8,7 +8,8 @@
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.assignment.StreamAdderWrapper" -->
<#import "../macro/CommonMacros.ftl" as lib>
<@lib.handleExceptions>
if ( ${sourceReference} != null ) {
${sourceReference}.forEach( ${ext.targetBeanName}::${ext.targetWriteAccessorName} );
}
<@lib.sourceLocalVarAssignment/>
<@lib.handleSourceReferenceNullCheck>
<#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference}</#if>.forEach( ${ext.targetBeanName}::${ext.targetWriteAccessorName} );
</@lib.handleSourceReferenceNullCheck>
</@lib.handleExceptions>

View File

@ -6,4 +6,4 @@
-->
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.common.SourceRHS" -->
<#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference}</#if>
<#if sourceLoopVarName??>${sourceLoopVarName}<#elseif sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference}</#if>

View File

@ -3,10 +3,12 @@
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._1561.java8;
package org.mapstruct.ap.test.bugs._1561;
import org.mapstruct.CollectionMappingStrategy;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
@ -18,7 +20,9 @@ public interface Issue1561Mapper {
Issue1561Mapper
INSTANCE = Mappers.getMapper( Issue1561Mapper.class );
@Mapping( target = "nestedTarget.properties", source = "properties")
Target map(Source source);
@InheritInverseConfiguration
Source map(Target target);
}

View File

@ -3,13 +3,15 @@
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._1561.java8;
package org.mapstruct.ap.test.bugs._1561;
import org.junit.Rule;
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 org.mapstruct.ap.testutil.runner.GeneratedSource;
import static org.assertj.core.api.Assertions.assertThat;
@ -21,10 +23,16 @@ import static org.assertj.core.api.Assertions.assertThat;
@WithClasses({
Issue1561Mapper.class,
Source.class,
Target.class
Target.class,
NestedTarget.class
})
public class Issue1561Test {
@Rule
public final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor(
Issue1561Mapper.class
);
@Test
public void shouldCorrectlyUseAdder() {
@ -34,12 +42,10 @@ public class Issue1561Test {
Target target = Issue1561Mapper.INSTANCE.map( source );
assertThat( target.getProperties() )
.containsExactly( "first", "second" );
assertThat( target.getNestedTarget().getProperties() ).containsExactly( "first", "second" );
Source mapped = Issue1561Mapper.INSTANCE.map( target );
assertThat( mapped.getProperties() )
.containsExactly( "first", "second" );
assertThat( mapped.getProperties() ).containsExactly( "first", "second" );
}
}

View File

@ -3,7 +3,7 @@
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._1561.java8;
package org.mapstruct.ap.test.bugs._1561;
import java.util.ArrayList;
import java.util.List;
@ -12,7 +12,7 @@ import java.util.stream.Stream;
/**
* @author Sebastian Haberey
*/
public class Target {
public class NestedTarget {
private List<String> properties = new ArrayList<String>();

View File

@ -3,7 +3,7 @@
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._1561.java8;
package org.mapstruct.ap.test.bugs._1561;
import java.util.ArrayList;
import java.util.List;

View File

@ -0,0 +1,19 @@
/*
* 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._1561;
public class Target {
private NestedTarget nestedTarget;
public NestedTarget getNestedTarget() {
return nestedTarget;
}
public void setNestedTarget(NestedTarget nestedTarget) {
this.nestedTarget = nestedTarget;
}
}

View File

@ -0,0 +1,77 @@
/*
* 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._1561;
import java.util.stream.Stream;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2019-01-29T19:40:52+0100",
comments = "version: , compiler: javac, environment: Java 1.8.0_181 (Oracle Corporation)"
)
public class Issue1561MapperImpl implements Issue1561Mapper {
@Override
public Target map(Source source) {
if ( source == null ) {
return null;
}
Target target = new Target();
target.setNestedTarget( sourceToNestedTarget( source ) );
return target;
}
@Override
public Source map(Target target) {
if ( target == null ) {
return null;
}
Source source = new Source();
Stream<String> nestedTargetProperty = targetNestedTargetProperties( target );
if ( nestedTargetProperty != null ) {
nestedTargetProperty.forEach( source::addProperty );
}
return source;
}
protected NestedTarget sourceToNestedTarget(Source source) {
if ( source == null ) {
return null;
}
NestedTarget nestedTarget = new NestedTarget();
if ( source.getProperties() != null ) {
for ( String property : source.getProperties() ) {
nestedTarget.addProperty( property );
}
}
return nestedTarget;
}
private Stream<String> targetNestedTargetProperties(Target target) {
if ( target == null ) {
return null;
}
NestedTarget nestedTarget = target.getNestedTarget();
if ( nestedTarget == null ) {
return null;
}
Stream<String> properties = nestedTarget.getProperties();
if ( properties == null ) {
return null;
}
return properties;
}
}

View File

@ -12,8 +12,8 @@ import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2019-01-28T21:17:39+0100",
comments = "version: , compiler: javac, environment: Java 1.8.0_181 (Oracle Corporation)"
date = "2019-01-27T12:40:32+0100",
comments = "version: , compiler: Eclipse JDT (Batch) 1.2.100.v20160418-1457, environment: Java 1.8.0_181 (Oracle Corporation)"
)
public class UserMapperImpl implements UserMapper {
@ -44,8 +44,9 @@ public class UserMapperImpl implements UserMapper {
else {
user.setSettings( null );
}
if ( userDTOContactDataDTOPreferences( userDTO ) != null ) {
for ( String contactDataDTOPreference : userDTOContactDataDTOPreferences( userDTO ) ) {
List<String> preferences = userDTOContactDataDTOPreferences( userDTO );
if ( preferences != null ) {
for ( String contactDataDTOPreference : preferences ) {
user.addPreference( contactDataDTOPreference );
}
}
@ -71,8 +72,9 @@ public class UserMapperImpl implements UserMapper {
if ( settings1 != null ) {
user.setSettings( Arrays.copyOf( settings1, settings1.length ) );
}
if ( userDTOContactDataDTOPreferences( userDTO ) != null ) {
for ( String contactDataDTOPreference : userDTOContactDataDTOPreferences( userDTO ) ) {
List<String> preferences = userDTOContactDataDTOPreferences( userDTO );
if ( preferences != null ) {
for ( String contactDataDTOPreference : preferences ) {
user.addPreference( contactDataDTOPreference );
}
}
@ -106,8 +108,9 @@ public class UserMapperImpl implements UserMapper {
else {
user.setSettings( new String[0] );
}
if ( userDTOContactDataDTOPreferences( userDTO ) != null ) {
for ( String contactDataDTOPreference : userDTOContactDataDTOPreferences( userDTO ) ) {
List<String> preferences = userDTOContactDataDTOPreferences( userDTO );
if ( preferences != null ) {
for ( String contactDataDTOPreference : preferences ) {
user.addPreference( contactDataDTOPreference );
}
}