Refactor options and add an enum (#3877)

This commit is contained in:
Filip Hrisafov 2025-06-01 07:52:18 +02:00 committed by GitHub
parent 9847eaf195
commit 46ce011e4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 127 additions and 124 deletions

View File

@ -13,17 +13,16 @@ import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
@ -35,9 +34,8 @@ import javax.lang.model.util.ElementKindVisitor6;
import javax.tools.Diagnostic.Kind;
import org.mapstruct.ap.internal.gem.MapperGem;
import org.mapstruct.ap.internal.gem.NullValueMappingStrategyGem;
import org.mapstruct.ap.internal.gem.ReportingPolicyGem;
import org.mapstruct.ap.internal.model.Mapper;
import org.mapstruct.ap.internal.option.MappingOption;
import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.processor.DefaultModelElementProcessorContext;
import org.mapstruct.ap.internal.processor.ModelElementProcessor;
@ -84,19 +82,6 @@ import static javax.lang.model.element.ElementKind.CLASS;
* @author Gunnar Morling
*/
@SupportedAnnotationTypes("org.mapstruct.Mapper")
@SupportedOptions({
MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP,
MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT,
MappingProcessor.UNMAPPED_TARGET_POLICY,
MappingProcessor.UNMAPPED_SOURCE_POLICY,
MappingProcessor.DEFAULT_COMPONENT_MODEL,
MappingProcessor.DEFAULT_INJECTION_STRATEGY,
MappingProcessor.DISABLE_BUILDERS,
MappingProcessor.VERBOSE,
MappingProcessor.NULL_VALUE_ITERABLE_MAPPING_STRATEGY,
MappingProcessor.NULL_VALUE_MAP_MAPPING_STRATEGY,
MappingProcessor.DISABLE_LIFECYCLE_OVERLOAD_DEDUPLICATE_SELECTOR,
})
public class MappingProcessor extends AbstractProcessor {
/**
@ -104,20 +89,32 @@ public class MappingProcessor extends AbstractProcessor {
*/
private static final boolean ANNOTATIONS_CLAIMED_EXCLUSIVELY = false;
protected static final String SUPPRESS_GENERATOR_TIMESTAMP = "mapstruct.suppressGeneratorTimestamp";
protected static final String SUPPRESS_GENERATOR_VERSION_INFO_COMMENT =
"mapstruct.suppressGeneratorVersionInfoComment";
protected static final String UNMAPPED_TARGET_POLICY = "mapstruct.unmappedTargetPolicy";
protected static final String UNMAPPED_SOURCE_POLICY = "mapstruct.unmappedSourcePolicy";
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";
protected static final String NULL_VALUE_ITERABLE_MAPPING_STRATEGY = "mapstruct.nullValueIterableMappingStrategy";
protected static final String NULL_VALUE_MAP_MAPPING_STRATEGY = "mapstruct.nullValueMapMappingStrategy";
protected static final String DISABLE_LIFECYCLE_OVERLOAD_DEDUPLICATE_SELECTOR =
"mapstruct.disableLifecycleOverloadDeduplicateSelector";
// CHECKSTYLE:OFF
// Deprecated options, kept for backwards compatibility.
// They will be removed in a future release.
@Deprecated
protected static final String SUPPRESS_GENERATOR_TIMESTAMP = MappingOption.SUPPRESS_GENERATOR_TIMESTAMP.getOptionName();
@Deprecated
protected static final String SUPPRESS_GENERATOR_VERSION_INFO_COMMENT = MappingOption.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT.getOptionName();
@Deprecated
protected static final String UNMAPPED_TARGET_POLICY = MappingOption.UNMAPPED_TARGET_POLICY.getOptionName();
@Deprecated
protected static final String UNMAPPED_SOURCE_POLICY = MappingOption.UNMAPPED_SOURCE_POLICY.getOptionName();
@Deprecated
protected static final String DEFAULT_COMPONENT_MODEL = MappingOption.DEFAULT_COMPONENT_MODEL.getOptionName();
@Deprecated
protected static final String DEFAULT_INJECTION_STRATEGY = MappingOption.DEFAULT_INJECTION_STRATEGY.getOptionName();
@Deprecated
protected static final String ALWAYS_GENERATE_SERVICE_FILE = MappingOption.ALWAYS_GENERATE_SERVICE_FILE.getOptionName();
@Deprecated
protected static final String DISABLE_BUILDERS = MappingOption.DISABLE_BUILDERS.getOptionName();
@Deprecated
protected static final String VERBOSE = MappingOption.VERBOSE.getOptionName();
@Deprecated
protected static final String NULL_VALUE_ITERABLE_MAPPING_STRATEGY = MappingOption.NULL_VALUE_ITERABLE_MAPPING_STRATEGY.getOptionName();
@Deprecated
protected static final String NULL_VALUE_MAP_MAPPING_STRATEGY = MappingOption.NULL_VALUE_MAP_MAPPING_STRATEGY.getOptionName();
// CHECKSTYLE:ON
private final Set<String> additionalSupportedOptions;
private final String additionalSupportedOptionsError;
@ -156,7 +153,7 @@ public class MappingProcessor extends AbstractProcessor {
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init( processingEnv );
options = createOptions();
options = new Options( processingEnv.getOptions() );
annotationProcessorContext = new AnnotationProcessorContext(
processingEnv.getElementUtils(),
processingEnv.getTypeUtils(),
@ -171,34 +168,6 @@ public class MappingProcessor extends AbstractProcessor {
}
}
private Options createOptions() {
String unmappedTargetPolicy = processingEnv.getOptions().get( UNMAPPED_TARGET_POLICY );
String unmappedSourcePolicy = processingEnv.getOptions().get( UNMAPPED_SOURCE_POLICY );
String nullValueIterableMappingStrategy = processingEnv.getOptions()
.get( NULL_VALUE_ITERABLE_MAPPING_STRATEGY );
String nullValueMapMappingStrategy = processingEnv.getOptions().get( NULL_VALUE_MAP_MAPPING_STRATEGY );
String disableLifecycleOverloadDeduplicateSelector = processingEnv.getOptions()
.get( DISABLE_LIFECYCLE_OVERLOAD_DEDUPLICATE_SELECTOR );
return new Options(
Boolean.parseBoolean( processingEnv.getOptions().get( SUPPRESS_GENERATOR_TIMESTAMP ) ),
Boolean.parseBoolean( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ),
unmappedTargetPolicy != null ? ReportingPolicyGem.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
unmappedSourcePolicy != null ? ReportingPolicyGem.valueOf( unmappedSourcePolicy.toUpperCase() ) : null,
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
processingEnv.getOptions().get( DEFAULT_INJECTION_STRATEGY ),
Boolean.parseBoolean( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ),
Boolean.parseBoolean( processingEnv.getOptions().get( DISABLE_BUILDERS ) ),
Boolean.parseBoolean( processingEnv.getOptions().get( VERBOSE ) ),
nullValueIterableMappingStrategy != null ?
NullValueMappingStrategyGem.valueOf( nullValueIterableMappingStrategy.toUpperCase( Locale.ROOT ) ) :
null,
nullValueMapMappingStrategy != null ?
NullValueMappingStrategyGem.valueOf( nullValueMapMappingStrategy.toUpperCase( Locale.ROOT ) ) : null,
Boolean.parseBoolean( disableLifecycleOverloadDeduplicateSelector )
);
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
@ -259,13 +228,11 @@ public class MappingProcessor extends AbstractProcessor {
@Override
public Set<String> getSupportedOptions() {
Set<String> supportedOptions = super.getSupportedOptions();
if ( additionalSupportedOptions.isEmpty() ) {
return supportedOptions;
}
Set<String> allSupportedOptions = new HashSet<>( supportedOptions );
allSupportedOptions.addAll( additionalSupportedOptions );
return allSupportedOptions;
return Stream.concat(
Stream.of( MappingOption.values() ).map( MappingOption::getOptionName ),
additionalSupportedOptions.stream()
)
.collect( Collectors.toSet() );
}
/**

View File

@ -56,16 +56,18 @@ public class DefaultOptions extends DelegatingOptions {
@Override
public ReportingPolicyGem unmappedTargetPolicy() {
if ( options.getUnmappedTargetPolicy() != null ) {
return options.getUnmappedTargetPolicy();
ReportingPolicyGem unmappedTargetPolicy = options.getUnmappedTargetPolicy();
if ( unmappedTargetPolicy != null ) {
return unmappedTargetPolicy;
}
return ReportingPolicyGem.valueOf( mapper.unmappedTargetPolicy().getDefaultValue() );
}
@Override
public ReportingPolicyGem unmappedSourcePolicy() {
if ( options.getUnmappedSourcePolicy() != null ) {
return options.getUnmappedSourcePolicy();
ReportingPolicyGem unmappedSourcePolicy = options.getUnmappedSourcePolicy();
if ( unmappedSourcePolicy != null ) {
return unmappedSourcePolicy;
}
return ReportingPolicyGem.valueOf( mapper.unmappedSourcePolicy().getDefaultValue() );
}
@ -77,8 +79,9 @@ public class DefaultOptions extends DelegatingOptions {
@Override
public String componentModel() {
if ( options.getDefaultComponentModel() != null ) {
return options.getDefaultComponentModel();
String defaultComponentModel = options.getDefaultComponentModel();
if ( defaultComponentModel != null ) {
return defaultComponentModel;
}
return mapper.componentModel().getDefaultValue();
}
@ -97,8 +100,9 @@ public class DefaultOptions extends DelegatingOptions {
@Override
public InjectionStrategyGem getInjectionStrategy() {
if ( options.getDefaultInjectionStrategy() != null ) {
return InjectionStrategyGem.valueOf( options.getDefaultInjectionStrategy().toUpperCase() );
String defaultInjectionStrategy = options.getDefaultInjectionStrategy();
if ( defaultInjectionStrategy != null ) {
return InjectionStrategyGem.valueOf( defaultInjectionStrategy.toUpperCase() );
}
return InjectionStrategyGem.valueOf( mapper.injectionStrategy().getDefaultValue() );
}

View File

@ -0,0 +1,43 @@
/*
* 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.internal.option;
/**
* @author Filip Hrisafov
*/
public enum MappingOption {
// CHECKSTYLE:OFF
SUPPRESS_GENERATOR_TIMESTAMP( "mapstruct.suppressGeneratorTimestamp" ),
SUPPRESS_GENERATOR_VERSION_INFO_COMMENT( "mapstruct.suppressGeneratorVersionInfoComment" ),
UNMAPPED_TARGET_POLICY("mapstruct.unmappedTargetPolicy"),
UNMAPPED_SOURCE_POLICY("mapstruct.unmappedSourcePolicy"),
DEFAULT_COMPONENT_MODEL("mapstruct.defaultComponentModel"),
DEFAULT_INJECTION_STRATEGY("mapstruct.defaultInjectionStrategy"),
ALWAYS_GENERATE_SERVICE_FILE("mapstruct.alwaysGenerateServicesFile"),
DISABLE_BUILDERS("mapstruct.disableBuilders"),
VERBOSE("mapstruct.verbose"),
NULL_VALUE_ITERABLE_MAPPING_STRATEGY("mapstruct.nullValueIterableMappingStrategy"),
NULL_VALUE_MAP_MAPPING_STRATEGY("mapstruct.nullValueMapMappingStrategy"),
DISABLE_LIFECYCLE_OVERLOAD_DEDUPLICATE_SELECTOR("mapstruct.disableLifecycleOverloadDeduplicateSelector"),
;
// CHECKSTYLE:ON
private final String optionName;
MappingOption(String optionName) {
this.optionName = optionName;
}
/**
* Returns the name of the option, which can be used in the compiler arguments.
*
* @return the name of the option
*/
public String getOptionName() {
return optionName;
}
}

View File

@ -5,6 +5,9 @@
*/
package org.mapstruct.ap.internal.option;
import java.util.Locale;
import java.util.Map;
import org.mapstruct.ap.internal.gem.NullValueMappingStrategyGem;
import org.mapstruct.ap.internal.gem.ReportingPolicyGem;
@ -13,93 +16,79 @@ import org.mapstruct.ap.internal.gem.ReportingPolicyGem;
*
* @author Andreas Gudian
* @author Gunnar Morling
* @author Filip Hrisafov
*/
public class Options {
private final boolean suppressGeneratorTimestamp;
private final boolean suppressGeneratorVersionComment;
private final ReportingPolicyGem unmappedTargetPolicy;
private final ReportingPolicyGem unmappedSourcePolicy;
private final boolean alwaysGenerateSpi;
private final String defaultComponentModel;
private final String defaultInjectionStrategy;
private final boolean disableBuilders;
private final boolean verbose;
private final NullValueMappingStrategyGem nullValueIterableMappingStrategy;
private final NullValueMappingStrategyGem nullValueMapMappingStrategy;
private final boolean disableLifecycleOverloadDeduplicateSelector;
//CHECKSTYLE:OFF
public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment,
ReportingPolicyGem unmappedTargetPolicy,
ReportingPolicyGem unmappedSourcePolicy,
String defaultComponentModel, String defaultInjectionStrategy,
boolean alwaysGenerateSpi,
boolean disableBuilders,
boolean verbose,
NullValueMappingStrategyGem nullValueIterableMappingStrategy,
NullValueMappingStrategyGem nullValueMapMappingStrategy,
boolean disableLifecycleOverloadDeduplicateSelector
) {
//CHECKSTYLE:ON
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
this.suppressGeneratorVersionComment = suppressGeneratorVersionComment;
this.unmappedTargetPolicy = unmappedTargetPolicy;
this.unmappedSourcePolicy = unmappedSourcePolicy;
this.defaultComponentModel = defaultComponentModel;
this.defaultInjectionStrategy = defaultInjectionStrategy;
this.alwaysGenerateSpi = alwaysGenerateSpi;
this.disableBuilders = disableBuilders;
this.verbose = verbose;
this.nullValueIterableMappingStrategy = nullValueIterableMappingStrategy;
this.nullValueMapMappingStrategy = nullValueMapMappingStrategy;
this.disableLifecycleOverloadDeduplicateSelector = disableLifecycleOverloadDeduplicateSelector;
private final Map<String, String> options;
public Options(Map<String, String> options) {
this.options = options;
}
public boolean isSuppressGeneratorTimestamp() {
return suppressGeneratorTimestamp;
return parseBoolean( MappingOption.SUPPRESS_GENERATOR_TIMESTAMP );
}
public boolean isSuppressGeneratorVersionComment() {
return suppressGeneratorVersionComment;
return parseBoolean( MappingOption.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT );
}
public ReportingPolicyGem getUnmappedTargetPolicy() {
return unmappedTargetPolicy;
return parseEnum( MappingOption.UNMAPPED_TARGET_POLICY, ReportingPolicyGem.class );
}
public ReportingPolicyGem getUnmappedSourcePolicy() {
return unmappedSourcePolicy;
return parseEnum( MappingOption.UNMAPPED_SOURCE_POLICY, ReportingPolicyGem.class );
}
public String getDefaultComponentModel() {
return defaultComponentModel;
return options.get( MappingOption.DEFAULT_COMPONENT_MODEL.getOptionName() );
}
public String getDefaultInjectionStrategy() {
return defaultInjectionStrategy;
return options.get( MappingOption.DEFAULT_INJECTION_STRATEGY.getOptionName() );
}
public boolean isAlwaysGenerateSpi() {
return alwaysGenerateSpi;
return parseBoolean( MappingOption.ALWAYS_GENERATE_SERVICE_FILE );
}
public boolean isDisableBuilders() {
return disableBuilders;
return parseBoolean( MappingOption.DISABLE_BUILDERS );
}
public boolean isVerbose() {
return verbose;
return parseBoolean( MappingOption.VERBOSE );
}
public NullValueMappingStrategyGem getNullValueIterableMappingStrategy() {
return nullValueIterableMappingStrategy;
return parseEnum( MappingOption.NULL_VALUE_ITERABLE_MAPPING_STRATEGY, NullValueMappingStrategyGem.class );
}
public NullValueMappingStrategyGem getNullValueMapMappingStrategy() {
return nullValueMapMappingStrategy;
return parseEnum( MappingOption.NULL_VALUE_MAP_MAPPING_STRATEGY, NullValueMappingStrategyGem.class );
}
public boolean isDisableLifecycleOverloadDeduplicateSelector() {
return disableLifecycleOverloadDeduplicateSelector;
return parseBoolean( MappingOption.DISABLE_LIFECYCLE_OVERLOAD_DEDUPLICATE_SELECTOR );
}
private boolean parseBoolean(MappingOption option) {
if ( options.isEmpty() ) {
return false;
}
return Boolean.parseBoolean( options.get( option.getOptionName() ) );
}
private <E extends Enum<E>> E parseEnum(MappingOption option, Class<E> enumType) {
if ( options.isEmpty() ) {
return null;
}
String value = options.get( option.getOptionName() );
if ( value == null ) {
return null;
}
return Enum.valueOf( enumType, value.toUpperCase( Locale.ROOT ) );
}
}