diff --git a/documentation/src/main/asciidoc/mapstruct-reference-guide.asciidoc b/documentation/src/main/asciidoc/mapstruct-reference-guide.asciidoc
index 79ce0dc09..c985a90ec 100644
--- a/documentation/src/main/asciidoc/mapstruct-reference-guide.asciidoc
+++ b/documentation/src/main/asciidoc/mapstruct-reference-guide.asciidoc
@@ -223,6 +223,8 @@ When invoking javac directly, these options are passed to the compiler in the fo
${org.mapstruct.version}
+
+ true
-Amapstruct.suppressGeneratorTimestamp=true
@@ -230,6 +232,9 @@ When invoking javac directly, these options are passed to the compiler in the fo
-Amapstruct.suppressGeneratorVersionInfoComment=true
+
+ -Amapstruct.verbose=true
+
@@ -246,7 +251,8 @@ When invoking javac directly, these options are passed to the compiler in the fo
compileJava {
options.compilerArgs = [
'-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.
|`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.
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.
diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
index dc565e13b..4878f3f98 100644
--- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
@@ -82,7 +82,8 @@ import static javax.lang.model.element.ElementKind.CLASS;
MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP,
MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT,
MappingProcessor.UNMAPPED_TARGET_POLICY,
- MappingProcessor.DEFAULT_COMPONENT_MODEL
+ MappingProcessor.DEFAULT_COMPONENT_MODEL,
+ MappingProcessor.VERBOSE
})
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 DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel";
protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile";
+ protected static final String VERBOSE = "mapstruct.verbose";
private Options options;
@@ -120,7 +122,9 @@ public class MappingProcessor extends AbstractProcessor {
options = createOptions();
annotationProcessorContext = new AnnotationProcessorContext(
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 ) ),
unmappedTargetPolicy != null ? ReportingPolicyPrism.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
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 );
}
catch ( TypeHierarchyErroneousException thie ) {
+ if ( options.isVerbose() ) {
+ processingEnv.getMessager().printMessage(
+ Kind.NOTE, "MapStruct: referred types not available (yet), deferring mapper: "
+ + mapperElement );
+ }
deferredMappers.add( mapperElement );
}
catch ( Throwable t ) {
@@ -242,7 +252,7 @@ public class MappingProcessor extends AbstractProcessor {
StringWriter sw = new StringWriter();
thrown.printStackTrace( new PrintWriter( sw ) );
- String reportableStacktrace = sw.toString().replace( System.getProperty( "line.separator" ), " " );
+ String reportableStacktrace = sw.toString().replace( System.lineSeparator( ), " " );
processingEnv.getMessager().printMessage(
Kind.ERROR, "Internal error in the mapping processor: " + reportableStacktrace, element );
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java b/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java
index c265d9daa..72a1eb29f 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java
@@ -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.SelectionParameters;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
+import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.Strings;
/**
@@ -94,6 +95,12 @@ public abstract class ContainerMappingMethodBuilder arguments = sourceParameters.stream()
+ .map( p -> p.isMappingContext() || p.isMappingTarget() || p.isTargetType() ? p.getName() : argument )
+ .collect( Collectors.toList() );
+
+ return returnTypeAsString + " " + mapper + "#" + name + "(" + Strings.join( arguments, "," ) + ")";
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java
index 229150403..423b5f4b4 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java
@@ -295,6 +295,9 @@ public class PropertyMapping extends ModelElement {
// handle source
this.rightHandSide = getSourceRHS( sourceReference );
+
+ ctx.getMessager().note( 2, Message.PROPERTYMAPPING_MAPPING_NOTE, rightHandSide, targetWriteAccessor );
+
rightHandSide.setUseElementAsSourceTypeForMatching(
targetWriteAccessorType == TargetWriteAccessorType.ADDER );
@@ -339,6 +342,12 @@ public class PropertyMapping extends ModelElement {
else {
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 ) {
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/TypeConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/model/TypeConversion.java
index d0481cdc2..3f06ce7e8 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/TypeConversion.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/TypeConversion.java
@@ -140,4 +140,10 @@ public class TypeConversion extends ModelElement implements Assignment {
public boolean isCallingUpdateMethod() {
return false;
}
+
+ @Override
+ public String toString() {
+ String argument = getAssignment() != null ? getAssignment().toString() : getSourceReference();
+ return openExpression + argument + closeExpression;
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java b/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java
index 77001c481..1e555e8d3 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/option/Options.java
@@ -19,15 +19,17 @@ public class Options {
private final ReportingPolicyPrism unmappedTargetPolicy;
private final boolean alwaysGenerateSpi;
private final String defaultComponentModel;
+ private final boolean verbose;
public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment,
ReportingPolicyPrism unmappedTargetPolicy,
- String defaultComponentModel, boolean alwaysGenerateSpi) {
+ String defaultComponentModel, boolean alwaysGenerateSpi, boolean verbose) {
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
this.suppressGeneratorVersionComment = suppressGeneratorVersionComment;
this.unmappedTargetPolicy = unmappedTargetPolicy;
this.defaultComponentModel = defaultComponentModel;
this.alwaysGenerateSpi = alwaysGenerateSpi;
+ this.verbose = verbose;
}
public boolean isSuppressGeneratorTimestamp() {
@@ -49,4 +51,8 @@ public class Options {
public boolean isAlwaysGenerateSpi() {
return alwaysGenerateSpi;
}
+
+ public boolean isVerbose() {
+ return verbose;
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java
index 5168dccc1..bc7374d39 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java
@@ -6,6 +6,7 @@
package org.mapstruct.ap.internal.processor;
import java.util.Map;
+import java.util.stream.IntStream;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
@@ -45,7 +46,7 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
RoundContext roundContext, Map notToBeImported) {
this.processingEnvironment = processingEnvironment;
- this.messager = new DelegatingMessager( processingEnvironment.getMessager() );
+ this.messager = new DelegatingMessager( processingEnvironment.getMessager(), options.isVerbose() );
this.accessorNaming = roundContext.getAnnotationProcessorContext().getAccessorNaming();
this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment );
this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation );
@@ -108,9 +109,11 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
private final Messager delegate;
private boolean isErroneous = false;
+ private final boolean verbose;
- DelegatingMessager(Messager delegate) {
+ DelegatingMessager(Messager delegate, boolean verbose) {
this.delegate = delegate;
+ this.verbose = verbose;
}
@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() {
return isErroneous;
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java
index 974822216..1b31bcf4c 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java
@@ -38,9 +38,9 @@ import org.mapstruct.ap.internal.model.MappingMethod;
import org.mapstruct.ap.internal.model.StreamMappingMethod;
import org.mapstruct.ap.internal.model.SupportingConstructorFragment;
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.TypeFactory;
-import org.mapstruct.ap.internal.model.common.FormattingParameters;
import org.mapstruct.ap.internal.model.source.MappingOptions;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
@@ -286,6 +286,7 @@ public class MapperCreationProcessor implements ModelElementProcessor\" or \"\" 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." ),
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/ExecutableElementAccessor.java b/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/ExecutableElementAccessor.java
index 356313f52..effd137b0 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/ExecutableElementAccessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/ExecutableElementAccessor.java
@@ -28,4 +28,9 @@ public class ExecutableElementAccessor extends AbstractAccessor {
public ExecutableElement getExecutable() {
return null;
}
+
+ @Override
+ public String toString() {
+ return element.toString();
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java b/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java
index 79d164ddb..25cea82c8 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java
@@ -37,7 +37,7 @@ class IndentationCorrectingWriter extends Writer {
* Set to true to enable output of written characters on the console.
*/
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 State currentState = State.START_OF_LINE;
diff --git a/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java b/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java
index 9921ad2f0..f5656e2e4 100644
--- a/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java
+++ b/processor/src/main/java/org/mapstruct/ap/spi/DefaultBuilderProvider.java
@@ -280,4 +280,5 @@ public class DefaultBuilderProvider implements BuilderProvider {
protected boolean shouldIgnore(TypeElement typeElement) {
return typeElement == null || JAVA_JAVAX_PACKAGE.matcher( typeElement.getQualifiedName() ).matches();
}
+
}
diff --git a/processor/src/main/java/org/mapstruct/ap/spi/FreeBuilderAccessorNamingStrategy.java b/processor/src/main/java/org/mapstruct/ap/spi/FreeBuilderAccessorNamingStrategy.java
index 5b269b4b0..92fef3a1b 100644
--- a/processor/src/main/java/org/mapstruct/ap/spi/FreeBuilderAccessorNamingStrategy.java
+++ b/processor/src/main/java/org/mapstruct/ap/spi/FreeBuilderAccessorNamingStrategy.java
@@ -35,4 +35,5 @@ public class FreeBuilderAccessorNamingStrategy extends DefaultAccessorNamingStra
// with set
return false;
}
+
}
diff --git a/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesAccessorNamingStrategy.java b/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesAccessorNamingStrategy.java
index abe777a1c..69c66cdd2 100644
--- a/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesAccessorNamingStrategy.java
+++ b/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesAccessorNamingStrategy.java
@@ -23,4 +23,5 @@ public class ImmutablesAccessorNamingStrategy extends DefaultAccessorNamingStrat
protected boolean isFluentSetter(ExecutableElement method) {
return super.isFluentSetter( method ) && !method.getSimpleName().toString().equals( "from" );
}
+
}
diff --git a/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java b/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java
index 16ad797a9..d4ccd029e 100644
--- a/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java
+++ b/processor/src/main/java/org/mapstruct/ap/spi/ImmutablesBuilderProvider.java
@@ -83,4 +83,5 @@ public class ImmutablesBuilderProvider extends DefaultBuilderProvider {
builderQualifiedName.append( "Immutable" ).append( typeElement.getSimpleName() );
return elementUtils.getTypeElement( builderQualifiedName );
}
+
}
diff --git a/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java b/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java
index fae086ab1..a30346c4b 100644
--- a/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java
+++ b/processor/src/main/java/org/mapstruct/ap/spi/NoOpBuilderProvider.java
@@ -23,5 +23,6 @@ public class NoOpBuilderProvider implements BuilderProvider {
public BuilderInfo findBuilderInfo(TypeMirror type) {
return null;
}
+
}
// end::documentation[]
diff --git a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java
index 6b40de313..76ceac40d 100755
--- a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java
+++ b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java
@@ -153,6 +153,11 @@ public class DefaultConversionContextTest {
lastKindPrinted = msg.getDiagnosticKind();
}
+ @Override
+ public void note(int level, Message msg, Object... args) {
+ throw new UnsupportedOperationException( "Should not be called" );
+ }
+
public Diagnostic.Kind getLastKindPrinted() {
return lastKindPrinted;
}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/AstModifyingAnnotationProcessorSaysNo.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/AstModifyingAnnotationProcessorSaysNo.java
new file mode 100644
index 000000000..898721b9f
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/AstModifyingAnnotationProcessorSaysNo.java
@@ -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;
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateBeanMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateBeanMapping.java
new file mode 100644
index 000000000..594318d9f
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateBeanMapping.java
@@ -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;
+ }
+ }
+
+}
+
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateIterableMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateIterableMapping.java
new file mode 100644
index 000000000..cf06fede0
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateIterableMapping.java
@@ -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 map(List 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;
+ }
+ }
+
+}
+
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateMapMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateMapMapping.java
new file mode 100644
index 000000000..815625689
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/CreateMapMapping.java
@@ -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 map(Map 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;
+ }
+ }
+}
+
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectBeanMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectBeanMapping.java
new file mode 100644
index 000000000..4b6d73d30
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectBeanMapping.java
@@ -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;
+ }
+ }
+
+}
+
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectIterableMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectIterableMapping.java
new file mode 100644
index 000000000..fa492cc14
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectIterableMapping.java
@@ -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 map(List source);
+
+ default TargetElement map(SourceElement sourceKey) {
+ return null;
+ }
+
+ class SourceElement {
+ }
+
+ class TargetElement {
+ }
+
+}
+
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectMapMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectMapMapping.java
new file mode 100644
index 000000000..7018642ce
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectMapMapping.java
@@ -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 map(Map source);
+
+ default TargetKey map(SourceKey sourceKey) {
+ return null;
+ }
+
+ default TargetValue map(SourceValue sourceValue) {
+ return null;
+ }
+
+ class SourceKey {
+ }
+
+ class SourceValue {
+ }
+
+ class TargetKey {
+ }
+
+ class TargetValue {
+ }
+}
+
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectStreamMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectStreamMapping.java
new file mode 100644
index 000000000..7ee44d8b0
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/SelectStreamMapping.java
@@ -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 map(Stream source);
+
+ default TargetElement map(SourceElement sourceKey) {
+ return null;
+ }
+
+ class SourceElement {
+ }
+
+ class TargetElement {
+ }
+
+}
+
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/ValueMapping.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/ValueMapping.java
new file mode 100644
index 000000000..f3e07fca8
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/ValueMapping.java
@@ -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 }
+
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/verbose/VerboseTest.java b/processor/src/test/java/org/mapstruct/ap/test/verbose/VerboseTest.java
new file mode 100644
index 000000000..99b77b122
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/verbose/VerboseTest.java
@@ -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() {
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/WithServiceImplementation.java b/processor/src/test/java/org/mapstruct/ap/testutil/WithServiceImplementation.java
index 2397667eb..16d8ad04f 100644
--- a/processor/src/test/java/org/mapstruct/ap/testutil/WithServiceImplementation.java
+++ b/processor/src/test/java/org/mapstruct/ap/testutil/WithServiceImplementation.java
@@ -6,6 +6,7 @@
package org.mapstruct.ap.testutil;
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;
@@ -17,6 +18,7 @@ import java.lang.annotation.Target;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
+@Repeatable( WithServiceImplementations.class )
public @interface WithServiceImplementation {
/**
* @return The service implementation class that is to be made available during the annotation processing.
diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/ExpectedNote.java b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/ExpectedNote.java
new file mode 100644
index 000000000..1cb95f52c
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/ExpectedNote.java
@@ -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();
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java
index cfe201f5d..22d9bcd68 100644
--- a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java
+++ b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java
@@ -8,6 +8,8 @@ package org.mapstruct.ap.testutil.compilation.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;
@@ -17,6 +19,7 @@ import org.codehaus.plexus.compiler.CompilerMessage;
import org.codehaus.plexus.compiler.CompilerResult;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
+import org.mapstruct.ap.testutil.compilation.annotation.ExpectedNote;
/**
* Represents the outcome of a compilation.
@@ -25,21 +28,37 @@ import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutco
*/
public class CompilationOutcomeDescriptor {
+ private static final String LINE_SEPARATOR = System.lineSeparator( );
+
private CompilationResult compilationResult;
private List diagnostics;
+ private List notes;
private CompilationOutcomeDescriptor(CompilationResult compilationResult,
- List diagnostics) {
+ List diagnostics,
+ List notes) {
this.compilationResult = compilationResult;
this.diagnostics = diagnostics;
+ this.notes = notes;
}
public static CompilationOutcomeDescriptor forExpectedCompilationResult(
- ExpectedCompilationOutcome expectedCompilationResult) {
+ ExpectedCompilationOutcome expectedCompilationResult, ExpectedNote.ExpectedNotes expectedNotes,
+ ExpectedNote expectedNote) {
+ List 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 ) {
return new CompilationOutcomeDescriptor(
CompilationResult.SUCCEEDED,
- Collections.emptyList()
+ Collections.emptyList(),
+ notes
);
}
else {
@@ -48,8 +67,7 @@ public class CompilationOutcomeDescriptor {
expectedCompilationResult.diagnostics() ) {
diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( diagnostic ) );
}
-
- return new CompilationOutcomeDescriptor( expectedCompilationResult.value(), diagnosticDescriptors );
+ return new CompilationOutcomeDescriptor( expectedCompilationResult.value(), diagnosticDescriptors, notes );
}
}
@@ -57,31 +75,34 @@ public class CompilationOutcomeDescriptor {
List> diagnostics) {
CompilationResult compilationResult =
compilationSuccessful ? CompilationResult.SUCCEEDED : CompilationResult.FAILED;
-
+ List notes = new ArrayList<>();
List diagnosticDescriptors = new ArrayList();
for ( Diagnostic extends JavaFileObject> diagnostic : diagnostics ) {
//ignore notes created by the compiler
if ( diagnostic.getKind() != Kind.NOTE ) {
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) {
CompilationResult compilationResult =
compilerResult.isSuccess() ? CompilationResult.SUCCEEDED : CompilationResult.FAILED;
-
List diagnosticDescriptors = new ArrayList();
for ( CompilerMessage message : compilerResult.getCompilerMessages() ) {
if ( message.getKind() != CompilerMessage.Kind.NOTE ) {
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() {
@@ -92,6 +113,10 @@ public class CompilationOutcomeDescriptor {
return diagnostics;
}
+ public List getNotes() {
+ return notes;
+ }
+
@Override
public int hashCode() {
final int prime = 31;
diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java
index f6ddcbd2b..a292ef6a2 100644
--- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java
+++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.stream.Collectors;
import org.junit.runners.model.FrameworkMethod;
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.DisableCheckstyle;
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.ProcessorOptions;
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 LINE_SEPARATOR = System.getProperty( "line.separator" );
+ private static final String LINE_SEPARATOR = System.lineSeparator( );
private static final DiagnosticDescriptorComparator COMPARATOR = new DiagnosticDescriptorComparator();
@@ -175,7 +177,9 @@ abstract class CompilingStatement extends Statement {
CompilationOutcomeDescriptor expectedResult =
CompilationOutcomeDescriptor.forExpectedCompilationResult(
- method.getAnnotation( ExpectedCompilationOutcome.class )
+ method.getAnnotation( ExpectedCompilationOutcome.class ),
+ method.getAnnotation( ExpectedNote.ExpectedNotes.class ),
+ method.getAnnotation( ExpectedNote.class )
);
if ( expectedResult.getCompilationResult() == CompilationResult.SUCCEEDED ) {
@@ -192,6 +196,7 @@ abstract class CompilingStatement extends Statement {
}
assertDiagnostics( actualResult.getDiagnostics(), expectedResult.getDiagnostics() );
+ assertNotes( actualResult.getNotes(), expectedResult.getNotes() );
if ( runCheckstyle ) {
assertCheckstyleRules();
@@ -239,6 +244,30 @@ abstract class CompilingStatement extends Statement {
return files;
}
+ private void assertNotes(List actualNotes, List expectedNotes) {
+ List expectedNotesRemaining = new ArrayList<>( expectedNotes );
+ Iterator 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 actualDiagnostics,
List expectedDiagnostics) {