mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
* #37 Rudimentary logging in mapstruct * #37 Rudimentary logging in mapstruct changed order * #37 rework * #37 documentation * #37 comments * #37 docmentation revisited * #37 review comments * #37 unit test * #37 unit test fixing empty mapper * #37 rework comments christian * #37 adding deferred mapper logging * #37 adding unit test for deferred mapper logging * #37 processing comments Filip
This commit is contained in:
parent
bc010a52dc
commit
b53741d960
@ -223,6 +223,8 @@ When invoking javac directly, these options are passed to the compiler in the fo
|
|||||||
<version>${org.mapstruct.version}</version>
|
<version>${org.mapstruct.version}</version>
|
||||||
</path>
|
</path>
|
||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
|
<!-- due to problem in maven-compiler-plugin, for verbose mode add showWarnings -->
|
||||||
|
<showWarnings>true</showWarnings>
|
||||||
<compilerArgs>
|
<compilerArgs>
|
||||||
<compilerArg>
|
<compilerArg>
|
||||||
-Amapstruct.suppressGeneratorTimestamp=true
|
-Amapstruct.suppressGeneratorTimestamp=true
|
||||||
@ -230,6 +232,9 @@ When invoking javac directly, these options are passed to the compiler in the fo
|
|||||||
<compilerArg>
|
<compilerArg>
|
||||||
-Amapstruct.suppressGeneratorVersionInfoComment=true
|
-Amapstruct.suppressGeneratorVersionInfoComment=true
|
||||||
</compilerArg>
|
</compilerArg>
|
||||||
|
<compilerArg>
|
||||||
|
-Amapstruct.verbose=true
|
||||||
|
</compilerArg>
|
||||||
</compilerArgs>
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -246,7 +251,8 @@ When invoking javac directly, these options are passed to the compiler in the fo
|
|||||||
compileJava {
|
compileJava {
|
||||||
options.compilerArgs = [
|
options.compilerArgs = [
|
||||||
'-Amapstruct.suppressGeneratorTimestamp=true',
|
'-Amapstruct.suppressGeneratorTimestamp=true',
|
||||||
'-Amapstruct.suppressGeneratorVersionInfoComment=true'
|
'-Amapstruct.suppressGeneratorVersionInfoComment=true',
|
||||||
|
'-Amapstruct.verbose=true'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
@ -265,6 +271,10 @@ suppressGeneratorTimestamp`
|
|||||||
|If set to `true`, the creation of a time stamp in the `@Generated` annotation in the generated mapper classes is suppressed.
|
|If set to `true`, the creation of a time stamp in the `@Generated` annotation in the generated mapper classes is suppressed.
|
||||||
|`false`
|
|`false`
|
||||||
|
|
||||||
|
|`mapstruct.verbose`
|
||||||
|
|If set to `true`, MapStruct in which MapStruct logs its major decisions. Note, at the moment of writing in Maven, also `showWarnings` needs to be added due to a problem in the maven-compiler-plugin configuration.
|
||||||
|
|`false`
|
||||||
|
|
||||||
|`mapstruct.
|
|`mapstruct.
|
||||||
suppressGeneratorVersionInfoComment`
|
suppressGeneratorVersionInfoComment`
|
||||||
|If set to `true`, the creation of the `comment` attribute in the `@Generated` annotation in the generated mapper classes is suppressed. The comment contains information about the version of MapStruct and about the compiler used for the annotation processing.
|
|If set to `true`, the creation of the `comment` attribute in the `@Generated` annotation in the generated mapper classes is suppressed. The comment contains information about the version of MapStruct and about the compiler used for the annotation processing.
|
||||||
|
@ -82,7 +82,8 @@ import static javax.lang.model.element.ElementKind.CLASS;
|
|||||||
MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP,
|
MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP,
|
||||||
MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT,
|
MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT,
|
||||||
MappingProcessor.UNMAPPED_TARGET_POLICY,
|
MappingProcessor.UNMAPPED_TARGET_POLICY,
|
||||||
MappingProcessor.DEFAULT_COMPONENT_MODEL
|
MappingProcessor.DEFAULT_COMPONENT_MODEL,
|
||||||
|
MappingProcessor.VERBOSE
|
||||||
})
|
})
|
||||||
public class MappingProcessor extends AbstractProcessor {
|
public class MappingProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
protected static final String UNMAPPED_TARGET_POLICY = "mapstruct.unmappedTargetPolicy";
|
protected static final String UNMAPPED_TARGET_POLICY = "mapstruct.unmappedTargetPolicy";
|
||||||
protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel";
|
protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel";
|
||||||
protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile";
|
protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile";
|
||||||
|
protected static final String VERBOSE = "mapstruct.verbose";
|
||||||
|
|
||||||
private Options options;
|
private Options options;
|
||||||
|
|
||||||
@ -120,7 +122,9 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
options = createOptions();
|
options = createOptions();
|
||||||
annotationProcessorContext = new AnnotationProcessorContext(
|
annotationProcessorContext = new AnnotationProcessorContext(
|
||||||
processingEnv.getElementUtils(),
|
processingEnv.getElementUtils(),
|
||||||
processingEnv.getTypeUtils()
|
processingEnv.getTypeUtils(),
|
||||||
|
processingEnv.getMessager(),
|
||||||
|
options.isVerbose()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +136,8 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ),
|
Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ),
|
||||||
unmappedTargetPolicy != null ? ReportingPolicyPrism.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
|
unmappedTargetPolicy != null ? ReportingPolicyPrism.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
|
||||||
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
|
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
|
||||||
Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) )
|
Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ),
|
||||||
|
Boolean.valueOf( processingEnv.getOptions().get( VERBOSE ) )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +226,11 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
processMapperTypeElement( context, mapperElement );
|
processMapperTypeElement( context, mapperElement );
|
||||||
}
|
}
|
||||||
catch ( TypeHierarchyErroneousException thie ) {
|
catch ( TypeHierarchyErroneousException thie ) {
|
||||||
|
if ( options.isVerbose() ) {
|
||||||
|
processingEnv.getMessager().printMessage(
|
||||||
|
Kind.NOTE, "MapStruct: referred types not available (yet), deferring mapper: "
|
||||||
|
+ mapperElement );
|
||||||
|
}
|
||||||
deferredMappers.add( mapperElement );
|
deferredMappers.add( mapperElement );
|
||||||
}
|
}
|
||||||
catch ( Throwable t ) {
|
catch ( Throwable t ) {
|
||||||
@ -242,7 +252,7 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
thrown.printStackTrace( new PrintWriter( sw ) );
|
thrown.printStackTrace( new PrintWriter( sw ) );
|
||||||
|
|
||||||
String reportableStacktrace = sw.toString().replace( System.getProperty( "line.separator" ), " " );
|
String reportableStacktrace = sw.toString().replace( System.lineSeparator( ), " " );
|
||||||
|
|
||||||
processingEnv.getMessager().printMessage(
|
processingEnv.getMessager().printMessage(
|
||||||
Kind.ERROR, "Internal error in the mapping processor: " + reportableStacktrace, element );
|
Kind.ERROR, "Internal error in the mapping processor: " + reportableStacktrace, element );
|
||||||
|
@ -20,6 +20,7 @@ import org.mapstruct.ap.internal.model.source.ForgedMethod;
|
|||||||
import org.mapstruct.ap.internal.model.source.Method;
|
import org.mapstruct.ap.internal.model.source.Method;
|
||||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||||
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
||||||
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
import org.mapstruct.ap.internal.util.Strings;
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,6 +95,12 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
|
|||||||
|
|
||||||
if ( assignment == null ) {
|
if ( assignment == null ) {
|
||||||
assignment = forgeMapping( sourceRHS, sourceElementType, targetElementType );
|
assignment = forgeMapping( sourceRHS, sourceElementType, targetElementType );
|
||||||
|
if ( assignment != null ) {
|
||||||
|
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_CREATE_ELEMENT_NOTE, assignment );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_SELECT_ELEMENT_NOTE, assignment );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( assignment == null ) {
|
if ( assignment == null ) {
|
||||||
|
@ -23,6 +23,7 @@ import org.mapstruct.ap.internal.model.source.ForgedMethod;
|
|||||||
import org.mapstruct.ap.internal.model.source.Method;
|
import org.mapstruct.ap.internal.model.source.Method;
|
||||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||||
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
||||||
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
import org.mapstruct.ap.internal.util.Strings;
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,8 +99,13 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
|||||||
|
|
||||||
if ( keyAssignment == null ) {
|
if ( keyAssignment == null ) {
|
||||||
keyAssignment = forgeMapping( keySourceRHS, keySourceType, keyTargetType );
|
keyAssignment = forgeMapping( keySourceRHS, keySourceType, keyTargetType );
|
||||||
|
if ( keyAssignment != null ) {
|
||||||
|
ctx.getMessager().note( 2, Message.MAPMAPPING_CREATE_KEY_NOTE, keyAssignment );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_KEY_NOTE, keyAssignment );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( keyAssignment == null ) {
|
if ( keyAssignment == null ) {
|
||||||
if ( method instanceof ForgedMethod ) {
|
if ( method instanceof ForgedMethod ) {
|
||||||
@ -150,6 +156,12 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
|||||||
|
|
||||||
if ( valueAssignment == null ) {
|
if ( valueAssignment == null ) {
|
||||||
valueAssignment = forgeMapping( valueSourceRHS, valueSourceType, valueTargetType );
|
valueAssignment = forgeMapping( valueSourceRHS, valueSourceType, valueTargetType );
|
||||||
|
if ( valueAssignment != null ) {
|
||||||
|
ctx.getMessager().note( 2, Message.MAPMAPPING_CREATE_VALUE_NOTE, valueAssignment );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_VALUE_NOTE, valueAssignment );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( valueAssignment == null ) {
|
if ( valueAssignment == null ) {
|
||||||
|
@ -10,6 +10,7 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.model.common.Assignment;
|
import org.mapstruct.ap.internal.model.common.Assignment;
|
||||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||||
@ -19,6 +20,7 @@ import org.mapstruct.ap.internal.model.common.ParameterBinding;
|
|||||||
import org.mapstruct.ap.internal.model.common.Type;
|
import org.mapstruct.ap.internal.model.common.Type;
|
||||||
import org.mapstruct.ap.internal.model.source.Method;
|
import org.mapstruct.ap.internal.model.source.Method;
|
||||||
import org.mapstruct.ap.internal.model.source.builtin.BuiltInMethod;
|
import org.mapstruct.ap.internal.model.source.builtin.BuiltInMethod;
|
||||||
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a reference to another method, e.g. used to map a bean property from source to target type or to
|
* Represents a reference to another method, e.g. used to map a bean property from source to target type or to
|
||||||
@ -348,4 +350,15 @@ public class MethodReference extends ModelElement implements Assignment {
|
|||||||
return new MethodReference( methodName, null, false );
|
return new MethodReference( methodName, null, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String mapper = declaringMapper != null ? declaringMapper.getType().getName().toString() : "";
|
||||||
|
String argument = getAssignment() != null ? getAssignment().toString() : getSourceReference();
|
||||||
|
String returnTypeAsString = returnType != null ? returnType.toString() : "";
|
||||||
|
List<String> arguments = sourceParameters.stream()
|
||||||
|
.map( p -> p.isMappingContext() || p.isMappingTarget() || p.isTargetType() ? p.getName() : argument )
|
||||||
|
.collect( Collectors.toList() );
|
||||||
|
|
||||||
|
return returnTypeAsString + " " + mapper + "#" + name + "(" + Strings.join( arguments, "," ) + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,6 +295,9 @@ public class PropertyMapping extends ModelElement {
|
|||||||
|
|
||||||
// handle source
|
// handle source
|
||||||
this.rightHandSide = getSourceRHS( sourceReference );
|
this.rightHandSide = getSourceRHS( sourceReference );
|
||||||
|
|
||||||
|
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_MAPPING_NOTE, rightHandSide, targetWriteAccessor );
|
||||||
|
|
||||||
rightHandSide.setUseElementAsSourceTypeForMatching(
|
rightHandSide.setUseElementAsSourceTypeForMatching(
|
||||||
targetWriteAccessorType == TargetWriteAccessorType.ADDER );
|
targetWriteAccessorType == TargetWriteAccessorType.ADDER );
|
||||||
|
|
||||||
@ -339,6 +342,12 @@ public class PropertyMapping extends ModelElement {
|
|||||||
else {
|
else {
|
||||||
assignment = forgeMapping( rightHandSide );
|
assignment = forgeMapping( rightHandSide );
|
||||||
}
|
}
|
||||||
|
if ( assignment != null ) {
|
||||||
|
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_CREATE_NOTE, assignment );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_SELECT_NOTE, assignment );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( assignment != null ) {
|
if ( assignment != null ) {
|
||||||
|
@ -140,4 +140,10 @@ public class TypeConversion extends ModelElement implements Assignment {
|
|||||||
public boolean isCallingUpdateMethod() {
|
public boolean isCallingUpdateMethod() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String argument = getAssignment() != null ? getAssignment().toString() : getSourceReference();
|
||||||
|
return openExpression + argument + closeExpression;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,17 @@ public class Options {
|
|||||||
private final ReportingPolicyPrism unmappedTargetPolicy;
|
private final ReportingPolicyPrism unmappedTargetPolicy;
|
||||||
private final boolean alwaysGenerateSpi;
|
private final boolean alwaysGenerateSpi;
|
||||||
private final String defaultComponentModel;
|
private final String defaultComponentModel;
|
||||||
|
private final boolean verbose;
|
||||||
|
|
||||||
public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment,
|
public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment,
|
||||||
ReportingPolicyPrism unmappedTargetPolicy,
|
ReportingPolicyPrism unmappedTargetPolicy,
|
||||||
String defaultComponentModel, boolean alwaysGenerateSpi) {
|
String defaultComponentModel, boolean alwaysGenerateSpi, boolean verbose) {
|
||||||
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
|
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
|
||||||
this.suppressGeneratorVersionComment = suppressGeneratorVersionComment;
|
this.suppressGeneratorVersionComment = suppressGeneratorVersionComment;
|
||||||
this.unmappedTargetPolicy = unmappedTargetPolicy;
|
this.unmappedTargetPolicy = unmappedTargetPolicy;
|
||||||
this.defaultComponentModel = defaultComponentModel;
|
this.defaultComponentModel = defaultComponentModel;
|
||||||
this.alwaysGenerateSpi = alwaysGenerateSpi;
|
this.alwaysGenerateSpi = alwaysGenerateSpi;
|
||||||
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSuppressGeneratorTimestamp() {
|
public boolean isSuppressGeneratorTimestamp() {
|
||||||
@ -49,4 +51,8 @@ public class Options {
|
|||||||
public boolean isAlwaysGenerateSpi() {
|
public boolean isAlwaysGenerateSpi() {
|
||||||
return alwaysGenerateSpi;
|
return alwaysGenerateSpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isVerbose() {
|
||||||
|
return verbose;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package org.mapstruct.ap.internal.processor;
|
package org.mapstruct.ap.internal.processor;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
import javax.annotation.processing.Filer;
|
import javax.annotation.processing.Filer;
|
||||||
import javax.annotation.processing.Messager;
|
import javax.annotation.processing.Messager;
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
@ -45,7 +46,7 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
|||||||
RoundContext roundContext, Map<String, String> notToBeImported) {
|
RoundContext roundContext, Map<String, String> notToBeImported) {
|
||||||
|
|
||||||
this.processingEnvironment = processingEnvironment;
|
this.processingEnvironment = processingEnvironment;
|
||||||
this.messager = new DelegatingMessager( processingEnvironment.getMessager() );
|
this.messager = new DelegatingMessager( processingEnvironment.getMessager(), options.isVerbose() );
|
||||||
this.accessorNaming = roundContext.getAnnotationProcessorContext().getAccessorNaming();
|
this.accessorNaming = roundContext.getAnnotationProcessorContext().getAccessorNaming();
|
||||||
this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment );
|
this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment );
|
||||||
this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation );
|
this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation );
|
||||||
@ -108,9 +109,11 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
|||||||
|
|
||||||
private final Messager delegate;
|
private final Messager delegate;
|
||||||
private boolean isErroneous = false;
|
private boolean isErroneous = false;
|
||||||
|
private final boolean verbose;
|
||||||
|
|
||||||
DelegatingMessager(Messager delegate) {
|
DelegatingMessager(Messager delegate, boolean verbose) {
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -155,6 +158,15 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void note( int level, Message msg, Object... args ) {
|
||||||
|
if ( verbose ) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
IntStream.range( 0, level ).mapToObj( i -> "-" ).forEach( builder::append );
|
||||||
|
builder.append( " MapStruct: " ).append( String.format( msg.getDescription(), args ) );
|
||||||
|
delegate.printMessage( Kind.NOTE, builder.toString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isErroneous() {
|
public boolean isErroneous() {
|
||||||
return isErroneous;
|
return isErroneous;
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,9 @@ import org.mapstruct.ap.internal.model.MappingMethod;
|
|||||||
import org.mapstruct.ap.internal.model.StreamMappingMethod;
|
import org.mapstruct.ap.internal.model.StreamMappingMethod;
|
||||||
import org.mapstruct.ap.internal.model.SupportingConstructorFragment;
|
import org.mapstruct.ap.internal.model.SupportingConstructorFragment;
|
||||||
import org.mapstruct.ap.internal.model.ValueMappingMethod;
|
import org.mapstruct.ap.internal.model.ValueMappingMethod;
|
||||||
|
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||||
import org.mapstruct.ap.internal.model.common.Type;
|
import org.mapstruct.ap.internal.model.common.Type;
|
||||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
|
||||||
import org.mapstruct.ap.internal.model.source.MappingOptions;
|
import org.mapstruct.ap.internal.model.source.MappingOptions;
|
||||||
import org.mapstruct.ap.internal.model.source.Method;
|
import org.mapstruct.ap.internal.model.source.Method;
|
||||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||||
@ -286,6 +286,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
boolean hasFactoryMethod = false;
|
boolean hasFactoryMethod = false;
|
||||||
|
|
||||||
if ( method.isIterableMapping() ) {
|
if ( method.isIterableMapping() ) {
|
||||||
|
this.messager.note( 1, Message.ITERABLEMAPPING_CREATE_NOTE, method );
|
||||||
IterableMappingMethod iterableMappingMethod = createWithElementMappingMethod(
|
IterableMappingMethod iterableMappingMethod = createWithElementMappingMethod(
|
||||||
method,
|
method,
|
||||||
mappingOptions,
|
mappingOptions,
|
||||||
@ -313,6 +314,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
nullValueMappingStrategy = mappingOptions.getMapMapping().getNullValueMappingStrategy();
|
nullValueMappingStrategy = mappingOptions.getMapMapping().getNullValueMappingStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.messager.note( 1, Message.MAPMAPPING_CREATE_NOTE, method );
|
||||||
MapMappingMethod mapMappingMethod = builder
|
MapMappingMethod mapMappingMethod = builder
|
||||||
.mappingContext( mappingContext )
|
.mappingContext( mappingContext )
|
||||||
.method( method )
|
.method( method )
|
||||||
@ -328,6 +330,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
else if ( method.isValueMapping() ) {
|
else if ( method.isValueMapping() ) {
|
||||||
// prefer value mappings over enum mapping
|
// prefer value mappings over enum mapping
|
||||||
|
this.messager.note( 1, Message.VALUEMAPPING_CREATE_NOTE, method );
|
||||||
ValueMappingMethod valueMappingMethod = new ValueMappingMethod.Builder()
|
ValueMappingMethod valueMappingMethod = new ValueMappingMethod.Builder()
|
||||||
.mappingContext( mappingContext )
|
.mappingContext( mappingContext )
|
||||||
.method( method )
|
.method( method )
|
||||||
@ -352,6 +355,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( method.isStreamMapping() ) {
|
else if ( method.isStreamMapping() ) {
|
||||||
|
this.messager.note( 1, Message.STREAMMAPPING_CREATE_NOTE, method );
|
||||||
StreamMappingMethod streamMappingMethod = createWithElementMappingMethod(
|
StreamMappingMethod streamMappingMethod = createWithElementMappingMethod(
|
||||||
method,
|
method,
|
||||||
mappingOptions,
|
mappingOptions,
|
||||||
@ -364,8 +368,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
mappingMethods.add( streamMappingMethod );
|
mappingMethods.add( streamMappingMethod );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
this.messager.note( 1, Message.BEANMAPPING_CREATE_NOTE, method );
|
||||||
|
|
||||||
BeanMappingMethod.Builder builder = new BeanMappingMethod.Builder();
|
BeanMappingMethod.Builder builder = new BeanMappingMethod.Builder();
|
||||||
BeanMappingMethod beanMappingMethod = builder
|
BeanMappingMethod beanMappingMethod = builder
|
||||||
.mappingContext( mappingContext )
|
.mappingContext( mappingContext )
|
||||||
|
@ -72,8 +72,14 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
this.typeUtils = context.getTypeUtils();
|
this.typeUtils = context.getTypeUtils();
|
||||||
this.elementUtils = context.getElementUtils();
|
this.elementUtils = context.getElementUtils();
|
||||||
|
|
||||||
|
this.messager.note( 0, Message.PROCESSING_NOTE, mapperTypeElement );
|
||||||
|
|
||||||
MapperConfiguration mapperConfig = MapperConfiguration.getInstanceOn( mapperTypeElement );
|
MapperConfiguration mapperConfig = MapperConfiguration.getInstanceOn( mapperTypeElement );
|
||||||
|
|
||||||
|
if ( mapperConfig != null ) {
|
||||||
|
this.messager.note( 0, Message.CONFIG_NOTE, mapperConfig.getClass().getName() );
|
||||||
|
}
|
||||||
|
|
||||||
if ( !mapperConfig.isValid() ) {
|
if ( !mapperConfig.isValid() ) {
|
||||||
throw new AnnotationProcessingException(
|
throw new AnnotationProcessingException(
|
||||||
"Couldn't retrieve @Mapper annotation",
|
"Couldn't retrieve @Mapper annotation",
|
||||||
|
@ -10,8 +10,10 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
import javax.annotation.processing.Messager;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||||
import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
||||||
@ -39,12 +41,16 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
|
|||||||
private AccessorNamingUtils accessorNaming;
|
private AccessorNamingUtils accessorNaming;
|
||||||
private Elements elementUtils;
|
private Elements elementUtils;
|
||||||
private Types typeUtils;
|
private Types typeUtils;
|
||||||
|
private Messager messager;
|
||||||
|
private boolean verbose;
|
||||||
|
|
||||||
public AnnotationProcessorContext(Elements elementUtils, Types typeUtils) {
|
public AnnotationProcessorContext(Elements elementUtils, Types typeUtils, Messager messager, boolean verbose) {
|
||||||
astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList(
|
astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList(
|
||||||
findAstModifyingAnnotationProcessors() );
|
findAstModifyingAnnotationProcessors() );
|
||||||
this.elementUtils = elementUtils;
|
this.elementUtils = elementUtils;
|
||||||
this.typeUtils = typeUtils;
|
this.typeUtils = typeUtils;
|
||||||
|
this.messager = messager;
|
||||||
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,10 +70,16 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
|
|||||||
if ( elementUtils.getTypeElement( ImmutablesConstants.IMMUTABLE_FQN ) != null ) {
|
if ( elementUtils.getTypeElement( ImmutablesConstants.IMMUTABLE_FQN ) != null ) {
|
||||||
defaultAccessorNamingStrategy = new ImmutablesAccessorNamingStrategy();
|
defaultAccessorNamingStrategy = new ImmutablesAccessorNamingStrategy();
|
||||||
defaultBuilderProvider = new ImmutablesBuilderProvider();
|
defaultBuilderProvider = new ImmutablesBuilderProvider();
|
||||||
|
if ( verbose ) {
|
||||||
|
messager.printMessage( Diagnostic.Kind.NOTE, "MapStruct: Immutables found on classpath" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( elementUtils.getTypeElement( FreeBuilderConstants.FREE_BUILDER_FQN ) != null ) {
|
else if ( elementUtils.getTypeElement( FreeBuilderConstants.FREE_BUILDER_FQN ) != null ) {
|
||||||
defaultAccessorNamingStrategy = new FreeBuilderAccessorNamingStrategy();
|
defaultAccessorNamingStrategy = new FreeBuilderAccessorNamingStrategy();
|
||||||
defaultBuilderProvider = new DefaultBuilderProvider();
|
defaultBuilderProvider = new DefaultBuilderProvider();
|
||||||
|
if ( verbose ) {
|
||||||
|
messager.printMessage( Diagnostic.Kind.NOTE, "MapStruct: Freebuilder found on classpath" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
defaultAccessorNamingStrategy = new DefaultAccessorNamingStrategy();
|
defaultAccessorNamingStrategy = new DefaultAccessorNamingStrategy();
|
||||||
@ -75,8 +87,21 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
|
|||||||
}
|
}
|
||||||
this.accessorNamingStrategy = Services.get( AccessorNamingStrategy.class, defaultAccessorNamingStrategy );
|
this.accessorNamingStrategy = Services.get( AccessorNamingStrategy.class, defaultAccessorNamingStrategy );
|
||||||
this.accessorNamingStrategy.init( this );
|
this.accessorNamingStrategy.init( this );
|
||||||
|
if ( verbose ) {
|
||||||
|
messager.printMessage(
|
||||||
|
Diagnostic.Kind.NOTE,
|
||||||
|
"MapStruct: Using accessor naming strategy: "
|
||||||
|
+ this.accessorNamingStrategy.getClass().getCanonicalName()
|
||||||
|
);
|
||||||
|
}
|
||||||
this.builderProvider = Services.get( BuilderProvider.class, defaultBuilderProvider );
|
this.builderProvider = Services.get( BuilderProvider.class, defaultBuilderProvider );
|
||||||
this.builderProvider.init( this );
|
this.builderProvider.init( this );
|
||||||
|
if ( verbose ) {
|
||||||
|
messager.printMessage(
|
||||||
|
Diagnostic.Kind.NOTE,
|
||||||
|
"MapStruct: Using builder provider: " + this.builderProvider.getClass().getCanonicalName()
|
||||||
|
);
|
||||||
|
}
|
||||||
this.accessorNaming = new AccessorNamingUtils( this.accessorNamingStrategy );
|
this.accessorNaming = new AccessorNamingUtils( this.accessorNamingStrategy );
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
@ -67,4 +67,12 @@ public interface FormattingMessager {
|
|||||||
AnnotationValue v,
|
AnnotationValue v,
|
||||||
Message msg,
|
Message msg,
|
||||||
Object... args);
|
Object... args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just log as plain note
|
||||||
|
* @param level nesting level
|
||||||
|
* @param log the log message
|
||||||
|
* @param args the arguments
|
||||||
|
*/
|
||||||
|
void note(int level, Message log, Object... args);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,10 @@ import javax.tools.Diagnostic;
|
|||||||
public enum Message {
|
public enum Message {
|
||||||
|
|
||||||
// CHECKSTYLE:OFF
|
// CHECKSTYLE:OFF
|
||||||
|
PROCESSING_NOTE( "processing: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
CONFIG_NOTE( "applying mapper configuration: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
|
||||||
|
BEANMAPPING_CREATE_NOTE( "creating bean mapping method implementation for %s.", Diagnostic.Kind.NOTE ),
|
||||||
BEANMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'nullValuePropertyMappingStrategy', 'resultType' and 'qualifiedBy' are undefined in @BeanMapping, define at least one of them." ),
|
BEANMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'nullValuePropertyMappingStrategy', 'resultType' and 'qualifiedBy' are undefined in @BeanMapping, define at least one of them." ),
|
||||||
BEANMAPPING_NOT_ASSIGNABLE( "%s not assignable to: %s." ),
|
BEANMAPPING_NOT_ASSIGNABLE( "%s not assignable to: %s." ),
|
||||||
BEANMAPPING_ABSTRACT( "The result type %s may not be an abstract class nor interface." ),
|
BEANMAPPING_ABSTRACT( "The result type %s may not be an abstract class nor interface." ),
|
||||||
@ -31,6 +35,9 @@ public enum Message {
|
|||||||
BEANMAPPING_CYCLE_BETWEEN_PROPERTIES( "Cycle(s) between properties given via dependsOn(): %s." ),
|
BEANMAPPING_CYCLE_BETWEEN_PROPERTIES( "Cycle(s) between properties given via dependsOn(): %s." ),
|
||||||
BEANMAPPING_UNKNOWN_PROPERTY_IN_DEPENDS_ON( "\"%s\" is no property of the method return type." ),
|
BEANMAPPING_UNKNOWN_PROPERTY_IN_DEPENDS_ON( "\"%s\" is no property of the method return type." ),
|
||||||
|
|
||||||
|
PROPERTYMAPPING_MAPPING_NOTE( "mapping property: %s to: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
PROPERTYMAPPING_CREATE_NOTE( "creating property mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
PROPERTYMAPPING_SELECT_NOTE( "selecting property mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
PROPERTYMAPPING_MAPPING_NOT_FOUND( "Can't map %s to \"%s %s\". Consider to declare/implement a mapping method: \"%s map(%s value)\"." ),
|
PROPERTYMAPPING_MAPPING_NOT_FOUND( "Can't map %s to \"%s %s\". Consider to declare/implement a mapping method: \"%s map(%s value)\"." ),
|
||||||
PROPERTYMAPPING_FORGED_MAPPING_NOT_FOUND( "Can't map %s to %s. Consider to implement a mapping method: \"%s map(%s value)\"." ),
|
PROPERTYMAPPING_FORGED_MAPPING_NOT_FOUND( "Can't map %s to %s. Consider to implement a mapping method: \"%s map(%s value)\"." ),
|
||||||
PROPERTYMAPPING_DUPLICATE_TARGETS( "Target property \"%s\" must not be mapped more than once." ),
|
PROPERTYMAPPING_DUPLICATE_TARGETS( "Target property \"%s\" must not be mapped more than once." ),
|
||||||
@ -67,10 +74,19 @@ public enum Message {
|
|||||||
CONSTANTMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE( "No read accessor found for property \"%s\" in target type." ),
|
CONSTANTMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE( "No read accessor found for property \"%s\" in target type." ),
|
||||||
CONSTANTMAPPING_NON_EXISTING_CONSTANT( "Constant %s doesn't exist in enum type %s for property \"%s\"." ),
|
CONSTANTMAPPING_NON_EXISTING_CONSTANT( "Constant %s doesn't exist in enum type %s for property \"%s\"." ),
|
||||||
|
|
||||||
|
MAPMAPPING_CREATE_NOTE( "creating map mapping method implementation for %s.", Diagnostic.Kind.NOTE ),
|
||||||
MAPMAPPING_KEY_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source key type to target key type." ),
|
MAPMAPPING_KEY_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source key type to target key type." ),
|
||||||
MAPMAPPING_VALUE_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source value type to target value type." ),
|
MAPMAPPING_VALUE_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source value type to target value type." ),
|
||||||
MAPMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'keyDateFormat', 'keyQualifiedBy', 'keyTargetType', 'valueDateFormat', 'valueQualfiedBy' and 'valueTargetType' are all undefined in @MapMapping, define at least one of them." ),
|
MAPMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'keyDateFormat', 'keyQualifiedBy', 'keyTargetType', 'valueDateFormat', 'valueQualfiedBy' and 'valueTargetType' are all undefined in @MapMapping, define at least one of them." ),
|
||||||
|
MAPMAPPING_SELECT_KEY_NOTE( "selecting key mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
MAPMAPPING_SELECT_VALUE_NOTE( "selecting value mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
MAPMAPPING_CREATE_KEY_NOTE( "creating key mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
MAPMAPPING_CREATE_VALUE_NOTE( "creating value mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
|
||||||
|
STREAMMAPPING_CREATE_NOTE( "creating stream mapping method implementation for %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
ITERABLEMAPPING_CREATE_NOTE( "creating iterable mapping method implementation for %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
ITERABLEMAPPING_SELECT_ELEMENT_NOTE( "selecting element mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
|
ITERABLEMAPPING_CREATE_ELEMENT_NOTE( "creating element mapping: %s.", Diagnostic.Kind.NOTE ),
|
||||||
ITERABLEMAPPING_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source element type into target element type." ),
|
ITERABLEMAPPING_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source element type into target element type." ),
|
||||||
ITERABLEMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy','dateformat', 'qualifiedBy' and 'elementTargetType' are undefined in @IterableMapping, define at least one of them." ),
|
ITERABLEMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy','dateformat', 'qualifiedBy' and 'elementTargetType' are undefined in @IterableMapping, define at least one of them." ),
|
||||||
|
|
||||||
@ -128,6 +144,7 @@ public enum Message {
|
|||||||
INHERITINVERSECONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH( "More than one configuration prototype method is applicable. Use @InheritInverseConfiguration to select one of them explicitly: %s." ),
|
INHERITINVERSECONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH( "More than one configuration prototype method is applicable. Use @InheritInverseConfiguration to select one of them explicitly: %s." ),
|
||||||
INHERITCONFIGURATION_CYCLE( "Cycle detected while evaluating inherited configurations. Inheritance path: %s" ),
|
INHERITCONFIGURATION_CYCLE( "Cycle detected while evaluating inherited configurations. Inheritance path: %s" ),
|
||||||
|
|
||||||
|
VALUEMAPPING_CREATE_NOTE( "creating value mapping method implementation for %s.", Diagnostic.Kind.NOTE ),
|
||||||
VALUEMAPPING_DUPLICATE_SOURCE( "Source value mapping: \"%s\" cannot be mapped more than once." ),
|
VALUEMAPPING_DUPLICATE_SOURCE( "Source value mapping: \"%s\" cannot be mapped more than once." ),
|
||||||
VALUEMAPPING_ANY_AREADY_DEFINED( "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" can only be used once." ),
|
VALUEMAPPING_ANY_AREADY_DEFINED( "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" can only be used once." ),
|
||||||
VALUE_MAPPING_UNMAPPED_SOURCES( "The following constants from the %s enum have no corresponding constant in the %s enum and must be be mapped via adding additional mappings: %s." ),
|
VALUE_MAPPING_UNMAPPED_SOURCES( "The following constants from the %s enum have no corresponding constant in the %s enum and must be be mapped via adding additional mappings: %s." ),
|
||||||
|
@ -28,4 +28,9 @@ public class ExecutableElementAccessor extends AbstractAccessor<ExecutableElemen
|
|||||||
public ExecutableElement getExecutable() {
|
public ExecutableElement getExecutable() {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return element.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,4 +29,9 @@ public class VariableElementAccessor extends AbstractAccessor<VariableElement> {
|
|||||||
public ExecutableElement getExecutable() {
|
public ExecutableElement getExecutable() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return element.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ class IndentationCorrectingWriter extends Writer {
|
|||||||
* Set to true to enable output of written characters on the console.
|
* Set to true to enable output of written characters on the console.
|
||||||
*/
|
*/
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
|
private static final String LINE_SEPARATOR = System.lineSeparator( );
|
||||||
private static final boolean IS_WINDOWS = System.getProperty( "os.name" ).startsWith( "Windows" );
|
private static final boolean IS_WINDOWS = System.getProperty( "os.name" ).startsWith( "Windows" );
|
||||||
|
|
||||||
private State currentState = State.START_OF_LINE;
|
private State currentState = State.START_OF_LINE;
|
||||||
|
@ -280,4 +280,5 @@ public class DefaultBuilderProvider implements BuilderProvider {
|
|||||||
protected boolean shouldIgnore(TypeElement typeElement) {
|
protected boolean shouldIgnore(TypeElement typeElement) {
|
||||||
return typeElement == null || JAVA_JAVAX_PACKAGE.matcher( typeElement.getQualifiedName() ).matches();
|
return typeElement == null || JAVA_JAVAX_PACKAGE.matcher( typeElement.getQualifiedName() ).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,4 +35,5 @@ public class FreeBuilderAccessorNamingStrategy extends DefaultAccessorNamingStra
|
|||||||
// with set
|
// with set
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,5 @@ public class ImmutablesAccessorNamingStrategy extends DefaultAccessorNamingStrat
|
|||||||
protected boolean isFluentSetter(ExecutableElement method) {
|
protected boolean isFluentSetter(ExecutableElement method) {
|
||||||
return super.isFluentSetter( method ) && !method.getSimpleName().toString().equals( "from" );
|
return super.isFluentSetter( method ) && !method.getSimpleName().toString().equals( "from" );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -83,4 +83,5 @@ public class ImmutablesBuilderProvider extends DefaultBuilderProvider {
|
|||||||
builderQualifiedName.append( "Immutable" ).append( typeElement.getSimpleName() );
|
builderQualifiedName.append( "Immutable" ).append( typeElement.getSimpleName() );
|
||||||
return elementUtils.getTypeElement( builderQualifiedName );
|
return elementUtils.getTypeElement( builderQualifiedName );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,5 +23,6 @@ public class NoOpBuilderProvider implements BuilderProvider {
|
|||||||
public BuilderInfo findBuilderInfo(TypeMirror type) {
|
public BuilderInfo findBuilderInfo(TypeMirror type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// end::documentation[]
|
// end::documentation[]
|
||||||
|
@ -153,6 +153,11 @@ public class DefaultConversionContextTest {
|
|||||||
lastKindPrinted = msg.getDiagnosticKind();
|
lastKindPrinted = msg.getDiagnosticKind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void note(int level, Message msg, Object... args) {
|
||||||
|
throw new UnsupportedOperationException( "Should not be called" );
|
||||||
|
}
|
||||||
|
|
||||||
public Diagnostic.Kind getLastKindPrinted() {
|
public Diagnostic.Kind getLastKindPrinted() {
|
||||||
return lastKindPrinted;
|
return lastKindPrinted;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
||||||
|
|
||||||
|
public class AstModifyingAnnotationProcessorSaysNo implements AstModifyingAnnotationProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTypeComplete(TypeMirror type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CreateBeanMapping {
|
||||||
|
|
||||||
|
CreateBeanMapping INSTANCE = Mappers.getMapper( CreateBeanMapping.class );
|
||||||
|
|
||||||
|
Target map(Source source);
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
private NestedSource nested;
|
||||||
|
|
||||||
|
public NestedSource getNested() {
|
||||||
|
return nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNested(NestedSource nested) {
|
||||||
|
this.nested = nested;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
private NestedTarget nested;
|
||||||
|
|
||||||
|
public NestedTarget getNested() {
|
||||||
|
return nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNested(NestedTarget nested) {
|
||||||
|
this.nested = nested;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedSource {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedTarget {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CreateIterableMapping {
|
||||||
|
|
||||||
|
CreateIterableMapping INSTANCE = Mappers.getMapper( CreateIterableMapping.class );
|
||||||
|
|
||||||
|
List<TargetElement> map(List<SourceElement> source);
|
||||||
|
|
||||||
|
class SourceElement {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetElement {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CreateMapMapping {
|
||||||
|
|
||||||
|
CreateMapMapping INSTANCE = Mappers.getMapper( CreateMapMapping.class );
|
||||||
|
|
||||||
|
Map<TargetKey, TargetValue> map(Map<SourceKey, SourceValue> source);
|
||||||
|
|
||||||
|
// empty beans fail.. TODO check
|
||||||
|
class SourceKey {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceValue {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetKey {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetValue {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface SelectBeanMapping {
|
||||||
|
|
||||||
|
SelectBeanMapping INSTANCE = Mappers.getMapper( SelectBeanMapping.class );
|
||||||
|
|
||||||
|
Target map(Source source);
|
||||||
|
|
||||||
|
NestedTarget map(NestedSource source);
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
private NestedSource nested;
|
||||||
|
|
||||||
|
public NestedSource getNested() {
|
||||||
|
return nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNested(NestedSource nested) {
|
||||||
|
this.nested = nested;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
private NestedTarget nested;
|
||||||
|
|
||||||
|
public NestedTarget getNested() {
|
||||||
|
return nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNested(NestedTarget nested) {
|
||||||
|
this.nested = nested;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedSource {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedTarget {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface SelectIterableMapping {
|
||||||
|
|
||||||
|
SelectIterableMapping INSTANCE = Mappers.getMapper( SelectIterableMapping.class );
|
||||||
|
|
||||||
|
List<TargetElement> map(List<SourceElement> source);
|
||||||
|
|
||||||
|
default TargetElement map(SourceElement sourceKey) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceElement {
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetElement {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface SelectMapMapping {
|
||||||
|
|
||||||
|
SelectMapMapping INSTANCE = Mappers.getMapper( SelectMapMapping.class );
|
||||||
|
|
||||||
|
Map<TargetKey, TargetValue> map(Map<SourceKey, SourceValue> source);
|
||||||
|
|
||||||
|
default TargetKey map(SourceKey sourceKey) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default TargetValue map(SourceValue sourceValue) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceKey {
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceValue {
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetKey {
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetValue {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface SelectStreamMapping {
|
||||||
|
|
||||||
|
SelectStreamMapping INSTANCE = Mappers.getMapper( SelectStreamMapping.class );
|
||||||
|
|
||||||
|
Stream<TargetElement> map(Stream<SourceElement> source);
|
||||||
|
|
||||||
|
default TargetElement map(SourceElement sourceKey) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceElement {
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetElement {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ValueMapping {
|
||||||
|
|
||||||
|
ValueMapping INSTANCE = Mappers.getMapper( ValueMapping.class );
|
||||||
|
|
||||||
|
TargetEnum map(SourceEnum source);
|
||||||
|
|
||||||
|
enum TargetEnum { VALUE }
|
||||||
|
|
||||||
|
enum SourceEnum { VALUE }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* 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.verbose;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||||
|
import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
||||||
|
import org.mapstruct.ap.spi.BuilderProvider;
|
||||||
|
import org.mapstruct.ap.spi.ImmutablesAccessorNamingStrategy;
|
||||||
|
import org.mapstruct.ap.spi.ImmutablesBuilderProvider;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.WithServiceImplementation;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedNote;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
import org.mapstruct.ap.testutil.runner.Compiler;
|
||||||
|
import org.mapstruct.ap.testutil.runner.DisabledOnCompiler;
|
||||||
|
|
||||||
|
@IssueKey("37")
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
public class VerboseTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(CreateBeanMapping.class)
|
||||||
|
@ExpectedNote("^MapStruct: Using accessor naming strategy:.*DefaultAccessorNamingStrategy.*$")
|
||||||
|
@ExpectedNote("^MapStruct: Using builder provider:.*DefaultBuilderProvider.*$")
|
||||||
|
@ExpectedNote("^ MapStruct: processing:.*.CreateBeanMapping.*$")
|
||||||
|
@ExpectedNote("^ MapStruct: applying mapper configuration:.*MapperConfiguration.*$")
|
||||||
|
public void testGeneralMessages() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@WithServiceImplementation(provides = BuilderProvider.class, value = ImmutablesBuilderProvider.class)
|
||||||
|
@WithServiceImplementation(provides = AccessorNamingStrategy.class, value = ImmutablesAccessorNamingStrategy.class)
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(CreateBeanMapping.class)
|
||||||
|
@ExpectedNote("^MapStruct: Using accessor naming strategy:.*ImmutablesAccessorNamingStrategy.*$")
|
||||||
|
@ExpectedNote("^MapStruct: Using builder provider:.*ImmutablesBuilderProvider.*$")
|
||||||
|
@ExpectedNote("^ MapStruct: processing:.*.CreateBeanMapping.*$")
|
||||||
|
@ExpectedNote("^ MapStruct: applying mapper configuration:.*MapperConfiguration.*$")
|
||||||
|
public void testGeneralWithOtherSPI() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@WithServiceImplementation(provides = AstModifyingAnnotationProcessor.class,
|
||||||
|
value = AstModifyingAnnotationProcessorSaysNo.class)
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(CreateBeanMapping.class)
|
||||||
|
@ExpectedNote("^MapStruct: referred types not available \\(yet\\), deferring mapper:.*CreateBeanMapping.*$")
|
||||||
|
public void testDeferred() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(CreateBeanMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating bean mapping method implementation for.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: creating property mapping.*$")
|
||||||
|
public void testCreateBeanMapping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(SelectBeanMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating bean mapping method implementation for.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: selecting property mapping.*$")
|
||||||
|
public void testSelectBeanMapping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(ValueMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating value mapping method implementation for.*$")
|
||||||
|
public void testValueMapping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(CreateIterableMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating iterable mapping method implementation for.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: creating element mapping.*$")
|
||||||
|
public void testVerboseCreateIterableMapping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(SelectIterableMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating iterable mapping method implementation for.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: selecting element mapping.*$")
|
||||||
|
public void testVerboseSelectingIterableMapping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(SelectStreamMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating stream mapping method implementation for.*$")
|
||||||
|
public void testVerboseSelectingStreamMapping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(CreateMapMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating map mapping method implementation for.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: creating key mapping.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: creating value mapping.*$")
|
||||||
|
public void testVerboseCreateMapMapping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisabledOnCompiler( Compiler.ECLIPSE )
|
||||||
|
@ProcessorOption(name = "mapstruct.verbose", value = "true")
|
||||||
|
@WithClasses(SelectMapMapping.class)
|
||||||
|
@ExpectedNote("^- MapStruct: creating map mapping method implementation for.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: selecting key mapping.*$")
|
||||||
|
@ExpectedNote("^-- MapStruct: selecting value mapping.*$")
|
||||||
|
public void testVerboseSelectingMapMapping() {
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
package org.mapstruct.ap.testutil;
|
package org.mapstruct.ap.testutil;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
@ -17,6 +18,7 @@ import java.lang.annotation.Target;
|
|||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
|
@Repeatable( WithServiceImplementations.class )
|
||||||
public @interface WithServiceImplementation {
|
public @interface WithServiceImplementation {
|
||||||
/**
|
/**
|
||||||
* @return The service implementation class that is to be made available during the annotation processing.
|
* @return The service implementation class that is to be made available during the annotation processing.
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.testutil.compilation.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An expected {@link javax.tools.Diagnostic.Kind#NOTE}.
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Repeatable(ExpectedNote.ExpectedNotes.class)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface ExpectedNote {
|
||||||
|
|
||||||
|
String value();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The notes in the order they are expected
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface ExpectedNotes {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regexp for the note to match.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ExpectedNote[] value();
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,8 @@ package org.mapstruct.ap.testutil.compilation.model;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
@ -17,6 +19,7 @@ import org.codehaus.plexus.compiler.CompilerMessage;
|
|||||||
import org.codehaus.plexus.compiler.CompilerResult;
|
import org.codehaus.plexus.compiler.CompilerResult;
|
||||||
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
||||||
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedNote;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the outcome of a compilation.
|
* Represents the outcome of a compilation.
|
||||||
@ -25,21 +28,37 @@ import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutco
|
|||||||
*/
|
*/
|
||||||
public class CompilationOutcomeDescriptor {
|
public class CompilationOutcomeDescriptor {
|
||||||
|
|
||||||
|
private static final String LINE_SEPARATOR = System.lineSeparator( );
|
||||||
|
|
||||||
private CompilationResult compilationResult;
|
private CompilationResult compilationResult;
|
||||||
private List<DiagnosticDescriptor> diagnostics;
|
private List<DiagnosticDescriptor> diagnostics;
|
||||||
|
private List<String> notes;
|
||||||
|
|
||||||
private CompilationOutcomeDescriptor(CompilationResult compilationResult,
|
private CompilationOutcomeDescriptor(CompilationResult compilationResult,
|
||||||
List<DiagnosticDescriptor> diagnostics) {
|
List<DiagnosticDescriptor> diagnostics,
|
||||||
|
List<String> notes) {
|
||||||
this.compilationResult = compilationResult;
|
this.compilationResult = compilationResult;
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
|
this.notes = notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompilationOutcomeDescriptor forExpectedCompilationResult(
|
public static CompilationOutcomeDescriptor forExpectedCompilationResult(
|
||||||
ExpectedCompilationOutcome expectedCompilationResult) {
|
ExpectedCompilationOutcome expectedCompilationResult, ExpectedNote.ExpectedNotes expectedNotes,
|
||||||
|
ExpectedNote expectedNote) {
|
||||||
|
List<String> notes = new ArrayList<>();
|
||||||
|
if ( expectedNotes != null ) {
|
||||||
|
notes.addAll( Stream.of( expectedNotes.value() )
|
||||||
|
.map( ExpectedNote::value )
|
||||||
|
.collect( Collectors.toList() ) );
|
||||||
|
}
|
||||||
|
if ( expectedNote != null ) {
|
||||||
|
notes.add( expectedNote.value() );
|
||||||
|
}
|
||||||
if ( expectedCompilationResult == null ) {
|
if ( expectedCompilationResult == null ) {
|
||||||
return new CompilationOutcomeDescriptor(
|
return new CompilationOutcomeDescriptor(
|
||||||
CompilationResult.SUCCEEDED,
|
CompilationResult.SUCCEEDED,
|
||||||
Collections.<DiagnosticDescriptor>emptyList()
|
Collections.<DiagnosticDescriptor>emptyList(),
|
||||||
|
notes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -48,8 +67,7 @@ public class CompilationOutcomeDescriptor {
|
|||||||
expectedCompilationResult.diagnostics() ) {
|
expectedCompilationResult.diagnostics() ) {
|
||||||
diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( diagnostic ) );
|
diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( diagnostic ) );
|
||||||
}
|
}
|
||||||
|
return new CompilationOutcomeDescriptor( expectedCompilationResult.value(), diagnosticDescriptors, notes );
|
||||||
return new CompilationOutcomeDescriptor( expectedCompilationResult.value(), diagnosticDescriptors );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,31 +75,34 @@ public class CompilationOutcomeDescriptor {
|
|||||||
List<Diagnostic<? extends JavaFileObject>> diagnostics) {
|
List<Diagnostic<? extends JavaFileObject>> diagnostics) {
|
||||||
CompilationResult compilationResult =
|
CompilationResult compilationResult =
|
||||||
compilationSuccessful ? CompilationResult.SUCCEEDED : CompilationResult.FAILED;
|
compilationSuccessful ? CompilationResult.SUCCEEDED : CompilationResult.FAILED;
|
||||||
|
List<String> notes = new ArrayList<>();
|
||||||
List<DiagnosticDescriptor> diagnosticDescriptors = new ArrayList<DiagnosticDescriptor>();
|
List<DiagnosticDescriptor> diagnosticDescriptors = new ArrayList<DiagnosticDescriptor>();
|
||||||
for ( Diagnostic<? extends JavaFileObject> diagnostic : diagnostics ) {
|
for ( Diagnostic<? extends JavaFileObject> diagnostic : diagnostics ) {
|
||||||
//ignore notes created by the compiler
|
//ignore notes created by the compiler
|
||||||
if ( diagnostic.getKind() != Kind.NOTE ) {
|
if ( diagnostic.getKind() != Kind.NOTE ) {
|
||||||
diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( sourceDir, diagnostic ) );
|
diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( sourceDir, diagnostic ) );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
notes.add( diagnostic.getMessage( null ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CompilationOutcomeDescriptor( compilationResult, diagnosticDescriptors );
|
return new CompilationOutcomeDescriptor( compilationResult, diagnosticDescriptors, notes );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompilationOutcomeDescriptor forResult(String sourceDir, CompilerResult compilerResult) {
|
public static CompilationOutcomeDescriptor forResult(String sourceDir, CompilerResult compilerResult) {
|
||||||
CompilationResult compilationResult =
|
CompilationResult compilationResult =
|
||||||
compilerResult.isSuccess() ? CompilationResult.SUCCEEDED : CompilationResult.FAILED;
|
compilerResult.isSuccess() ? CompilationResult.SUCCEEDED : CompilationResult.FAILED;
|
||||||
|
|
||||||
List<DiagnosticDescriptor> diagnosticDescriptors = new ArrayList<DiagnosticDescriptor>();
|
List<DiagnosticDescriptor> diagnosticDescriptors = new ArrayList<DiagnosticDescriptor>();
|
||||||
|
|
||||||
for ( CompilerMessage message : compilerResult.getCompilerMessages() ) {
|
for ( CompilerMessage message : compilerResult.getCompilerMessages() ) {
|
||||||
if ( message.getKind() != CompilerMessage.Kind.NOTE ) {
|
if ( message.getKind() != CompilerMessage.Kind.NOTE ) {
|
||||||
diagnosticDescriptors.add( DiagnosticDescriptor.forCompilerMessage( sourceDir, message ) );
|
diagnosticDescriptors.add( DiagnosticDescriptor.forCompilerMessage( sourceDir, message ) );
|
||||||
}
|
}
|
||||||
|
// the eclipse compiler does not support NOTE (it is never actually set).
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CompilationOutcomeDescriptor( compilationResult, diagnosticDescriptors );
|
return new CompilationOutcomeDescriptor( compilationResult, diagnosticDescriptors, Collections.emptyList() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompilationResult getCompilationResult() {
|
public CompilationResult getCompilationResult() {
|
||||||
@ -92,6 +113,10 @@ public class CompilationOutcomeDescriptor {
|
|||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getNotes() {
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.junit.runners.model.FrameworkMethod;
|
import org.junit.runners.model.FrameworkMethod;
|
||||||
import org.junit.runners.model.Statement;
|
import org.junit.runners.model.Statement;
|
||||||
@ -32,6 +33,7 @@ import org.mapstruct.ap.testutil.WithServiceImplementations;
|
|||||||
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
||||||
import org.mapstruct.ap.testutil.compilation.annotation.DisableCheckstyle;
|
import org.mapstruct.ap.testutil.compilation.annotation.DisableCheckstyle;
|
||||||
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedNote;
|
||||||
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption;
|
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption;
|
||||||
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOptions;
|
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOptions;
|
||||||
import org.mapstruct.ap.testutil.compilation.model.CompilationOutcomeDescriptor;
|
import org.mapstruct.ap.testutil.compilation.model.CompilationOutcomeDescriptor;
|
||||||
@ -54,7 +56,7 @@ abstract class CompilingStatement extends Statement {
|
|||||||
|
|
||||||
private static final String TARGET_COMPILATION_TESTS = "/target/compilation-tests/";
|
private static final String TARGET_COMPILATION_TESTS = "/target/compilation-tests/";
|
||||||
|
|
||||||
private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
|
private static final String LINE_SEPARATOR = System.lineSeparator( );
|
||||||
|
|
||||||
private static final DiagnosticDescriptorComparator COMPARATOR = new DiagnosticDescriptorComparator();
|
private static final DiagnosticDescriptorComparator COMPARATOR = new DiagnosticDescriptorComparator();
|
||||||
|
|
||||||
@ -175,7 +177,9 @@ abstract class CompilingStatement extends Statement {
|
|||||||
|
|
||||||
CompilationOutcomeDescriptor expectedResult =
|
CompilationOutcomeDescriptor expectedResult =
|
||||||
CompilationOutcomeDescriptor.forExpectedCompilationResult(
|
CompilationOutcomeDescriptor.forExpectedCompilationResult(
|
||||||
method.getAnnotation( ExpectedCompilationOutcome.class )
|
method.getAnnotation( ExpectedCompilationOutcome.class ),
|
||||||
|
method.getAnnotation( ExpectedNote.ExpectedNotes.class ),
|
||||||
|
method.getAnnotation( ExpectedNote.class )
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( expectedResult.getCompilationResult() == CompilationResult.SUCCEEDED ) {
|
if ( expectedResult.getCompilationResult() == CompilationResult.SUCCEEDED ) {
|
||||||
@ -192,6 +196,7 @@ abstract class CompilingStatement extends Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertDiagnostics( actualResult.getDiagnostics(), expectedResult.getDiagnostics() );
|
assertDiagnostics( actualResult.getDiagnostics(), expectedResult.getDiagnostics() );
|
||||||
|
assertNotes( actualResult.getNotes(), expectedResult.getNotes() );
|
||||||
|
|
||||||
if ( runCheckstyle ) {
|
if ( runCheckstyle ) {
|
||||||
assertCheckstyleRules();
|
assertCheckstyleRules();
|
||||||
@ -239,6 +244,30 @@ abstract class CompilingStatement extends Statement {
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertNotes(List<String> actualNotes, List<String> expectedNotes) {
|
||||||
|
List<String> expectedNotesRemaining = new ArrayList<>( expectedNotes );
|
||||||
|
Iterator<String> expectedNotesIterator = expectedNotesRemaining.iterator();
|
||||||
|
if ( expectedNotesIterator.hasNext() ) {
|
||||||
|
String expectedNoteRegexp = expectedNotesIterator.next();
|
||||||
|
for ( String actualNote : actualNotes ) {
|
||||||
|
if ( actualNote.matches( expectedNoteRegexp ) ) {
|
||||||
|
expectedNotesIterator.remove();
|
||||||
|
if ( expectedNotesIterator.hasNext() ) {
|
||||||
|
expectedNoteRegexp = expectedNotesIterator.next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat( expectedNotesRemaining )
|
||||||
|
.describedAs( "There are unmatched notes: " +
|
||||||
|
expectedNotesRemaining.stream().collect( Collectors.joining( LINE_SEPARATOR ) ).toString() )
|
||||||
|
.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private void assertDiagnostics(List<DiagnosticDescriptor> actualDiagnostics,
|
private void assertDiagnostics(List<DiagnosticDescriptor> actualDiagnostics,
|
||||||
List<DiagnosticDescriptor> expectedDiagnostics) {
|
List<DiagnosticDescriptor> expectedDiagnostics) {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user