mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#2056: Handle null TypeMirror in uses and import gracefully
Due to a bug in javac (JDK-8229535) for an annotation with Class values, instead of returning a TypeMirror with TypeKind#ERROR the compiler returns the string "<error>". Eclipse doesn't have this problem currently.
This commit is contained in:
parent
c410379f83
commit
a845197b0b
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-usestypegeneration-aggregator</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>itest-usestypegeneration-generator</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<compilerArgs>
|
||||||
|
<compilerArg>-proc:none</compilerArg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-it-parent</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-usestypegeneration-aggregator</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>generator</module>
|
||||||
|
<module>usage</module>
|
||||||
|
</modules>
|
||||||
|
</project>
|
@ -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
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-usestypegeneration-aggregator</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>itest-usestypegeneration-usage</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-usestypegeneration-generator</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<compilerArgs>
|
||||||
|
<compilerArg>-XprintProcessorInfo</compilerArg>
|
||||||
|
<compilerArg>-XprintRounds</compilerArg>
|
||||||
|
</compilerArgs>
|
||||||
|
<testCompilerArgument>-proc:none</testCompilerArgument>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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" );
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<org.mapstruct.gem.version>1.0.0.Alpha1</org.mapstruct.gem.version>
|
<org.mapstruct.gem.version>1.0.0.Alpha2</org.mapstruct.gem.version>
|
||||||
<!-- We can't go to 3.0.0-M2 as it has a regression. See https://issues.apache.org/jira/browse/MENFORCER-306 -->
|
<!-- We can't go to 3.0.0-M2 as it has a regression. See https://issues.apache.org/jira/browse/MENFORCER-306 -->
|
||||||
<org.apache.maven.plugins.enforcer.version>3.0.0-M1</org.apache.maven.plugins.enforcer.version>
|
<org.apache.maven.plugins.enforcer.version>3.0.0-M1</org.apache.maven.plugins.enforcer.version>
|
||||||
<org.apache.maven.plugins.surefire.version>3.0.0-M3</org.apache.maven.plugins.surefire.version>
|
<org.apache.maven.plugins.surefire.version>3.0.0-M3</org.apache.maven.plugins.surefire.version>
|
||||||
|
@ -29,6 +29,7 @@ import javax.lang.model.element.ElementKind;
|
|||||||
import javax.lang.model.element.Name;
|
import javax.lang.model.element.Name;
|
||||||
import javax.lang.model.element.QualifiedNameable;
|
import javax.lang.model.element.QualifiedNameable;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.ElementKindVisitor6;
|
import javax.lang.model.util.ElementKindVisitor6;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
@ -177,7 +178,8 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
erroneousElementName = ( (QualifiedNameable) erroneousElement ).getQualifiedName().toString();
|
erroneousElementName = ( (QualifiedNameable) erroneousElement ).getQualifiedName().toString();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
erroneousElementName = erroneousElement.getSimpleName().toString();
|
erroneousElementName =
|
||||||
|
erroneousElement != null ? erroneousElement.getSimpleName().toString() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When running on Java 8 we need to fetch the deferredMapperElement again.
|
// When running on Java 8 we need to fetch the deferredMapperElement again.
|
||||||
@ -265,9 +267,10 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
processMapperTypeElement( context, mapperElement );
|
processMapperTypeElement( context, mapperElement );
|
||||||
}
|
}
|
||||||
catch ( TypeHierarchyErroneousException thie ) {
|
catch ( TypeHierarchyErroneousException thie ) {
|
||||||
Element erroneousElement = roundContext.getAnnotationProcessorContext()
|
TypeMirror erroneousType = thie.getType();
|
||||||
|
Element erroneousElement = erroneousType != null ? roundContext.getAnnotationProcessorContext()
|
||||||
.getTypeUtils()
|
.getTypeUtils()
|
||||||
.asElement( thie.getType() );
|
.asElement( erroneousType ) : null;
|
||||||
if ( options.isVerbose() ) {
|
if ( options.isVerbose() ) {
|
||||||
processingEnv.getMessager().printMessage(
|
processingEnv.getMessager().printMessage(
|
||||||
Kind.NOTE, "MapStruct: referred types not available (yet), deferring mapper: "
|
Kind.NOTE, "MapStruct: referred types not available (yet), deferring mapper: "
|
||||||
|
@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.model.source;
|
|||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.Elements;
|
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.NullValueMappingStrategyGem;
|
||||||
import org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem;
|
import org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem;
|
||||||
import org.mapstruct.ap.internal.gem.ReportingPolicyGem;
|
import org.mapstruct.ap.internal.gem.ReportingPolicyGem;
|
||||||
|
import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain Of Responsibility Pattern.
|
* Chain Of Responsibility Pattern.
|
||||||
@ -110,9 +110,18 @@ public abstract class DelegatingOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Set<DeclaredType> toDeclaredTypes(List<TypeMirror> in, Set<DeclaredType> next) {
|
protected Set<DeclaredType> toDeclaredTypes(List<TypeMirror> in, Set<DeclaredType> next) {
|
||||||
Set result = in.stream()
|
Set<DeclaredType> result = new LinkedHashSet<>();
|
||||||
.map( DeclaredType.class::cast )
|
for ( TypeMirror typeMirror : in ) {
|
||||||
.collect( Collectors.toCollection( LinkedHashSet::new ) );
|
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 "<error>"
|
||||||
|
// 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 );
|
result.addAll( next );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user