mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1159: Do not fail loading AnnotationProcessorContext if loading AstModifyingAnnotationProcessor fails
This commit is contained in:
parent
c58f80cc5f
commit
3bffe96983
@ -156,4 +156,11 @@ public class MavenIntegrationTest {
|
||||
void usesTypeGenerationTestEclipse() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests usage of MapStruct with faulty provider of AstModifyingAnnotationProcessor.
|
||||
*/
|
||||
@ProcessorTest(baseDir = "faultyAstModifyingAnnotationProcessorTest")
|
||||
void faultyAstModifyingProcessor() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
<!--
|
||||
|
||||
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-faultyAstModifyingProcessor-aggregator</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>itest-faultyAstModifyingProcessor-generator</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>${mapstruct.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<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,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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -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-faultyAstModifyingProcessor-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-faultyAstModifyingProcessor-aggregator</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>itest-faultyAstModifyingProcessor-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-faultyAstModifyingProcessor-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.faultyAstModifyingProcessor.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.faultyAstModifyingProcessor.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.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);
|
||||
}
|
@ -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" );
|
||||
}
|
||||
}
|
@ -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<AstModifyingAnnotationProcessor> findAstModifyingAnnotationProcessors() {
|
||||
private static List<AstModifyingAnnotationProcessor> findAstModifyingAnnotationProcessors(Messager messager) {
|
||||
List<AstModifyingAnnotationProcessor> processors = new ArrayList<>();
|
||||
|
||||
ServiceLoader<AstModifyingAnnotationProcessor> 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<AstModifyingAnnotationProcessor> 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<AstModifyingAnnotationProcessor> {
|
||||
|
||||
private final Messager messager;
|
||||
private final Iterator<AstModifyingAnnotationProcessor> delegate;
|
||||
|
||||
private FaultyDelegatingIterator(Messager messager,
|
||||
Iterator<AstModifyingAnnotationProcessor> 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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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" );
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user