#455 Add a fallback error reporting in case any uncaught exceptions occur - otherwise those errors are just swallowed and hard to find

This commit is contained in:
Andreas Gudian 2015-05-18 21:04:22 +02:00
parent 28ebf763cd
commit fbb80bfb25

View File

@ -18,6 +18,8 @@
*/ */
package org.mapstruct.ap; package org.mapstruct.ap;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -136,28 +138,53 @@ public class MappingProcessor extends AbstractProcessor {
continue; continue;
} }
for ( Element mapperElement : roundEnvironment.getElementsAnnotatedWith( annotation ) ) { Set<? extends Element> elementsWithAnnotation;
TypeElement mapperTypeElement = asTypeElement( mapperElement ); try {
elementsWithAnnotation = roundEnvironment.getElementsAnnotatedWith( annotation );
}
catch ( Throwable t ) { // whenever that may happen, but just to stay on the save side
handleUncaughtError( annotation, t );
continue;
}
// on some JDKs, RoundEnvironment.getElementsAnnotatedWith( ... ) returns types with for ( Element mapperElement : elementsWithAnnotation ) {
// annotations unknown to the compiler, even though they are not declared Mappers try {
if ( mapperTypeElement == null || MapperPrism.getInstanceOn( mapperTypeElement ) == null ) { TypeElement mapperTypeElement = asTypeElement( mapperElement );
continue;
// on some JDKs, RoundEnvironment.getElementsAnnotatedWith( ... ) returns types with
// annotations unknown to the compiler, even though they are not declared Mappers
if ( mapperTypeElement == null || MapperPrism.getInstanceOn( mapperTypeElement ) == null ) {
continue;
}
// create a new context for each generated mapper in order to have imports of referenced types
// correctly managed;
// note that this assumes that a new source file is created for each mapper which must not
// necessarily be the case, e.g. in case of several mapper interfaces declared as inner types
// of one outer interface
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
processMapperTypeElement( context, mapperTypeElement );
}
catch ( Throwable t ) {
handleUncaughtError( mapperElement, t );
break;
} }
// create a new context for each generated mapper in order to have imports of referenced types
// correctly managed;
// note that this assumes that a new source file is created for each mapper which must not
// necessarily be the case, e.g. in case of several mapper interfaces declared as inner types
// of one outer interface
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
processMapperTypeElement( context, mapperTypeElement );
} }
} }
return ANNOTATIONS_CLAIMED_EXCLUSIVELY; return ANNOTATIONS_CLAIMED_EXCLUSIVELY;
} }
private void handleUncaughtError(Element element, Throwable thrown) {
StringWriter sw = new StringWriter();
thrown.printStackTrace( new PrintWriter( sw ) );
String reportableStacktrace = sw.toString().replace( System.getProperty( "line.separator" ), " " );
processingEnv.getMessager().printMessage(
Kind.ERROR, "Internal error in the mapping processor: " + reportableStacktrace, element );
}
/** /**
* Applies all registered {@link ModelElementProcessor}s to the given mapper * Applies all registered {@link ModelElementProcessor}s to the given mapper
* type. * type.