diff --git a/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java b/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
index 13cd77475..0789e3051 100644
--- a/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
+++ b/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
@@ -156,4 +156,11 @@ public class MavenIntegrationTest {
void usesTypeGenerationTestEclipse() {
}
+ /**
+ * Tests usage of MapStruct with faulty provider of AstModifyingAnnotationProcessor.
+ */
+ @ProcessorTest(baseDir = "faultyAstModifyingAnnotationProcessorTest")
+ void faultyAstModifyingProcessor() {
+ }
+
}
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/pom.xml b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/pom.xml
new file mode 100644
index 000000000..08390085d
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+
+ org.mapstruct.itest
+ itest-faultyAstModifyingProcessor-aggregator
+ 1.0.0
+ ../pom.xml
+
+
+ itest-faultyAstModifyingProcessor-generator
+ jar
+
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+ provided
+
+
+ junit
+ junit
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ -proc:none
+
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/AstModifyingProcessorSaysYes.java b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/AstModifyingProcessorSaysYes.java
new file mode 100644
index 000000000..e4a5fe5ea
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/AstModifyingProcessorSaysYes.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.faultyAstModifyingProcessor;
+
+import javax.lang.model.type.TypeMirror;
+
+import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
+
+/**
+ * @author Filip Hrisafov
+ */
+public class AstModifyingProcessorSaysYes implements AstModifyingAnnotationProcessor {
+
+ @Override
+ public boolean isTypeComplete(TypeMirror type) {
+ return true;
+ }
+}
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/FaultyAstModifyingProcessor.java b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/FaultyAstModifyingProcessor.java
new file mode 100644
index 000000000..ba1be9b2c
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/FaultyAstModifyingProcessor.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.faultyAstModifyingProcessor;
+
+import javax.lang.model.type.TypeMirror;
+
+import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
+
+/**
+ * @author Filip Hrisafov
+ */
+public class FaultyAstModifyingProcessor implements AstModifyingAnnotationProcessor {
+
+ public FaultyAstModifyingProcessor() {
+ throw new RuntimeException( "Failed to create processor" );
+ }
+
+ @Override
+ public boolean isTypeComplete(TypeMirror type) {
+ return true;
+ }
+}
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/FaultyStaticAstModifyingProcessor.java b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/FaultyStaticAstModifyingProcessor.java
new file mode 100644
index 000000000..5f1616501
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/FaultyStaticAstModifyingProcessor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.faultyAstModifyingProcessor;
+
+import javax.lang.model.type.TypeMirror;
+
+import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
+
+/**
+ * @author Filip Hrisafov
+ */
+public class FaultyStaticAstModifyingProcessor implements AstModifyingAnnotationProcessor {
+
+ static {
+ if ( true ) {
+ throw new RuntimeException( "Failed to initialize class" );
+ }
+ }
+
+ @Override
+ public boolean isTypeComplete(TypeMirror type) {
+ return true;
+ }
+}
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/resources/META-INF/services/org.mapstruct.ap.spi.AstModifyingAnnotationProcessor b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/resources/META-INF/services/org.mapstruct.ap.spi.AstModifyingAnnotationProcessor
new file mode 100644
index 000000000..3bc4f6138
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/generator/src/main/resources/META-INF/services/org.mapstruct.ap.spi.AstModifyingAnnotationProcessor
@@ -0,0 +1,7 @@
+# Copyright MapStruct Authors.
+#
+# Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+org.mapstruct.itest.faultyAstModifyingProcessor.UnknownAstModifyingProcessor
+org.mapstruct.itest.faultyAstModifyingProcessor.AstModifyingProcessorSaysYes
+org.mapstruct.itest.faultyAstModifyingProcessor.FaultyAstModifyingProcessor
+org.mapstruct.itest.faultyAstModifyingProcessor.FaultyStaticAstModifyingProcessor
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/pom.xml b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/pom.xml
new file mode 100644
index 000000000..dae561252
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/pom.xml
@@ -0,0 +1,27 @@
+
+
+
+ 4.0.0
+
+
+ org.mapstruct
+ mapstruct-it-parent
+ 1.0.0
+ ../pom.xml
+
+
+ org.mapstruct.itest
+ itest-faultyAstModifyingProcessor-aggregator
+ pom
+
+
+ generator
+ usage
+
+
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/pom.xml b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/pom.xml
new file mode 100644
index 000000000..cc0d0e4f9
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+
+ org.mapstruct.itest
+ itest-faultyAstModifyingProcessor-aggregator
+ 1.0.0
+ ../pom.xml
+
+
+ itest-faultyAstModifyingProcessor-usage
+ jar
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.mapstruct.itest
+ itest-faultyAstModifyingProcessor-generator
+ 1.0.0
+ provided
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ -XprintProcessorInfo
+ -XprintRounds
+
+ -proc:none
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/Order.java b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/Order.java
new file mode 100644
index 000000000..1d7cd6380
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/Order.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.itest.faultyAstModifyingProcessor.usage;
+
+/**
+ * @author Filip Hrisafov
+ */
+public class Order {
+
+ private String item;
+
+ public String getItem() {
+ return item;
+ }
+
+ public void setItem(String item) {
+ this.item = item;
+ }
+}
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/OrderDto.java b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/OrderDto.java
new file mode 100644
index 000000000..afc64606b
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/OrderDto.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.itest.faultyAstModifyingProcessor.usage;
+
+/**
+ * @author Filip Hrisafov
+ */
+public class OrderDto {
+
+ private String item;
+
+ public String getItem() {
+ return item;
+ }
+
+ public void setItem(String item) {
+ this.item = item;
+ }
+}
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/OrderMapper.java b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/OrderMapper.java
new file mode 100644
index 000000000..75e52eb47
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/main/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/OrderMapper.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.faultyAstModifyingProcessor.usage;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+/**
+ * @author Filip Hrisafov
+ */
+@Mapper
+public interface OrderMapper {
+
+ OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
+
+ OrderDto orderToDto(Order order);
+}
diff --git a/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/test/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/FaultyAstModifyingTestTest.java b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/test/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/FaultyAstModifyingTestTest.java
new file mode 100644
index 000000000..06bfa3c53
--- /dev/null
+++ b/integrationtest/src/test/resources/faultyAstModifyingAnnotationProcessorTest/usage/src/test/java/org/mapstruct/itest/faultyAstModifyingProcessor/usage/FaultyAstModifyingTestTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.faultyAstModifyingProcessor.usage;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Integration test for using MapStruct with a faulty AstModifyingProcessor (i.e. when the processor cannot be loaded)
+ *
+ * @author Filip Hrisafov
+ */
+public class FaultyAstModifyingTestTest {
+
+ @Test
+ public void testMapping() {
+ Order order = new Order();
+ order.setItem( "my item" );
+
+ OrderDto dto = OrderMapper.INSTANCE.orderToDto( order );
+ assertThat( dto.getItem() ).isEqualTo( "my item" );
+ }
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java
index 2b6f353d0..8fdc6201e 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/util/AnnotationProcessorContext.java
@@ -5,7 +5,10 @@
*/
package org.mapstruct.ap.internal.util;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
@@ -45,7 +48,7 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
public AnnotationProcessorContext(Elements elementUtils, Types typeUtils, Messager messager, boolean verbose) {
astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList(
- findAstModifyingAnnotationProcessors() );
+ findAstModifyingAnnotationProcessors( messager ) );
this.elementUtils = elementUtils;
this.typeUtils = typeUtils;
this.messager = messager;
@@ -105,20 +108,86 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
this.initialized = true;
}
- private static List findAstModifyingAnnotationProcessors() {
+ private static List findAstModifyingAnnotationProcessors(Messager messager) {
List processors = new ArrayList<>();
ServiceLoader loader = ServiceLoader.load(
AstModifyingAnnotationProcessor.class, AnnotationProcessorContext.class.getClassLoader()
);
- for ( AstModifyingAnnotationProcessor astModifyingAnnotationProcessor : loader ) {
- processors.add( astModifyingAnnotationProcessor );
+ // Lombok packages an AstModifyingAnnotationProcessor as part of their jar
+ // this leads to problems within Eclipse when lombok is used as an agent
+ // Therefore we are wrapping this into an iterator that can handle exceptions by ignoring
+ // the faulty processor
+ Iterator loaderIterator = new FaultyDelegatingIterator(
+ messager,
+ loader.iterator()
+ );
+
+ while ( loaderIterator.hasNext() ) {
+ AstModifyingAnnotationProcessor processor = loaderIterator.next();
+ if ( processor != null ) {
+ processors.add( processor );
+ }
}
return processors;
}
+ private static class FaultyDelegatingIterator implements Iterator {
+
+ private final Messager messager;
+ private final Iterator delegate;
+
+ private FaultyDelegatingIterator(Messager messager,
+ Iterator delegate) {
+ this.messager = messager;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public boolean hasNext() {
+ // Check the delegate maximum of 5 times
+ // before returning false
+ int failures = 5;
+ while ( failures > 0 ) {
+ try {
+ return delegate.hasNext();
+ }
+ catch ( Throwable t ) {
+ failures--;
+ logFailure( t );
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public AstModifyingAnnotationProcessor next() {
+ try {
+ return delegate.next();
+ }
+ catch ( Throwable t ) {
+ logFailure( t );
+ return null;
+ }
+ }
+
+ private void logFailure(Throwable t) {
+ StringWriter sw = new StringWriter();
+ t.printStackTrace( new PrintWriter( sw ) );
+
+ String reportableStacktrace = sw.toString().replace( System.lineSeparator(), " " );
+
+ messager.printMessage(
+ Diagnostic.Kind.WARNING,
+ "Failed to read AstModifyingAnnotationProcessor. Reading next processor. Reason: " +
+ reportableStacktrace
+ );
+ }
+ }
+
@Override
public Elements getElementUtils() {
return elementUtils;
diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/FaultyAstModifyingAnnotationProcessor.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/FaultyAstModifyingAnnotationProcessor.java
new file mode 100644
index 000000000..99d88e988
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/FaultyAstModifyingAnnotationProcessor.java
@@ -0,0 +1,25 @@
+/*
+ * 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.bugs._1159;
+
+import javax.lang.model.type.TypeMirror;
+
+import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
+
+/**
+ * @author Filip Hrisafov
+ */
+public class FaultyAstModifyingAnnotationProcessor implements AstModifyingAnnotationProcessor {
+
+ public FaultyAstModifyingAnnotationProcessor() {
+ throw new RuntimeException( "Faulty AstModifyingAnnotationProcessor should not be instantiated" );
+ }
+
+ @Override
+ public boolean isTypeComplete(TypeMirror type) {
+ return false;
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/Issue1159Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/Issue1159Mapper.java
new file mode 100644
index 000000000..ab1441c14
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/Issue1159Mapper.java
@@ -0,0 +1,52 @@
+/*
+ * 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.bugs._1159;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+/**
+ * @author Filip Hrisafov
+ */
+@Mapper
+public interface Issue1159Mapper {
+
+ Issue1159Mapper INSTANCE = Mappers.getMapper( Issue1159Mapper.class );
+
+ CarManualDto translateManual(CarManual manual);
+
+ /**
+ * @author Filip Hrisafov
+ */
+ class CarManual {
+
+ private String content;
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+ }
+
+ /**
+ * @author Filip Hrisafov
+ */
+ class CarManualDto {
+
+ private String content;
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/Issue1159Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/Issue1159Test.java
new file mode 100644
index 000000000..b93cd6d06
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1159/Issue1159Test.java
@@ -0,0 +1,60 @@
+/*
+ * 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.bugs._1159;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
+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.CompilationResult;
+import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
+import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
+import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
+import org.mapstruct.ap.testutil.runner.Compiler;
+import org.mapstruct.ap.testutil.runner.DisabledOnCompiler;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Filip Hrisafov
+ */
+@IssueKey("1159")
+@RunWith(AnnotationProcessorTestRunner.class)
+@WithClasses({
+ Issue1159Mapper.class,
+})
+@WithServiceImplementation(
+ provides = AstModifyingAnnotationProcessor.class,
+ value = FaultyAstModifyingAnnotationProcessor.class
+)
+public class Issue1159Test {
+
+ @Test
+ // The warning is not present in the Eclipse compilation for some reason
+ @DisabledOnCompiler({
+ Compiler.ECLIPSE,
+ Compiler.ECLIPSE11
+ })
+ @ExpectedCompilationOutcome(value = CompilationResult.SUCCEEDED, diagnostics = {
+ @Diagnostic(
+ kind = javax.tools.Diagnostic.Kind.WARNING,
+ messageRegExp = "Failed to read AstModifyingAnnotationProcessor. Reading next processor. Reason:.*" +
+ "Faulty AstModifyingAnnotationProcessor should not be instantiated"
+ )
+ })
+ public void shouldIgnoreFaultyAstModifyingProcessor() {
+
+ Issue1159Mapper.CarManual manual = new Issue1159Mapper.CarManual();
+ manual.setContent( "test" );
+
+ Issue1159Mapper.CarManualDto manualDto = Issue1159Mapper.INSTANCE.translateManual( manual );
+
+ assertThat( manualDto ).isNotNull();
+ assertThat( manualDto.getContent() ).isEqualTo( "test" );
+ }
+}