diff --git a/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc b/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc index 730433639d..54906f7893 100644 --- a/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc +++ b/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc @@ -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 bean mapping via `@BeanMapping#ignoreUnmappedSourceProperties()`, it takes precedence over both `@Mapper#unmappedSourcePolicy()` and the option. |`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 diff --git a/documentation/src/main/asciidoc/chapter-3-defining-a-mapper.asciidoc b/documentation/src/main/asciidoc/chapter-3-defining-a-mapper.asciidoc index 9d5124ee97..4b7b1ffc0f 100644 --- a/documentation/src/main/asciidoc/chapter-3-defining-a-mapper.asciidoc +++ b/documentation/src/main/asciidoc/chapter-3-defining-a-mapper.asciidoc @@ -532,7 +532,7 @@ Otherwise, you would need to write a custom `BuilderProvider` [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 set pass the MapStruct processor option `mapstruct.disableBuilders` to the compiler. e.g. `-Amapstruct.disableBuilders=true`. ==== [[mapping-with-constructors]] diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java index 952257753a..0cc6b7cce3 100644 --- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java @@ -87,6 +87,7 @@ MappingProcessor.UNMAPPED_SOURCE_POLICY, MappingProcessor.DEFAULT_COMPONENT_MODEL, MappingProcessor.DEFAULT_INJECTION_STRATEGY, + MappingProcessor.DISABLE_BUILDERS, MappingProcessor.VERBOSE }) 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_INJECTION_STRATEGY = "mapstruct.defaultInjectionStrategy"; 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"; private Options options; @@ -130,6 +132,7 @@ public synchronized void init(ProcessingEnvironment processingEnv) { processingEnv.getElementUtils(), processingEnv.getTypeUtils(), processingEnv.getMessager(), + options.isDisableBuilders(), options.isVerbose() ); } @@ -146,6 +149,7 @@ private Options createOptions() { processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ), processingEnv.getOptions().get( DEFAULT_INJECTION_STRATEGY ), Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ), + Boolean.valueOf( processingEnv.getOptions().get( DISABLE_BUILDERS ) ), Boolean.valueOf( processingEnv.getOptions().get( VERBOSE ) ) ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java b/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java index 46a90d4b43..65089cc139 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java @@ -21,13 +21,16 @@ public class Options { private final boolean alwaysGenerateSpi; private final String defaultComponentModel; private final String defaultInjectionStrategy; + private final boolean disableBuilders; private final boolean verbose; public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment, ReportingPolicyGem unmappedTargetPolicy, ReportingPolicyGem unmappedSourcePolicy, String defaultComponentModel, String defaultInjectionStrategy, - boolean alwaysGenerateSpi, boolean verbose) { + boolean alwaysGenerateSpi, + boolean disableBuilders, + boolean verbose) { this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; this.suppressGeneratorVersionComment = suppressGeneratorVersionComment; this.unmappedTargetPolicy = unmappedTargetPolicy; @@ -35,6 +38,7 @@ public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVers this.defaultComponentModel = defaultComponentModel; this.defaultInjectionStrategy = defaultInjectionStrategy; this.alwaysGenerateSpi = alwaysGenerateSpi; + this.disableBuilders = disableBuilders; this.verbose = verbose; } @@ -66,6 +70,10 @@ public boolean isAlwaysGenerateSpi() { return alwaysGenerateSpi; } + public boolean isDisableBuilders() { + return disableBuilders; + } + public boolean isVerbose() { return verbose; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java index 86fb7e3092..7421dfde7a 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java @@ -31,6 +31,7 @@ import org.mapstruct.ap.spi.ImmutablesAccessorNamingStrategy; import org.mapstruct.ap.spi.ImmutablesBuilderProvider; 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"). @@ -51,14 +52,17 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen private Elements elementUtils; private Types typeUtils; private Messager messager; + private boolean disableBuilder; 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( findAstModifyingAnnotationProcessors( messager ) ); this.elementUtils = elementUtils; this.typeUtils = typeUtils; this.messager = messager; + this.disableBuilder = disableBuilder; this.verbose = verbose; } @@ -103,7 +107,9 @@ else if ( elementUtils.getTypeElement( FreeBuilderConstants.FREE_BUILDER_FQN ) ! + 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 ); if ( verbose ) { messager.printMessage( diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/off/SimpleNotRealyImmutableBuilderTest.java b/processor/src/test/java/org/mapstruct/ap/test/builder/off/SimpleNotRealyImmutableBuilderTest.java index cc11a8fcdb..aa880ee97b 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/builder/off/SimpleNotRealyImmutableBuilderTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/off/SimpleNotRealyImmutableBuilderTest.java @@ -9,12 +9,14 @@ import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption; import org.mapstruct.ap.testutil.runner.GeneratedSource; import org.mapstruct.factory.Mappers; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; -@IssueKey("1743") +@IssueKey("1661") @WithClasses({ SimpleMutablePerson.class, SimpleNotRealyImmutablePerson.class @@ -36,4 +38,18 @@ public void testSimpleImmutableBuilderHappyPath() { 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" ); + + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/off/SimpleWithBuilderMapper.java b/processor/src/test/java/org/mapstruct/ap/test/builder/off/SimpleWithBuilderMapper.java new file mode 100644 index 0000000000..6df547db78 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/off/SimpleWithBuilderMapper.java @@ -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); +}