#1661 Add support for globally disabling builders

This commit is contained in:
Filip Hrisafov 2022-01-29 11:46:34 +01:00 committed by GitHub
parent aade31f095
commit 5f4d355838
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 5 deletions

View File

@ -260,6 +260,11 @@ Supported values are:
If a policy is given for a specific mapper via `@Mapper#unmappedSourcePolicy()`, the value from the annotation takes precedence. If a policy is given for a specific mapper via `@Mapper#unmappedSourcePolicy()`, the value from the annotation takes precedence.
If a policy is given for a specific bean mapping via `@BeanMapping#ignoreUnmappedSourceProperties()`, it takes precedence over both `@Mapper#unmappedSourcePolicy()` and the option. If a policy is given for a specific bean mapping via `@BeanMapping#ignoreUnmappedSourceProperties()`, it takes precedence over both `@Mapper#unmappedSourcePolicy()` and the option.
|`WARN` |`WARN`
|`mapstruct.
disableBuilders`
|If set to `true`, then MapStruct will not use builder patterns when doing the mapping. This is equivalent to doing `@Mapper( builder = @Builder( disableBuilder = true ) )` for all of your mappers.
|`false`
|=== |===
=== Using MapStruct with the Java Module System === Using MapStruct with the Java Module System

View File

@ -532,7 +532,7 @@ Otherwise, you would need to write a custom `BuilderProvider`
[TIP] [TIP]
==== ====
In case you want to disable using builders then you can use the `NoOpBuilderProvider` by creating a `org.mapstruct.ap.spi.BuilderProvider` file in the `META-INF/services` directory with `org.mapstruct.ap.spi.NoOpBuilderProvider` as it's content. In case you want to disable using builders then you can pass the MapStruct processor option `mapstruct.disableBuilders` to the compiler. e.g. `-Amapstruct.disableBuilders=true`.
==== ====
[[mapping-with-constructors]] [[mapping-with-constructors]]

View File

@ -87,6 +87,7 @@ import static javax.lang.model.element.ElementKind.CLASS;
MappingProcessor.UNMAPPED_SOURCE_POLICY, MappingProcessor.UNMAPPED_SOURCE_POLICY,
MappingProcessor.DEFAULT_COMPONENT_MODEL, MappingProcessor.DEFAULT_COMPONENT_MODEL,
MappingProcessor.DEFAULT_INJECTION_STRATEGY, MappingProcessor.DEFAULT_INJECTION_STRATEGY,
MappingProcessor.DISABLE_BUILDERS,
MappingProcessor.VERBOSE MappingProcessor.VERBOSE
}) })
public class MappingProcessor extends AbstractProcessor { public class MappingProcessor extends AbstractProcessor {
@ -104,6 +105,7 @@ public class MappingProcessor extends AbstractProcessor {
protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel"; protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel";
protected static final String DEFAULT_INJECTION_STRATEGY = "mapstruct.defaultInjectionStrategy"; protected static final String DEFAULT_INJECTION_STRATEGY = "mapstruct.defaultInjectionStrategy";
protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile"; protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile";
protected static final String DISABLE_BUILDERS = "mapstruct.disableBuilders";
protected static final String VERBOSE = "mapstruct.verbose"; protected static final String VERBOSE = "mapstruct.verbose";
private Options options; private Options options;
@ -130,6 +132,7 @@ public class MappingProcessor extends AbstractProcessor {
processingEnv.getElementUtils(), processingEnv.getElementUtils(),
processingEnv.getTypeUtils(), processingEnv.getTypeUtils(),
processingEnv.getMessager(), processingEnv.getMessager(),
options.isDisableBuilders(),
options.isVerbose() options.isVerbose()
); );
} }
@ -146,6 +149,7 @@ public class MappingProcessor extends AbstractProcessor {
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ), processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
processingEnv.getOptions().get( DEFAULT_INJECTION_STRATEGY ), processingEnv.getOptions().get( DEFAULT_INJECTION_STRATEGY ),
Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ), Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ),
Boolean.valueOf( processingEnv.getOptions().get( DISABLE_BUILDERS ) ),
Boolean.valueOf( processingEnv.getOptions().get( VERBOSE ) ) Boolean.valueOf( processingEnv.getOptions().get( VERBOSE ) )
); );
} }

View File

