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 97da699cb..13cd77475 100644
--- a/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
+++ b/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
@@ -135,4 +135,25 @@ public class MavenIntegrationTest {
}
+ /**
+ * Tests usage of MapStruct with another processor that generates the uses type of a mapper.
+ */
+ @ProcessorTest(baseDir = "usesTypeGenerationTest", processorTypes = {
+ ProcessorTest.ProcessorType.JAVAC
+ })
+ void usesTypeGenerationTest() {
+ }
+
+ /**
+ * Tests usage of MapStruct with another processor that generates the uses type of a mapper.
+ */
+ @ProcessorTest(baseDir = "usesTypeGenerationTest", processorTypes = {
+ ProcessorTest.ProcessorType.ECLIPSE_JDT
+ })
+ @EnabledForJreRange(min = JRE.JAVA_11)
+ // For some reason the second run with eclipse does not load the ModelElementProcessor(s) on java 8,
+ // therefore we run this only on Java 11
+ void usesTypeGenerationTestEclipse() {
+ }
+
}
diff --git a/integrationtest/src/test/resources/usesTypeGenerationTest/generator/pom.xml b/integrationtest/src/test/resources/usesTypeGenerationTest/generator/pom.xml
new file mode 100644
index 000000000..6ac3a0129
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/generator/pom.xml
@@ -0,0 +1,43 @@
+
+
+ 4.0.0
+
+
+ org.mapstruct.itest
+ itest-usestypegeneration-aggregator
+ 1.0.0
+ ../pom.xml
+
+
+ itest-usestypegeneration-generator
+ jar
+
+
+
+ junit
+ junit
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ -proc:none
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/usesTypeGenerationTest/generator/src/main/java/org/mapstruct/itest/usestypegeneration/UsesTypeGenerationProcessor.java b/integrationtest/src/test/resources/usesTypeGenerationTest/generator/src/main/java/org/mapstruct/itest/usestypegeneration/UsesTypeGenerationProcessor.java
new file mode 100644
index 000000000..2c17279ff
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/generator/src/main/java/org/mapstruct/itest/usestypegeneration/UsesTypeGenerationProcessor.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.itest.usestypegeneration;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.TypeElement;
+import javax.tools.JavaFileObject;
+
+/**
+ * Generate conversion uses.
+ *
+ * @author Filip Hrisafov
+ *
+ */
+@SupportedAnnotationTypes("*")
+public class UsesTypeGenerationProcessor extends AbstractProcessor {
+
+ private boolean hasRun = false;
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if ( !hasRun ) {
+ try {
+ JavaFileObject dto = processingEnv.getFiler().createSourceFile( "org.mapstruct.itest.usestypegeneration.usage.StringUtils" );
+ Writer writer = dto.openWriter();
+
+ writer.append( "package org.mapstruct.itest.usestypegeneration.usage;" );
+ writer.append( "\n" );
+ writer.append( "public class StringUtils {" );
+ writer.append( "\n" );
+ writer.append( " public static String upperCase(String string) {" );
+ writer.append( "\n" );
+ writer.append( " return string == null ? null : string.toUpperCase();" );
+ writer.append( "\n" );
+ writer.append( " }" );
+ writer.append( "\n" );
+ writer.append( "}" );
+
+ writer.flush();
+ writer.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException( e );
+ }
+
+ hasRun = true;
+ }
+
+ return false;
+ }
+}
diff --git a/integrationtest/src/test/resources/usesTypeGenerationTest/generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/integrationtest/src/test/resources/usesTypeGenerationTest/generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 000000000..57be8919b
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1,4 @@
+# Copyright MapStruct Authors.
+#
+# Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+org.mapstruct.itest.usestypegeneration.UsesTypeGenerationProcessor
diff --git a/integrationtest/src/test/resources/usesTypeGenerationTest/pom.xml b/integrationtest/src/test/resources/usesTypeGenerationTest/pom.xml
new file mode 100644
index 000000000..7c0d555ea
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/pom.xml
@@ -0,0 +1,27 @@
+
+
+
+ 4.0.0
+
+
+ org.mapstruct
+ mapstruct-it-parent
+ 1.0.0
+ ../pom.xml
+
+
+ org.mapstruct.itest
+ itest-usestypegeneration-aggregator
+ pom
+
+
+ generator
+ usage
+
+
diff --git a/integrationtest/src/test/resources/usesTypeGenerationTest/usage/pom.xml b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/pom.xml
new file mode 100644
index 000000000..e8b8d7bf0
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+
+ org.mapstruct.itest
+ itest-usestypegeneration-aggregator
+ 1.0.0
+ ../pom.xml
+
+
+ itest-usestypegeneration-usage
+ jar
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.mapstruct.itest
+ itest-usestypegeneration-generator
+ 1.0.0
+ provided
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ -XprintProcessorInfo
+ -XprintRounds
+
+ -proc:none
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/usage/Order.java b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/usage/Order.java
new file mode 100644
index 000000000..4d5a102ae
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/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.usestypegeneration.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/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/usage/OrderDto.java b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/usage/OrderDto.java
new file mode 100644
index 000000000..69951da5b
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/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.usestypegeneration.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/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/usage/OrderMapper.java b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/usage/OrderMapper.java
new file mode 100644
index 000000000..8b33ab17d
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/main/java/org/mapstruct/itest/usestypegeneration/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.usestypegeneration.usage;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+/**
+ * @author Filip Hrisafov
+ */
+@Mapper(uses = StringUtils.class)
+public interface OrderMapper {
+
+ OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
+
+ OrderDto orderToDto(Order order);
+}
diff --git a/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/test/java/org/mapstruct/itest/usestypegeneration/usage/GeneratedUsesTypeTest.java b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/test/java/org/mapstruct/itest/usestypegeneration/usage/GeneratedUsesTypeTest.java
new file mode 100644
index 000000000..e715e6662
--- /dev/null
+++ b/integrationtest/src/test/resources/usesTypeGenerationTest/usage/src/test/java/org/mapstruct/itest/usestypegeneration/usage/GeneratedUsesTypeTest.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.usestypegeneration.usage;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Integration test for using MapStruct with another annotation processor that generates the other mappers for uses
+ *
+ * @author Filip Hrisafov
+ */
+public class GeneratedUsesTypeTest {
+
+ @Test
+ public void considersPropertiesOnGeneratedSourceAndTargetTypes() {
+ Order order = new Order();
+ order.setItem( "my item" );
+
+ OrderDto dto = OrderMapper.INSTANCE.orderToDto( order );
+ assertThat( dto.getItem() ).isEqualTo( "MY ITEM" );
+ }
+}
diff --git a/parent/pom.xml b/parent/pom.xml
index 37551e2ed..3efe0ad8f 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -21,7 +21,7 @@
UTF-8
- 1.0.0.Alpha1
+ 1.0.0.Alpha2
3.0.0-M1
3.0.0-M3
diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
index 546f06256..e7e52be69 100644
--- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
@@ -29,6 +29,7 @@ import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Name;
import javax.lang.model.element.QualifiedNameable;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementKindVisitor6;
import javax.tools.Diagnostic.Kind;
@@ -177,7 +178,8 @@ public class MappingProcessor extends AbstractProcessor {
erroneousElementName = ( (QualifiedNameable) erroneousElement ).getQualifiedName().toString();
}
else {
- erroneousElementName = erroneousElement.getSimpleName().toString();
+ erroneousElementName =
+ erroneousElement != null ? erroneousElement.getSimpleName().toString() : null;
}
// When running on Java 8 we need to fetch the deferredMapperElement again.
@@ -265,9 +267,10 @@ public class MappingProcessor extends AbstractProcessor {
processMapperTypeElement( context, mapperElement );
}
catch ( TypeHierarchyErroneousException thie ) {
- Element erroneousElement = roundContext.getAnnotationProcessorContext()
+ TypeMirror erroneousType = thie.getType();
+ Element erroneousElement = erroneousType != null ? roundContext.getAnnotationProcessorContext()
.getTypeUtils()
- .asElement( thie.getType() );
+ .asElement( erroneousType ) : null;
if ( options.isVerbose() ) {
processingEnv.getMessager().printMessage(
Kind.NOTE, "MapStruct: referred types not available (yet), deferring mapper: "
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java
index b9dc068d0..8bc6ab982 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/DelegatingOptions.java
@@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.model.source;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import java.util.stream.Collectors;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
@@ -21,6 +20,7 @@ import org.mapstruct.ap.internal.gem.NullValueCheckStrategyGem;
import org.mapstruct.ap.internal.gem.NullValueMappingStrategyGem;
import org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem;
import org.mapstruct.ap.internal.gem.ReportingPolicyGem;
+import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
/**
* Chain Of Responsibility Pattern.
@@ -110,9 +110,18 @@ public abstract class DelegatingOptions {
}
protected Set toDeclaredTypes(List in, Set next) {
- Set result = in.stream()
- .map( DeclaredType.class::cast )
- .collect( Collectors.toCollection( LinkedHashSet::new ) );
+ Set result = new LinkedHashSet<>();
+ for ( TypeMirror typeMirror : in ) {
+ if ( typeMirror == null ) {
+ // When a class used in uses or imports is created by another annotation processor
+ // then javac will not return correct TypeMirror with TypeKind#ERROR, but rather a string ""
+ // the gem tools would return a null TypeMirror in that case.
+ // Therefore throw TypeHierarchyErroneousException so we can postpone the generation of the mapper
+ throw new TypeHierarchyErroneousException( typeMirror );
+ }
+
+ result.add( (DeclaredType) typeMirror );
+ }
result.addAll( next );
return result;
}