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>
|
||||
<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 -->
|
||||
<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>
|
||||
|
@ -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: "
|
||||
|
@ -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<DeclaredType> toDeclaredTypes(List<TypeMirror> in, Set<DeclaredType> next) {
|
||||
Set result = in.stream()
|
||||
.map( DeclaredType.class::cast )
|
||||
.collect( Collectors.toCollection( LinkedHashSet::new ) );
|
||||
Set<DeclaredType> 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 "<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 );
|
||||
return result;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user