@ -21,13 +21,16 @@ public class Options {
private final boolean alwaysGenerateSpi; private final boolean alwaysGenerateSpi;
private final String defaultComponentModel; private final String defaultComponentModel;
private final String defaultInjectionStrategy; private final String defaultInjectionStrategy;
private final boolean disableBuilders;
private final boolean verbose; private final boolean verbose;
public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment, public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment,
ReportingPolicyGem unmappedTargetPolicy, ReportingPolicyGem unmappedTargetPolicy,
ReportingPolicyGem unmappedSourcePolicy, ReportingPolicyGem unmappedSourcePolicy,
String defaultComponentModel, String defaultInjectionStrategy, String defaultComponentModel, String defaultInjectionStrategy,
boolean alwaysGenerateSpi, boolean verbose) { boolean alwaysGenerateSpi,
boolean disableBuilders,
boolean verbose) {
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
this.suppressGeneratorVersionComment = suppressGeneratorVersionComment; this.suppressGeneratorVersionComment = suppressGeneratorVersionComment;
this.unmappedTargetPolicy = unmappedTargetPolicy; this.unmappedTargetPolicy = unmappedTargetPolicy;
@ -35,6 +38,7 @@ public class Options {
this.defaultComponentModel = defaultComponentModel; this.defaultComponentModel = defaultComponentModel;
this.defaultInjectionStrategy = defaultInjectionStrategy; this.defaultInjectionStrategy = defaultInjectionStrategy;
this.alwaysGenerateSpi = alwaysGenerateSpi; this.alwaysGenerateSpi = alwaysGenerateSpi;
this.disableBuilders = disableBuilders;
this.verbose = verbose; this.verbose = verbose;
} }
@ -66,6 +70,10 @@ public class Options {
return alwaysGenerateSpi; return alwaysGenerateSpi;
} }
public boolean isDisableBuilders() {
return disableBuilders;
}
public boolean isVerbose() { public boolean isVerbose() {
return verbose; return verbose;
} }

View File

@ -31,6 +31,7 @@ import org.mapstruct.ap.spi.FreeBuilderAccessorNamingStrategy;
import org.mapstruct.ap.spi.ImmutablesAccessorNamingStrategy; import org.mapstruct.ap.spi.ImmutablesAccessorNamingStrategy;
import org.mapstruct.ap.spi.ImmutablesBuilderProvider; import org.mapstruct.ap.spi.ImmutablesBuilderProvider;
import org.mapstruct.ap.spi.MapStructProcessingEnvironment; import org.mapstruct.ap.spi.MapStructProcessingEnvironment;
import org.mapstruct.ap.spi.NoOpBuilderProvider;
/** /**
* Keeps contextual data in the scope of the entire annotation processor ("application scope"). * Keeps contextual data in the scope of the entire annotation processor ("application scope").
@ -51,14 +52,17 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
private Elements elementUtils; private Elements elementUtils;
private Types typeUtils; private Types typeUtils;
private Messager messager; private Messager messager;
private boolean disableBuilder;
private boolean verbose; private boolean verbose;
public AnnotationProcessorContext(Elements elementUtils, Types typeUtils, Messager messager, boolean verbose) { public AnnotationProcessorContext(Elements elementUtils, Types typeUtils, Messager messager, boolean disableBuilder,
boolean verbose) {
astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList( astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList(
findAstModifyingAnnotationProcessors( messager ) ); findAstModifyingAnnotationProcessors( messager ) );
this.elementUtils = elementUtils; this.elementUtils = elementUtils;
this.typeUtils = typeUtils; this.typeUtils = typeUtils;
this.messager = messager; this.messager = messager;
this.disableBuilder = disableBuilder;
this.verbose = verbose; this.verbose = verbose;
} }
@ -103,7 +107,9 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
+ this.accessorNamingStrategy.getClass().getCanonicalName() + this.accessorNamingStrategy.getClass().getCanonicalName()
); );
} }
this.builderProvider = Services.get( BuilderProvider.class, defaultBuilderProvider ); this.builderProvider = this.disableBuilder ?
new NoOpBuilderProvider() :
Services.get( BuilderProvider.class, defaultBuilderProvider );
this.builderProvider.init( this ); this.builderProvider.init( this );
if ( verbose ) { if ( verbose ) {
messager.printMessage( messager.printMessage(

View File

@ -9,12 +9,13 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.ProcessorTest;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption;
import org.mapstruct.ap.testutil.runner.GeneratedSource; import org.mapstruct.ap.testutil.runner.GeneratedSource;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@IssueKey("1743") @IssueKey("1661")
@WithClasses({ @WithClasses({
SimpleMutablePerson.class, SimpleMutablePerson.class,
SimpleNotRealyImmutablePerson.class SimpleNotRealyImmutablePerson.class
@ -36,4 +37,18 @@ public class SimpleNotRealyImmutableBuilderTest {
assertThat( targetObject.getName() ).isEqualTo( "Bob" ); assertThat( targetObject.getName() ).isEqualTo( "Bob" );
} }
@ProcessorTest
@WithClasses({ SimpleWithBuilderMapper.class })
@ProcessorOption( name = "mapstruct.disableBuilders", value = "true")
public void builderGloballyDisabled() {
SimpleWithBuilderMapper mapper = Mappers.getMapper( SimpleWithBuilderMapper.class );
SimpleMutablePerson source = new SimpleMutablePerson();
source.setFullName( "Bob" );
SimpleNotRealyImmutablePerson targetObject = mapper.toNotRealyImmutable( source );
assertThat( targetObject.getName() ).isEqualTo( "Bob" );
}
} }

View File

@ -0,0 +1,17 @@
/*
* 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.builder.off;
import org.mapstruct.CollectionMappingStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface SimpleWithBuilderMapper {
@Mapping(target = "name", source = "fullName")
SimpleNotRealyImmutablePerson toNotRealyImmutable(SimpleMutablePerson source);
}