Skip to content

Commit 55e2b4d

Browse files
committed
Improve error handling in annotation processing
1 parent 776579d commit 55e2b4d

File tree

8 files changed

+142
-28
lines changed

8 files changed

+142
-28
lines changed

src/main/java/org/seasar/doma/internal/apt/AptTypeHandleException.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/main/java/org/seasar/doma/internal/apt/processor/AbstractProcessor.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.seasar.doma.internal.apt.processor;
22

3+
import java.io.PrintWriter;
4+
import java.io.StringWriter;
5+
import java.io.Writer;
36
import java.lang.annotation.Annotation;
47
import java.util.function.Consumer;
58
import javax.annotation.processing.ProcessingEnvironment;
@@ -47,13 +50,17 @@ protected void handleTypeElement(TypeElement typeElement, Consumer<TypeElement>
4750
ctx.getNotifier().notify(e);
4851
} catch (AptIllegalOptionException e) {
4952
ctx.getNotifier().notify(Kind.ERROR, e.getMessage(), typeElement);
50-
throw new AptTypeHandleException(typeElement, e);
53+
throw e;
5154
} catch (AptIllegalStateException e) {
52-
ctx.getNotifier().notify(Kind.ERROR, Message.DOMA4039, typeElement, new Object[] {});
53-
throw new AptTypeHandleException(typeElement, e);
54-
} catch (RuntimeException e) {
55-
ctx.getNotifier().notify(Kind.ERROR, Message.DOMA4016, typeElement, new Object[] {});
56-
throw new AptTypeHandleException(typeElement, e);
55+
String stackTrace = getStackTraceAsString(e);
56+
ctx.getNotifier()
57+
.notify(Kind.ERROR, Message.DOMA4039, typeElement, new Object[] {stackTrace});
58+
throw e;
59+
} catch (RuntimeException | AssertionError e) {
60+
String stackTrace = getStackTraceAsString(e);
61+
ctx.getNotifier()
62+
.notify(Kind.ERROR, Message.DOMA4016, typeElement, new Object[] {stackTrace});
63+
throw e;
5764
}
5865
if (ctx.getOptions().isDebugEnabled()) {
5966
ctx.getNotifier()
@@ -62,4 +69,10 @@ protected void handleTypeElement(TypeElement typeElement, Consumer<TypeElement>
6269
new Object[] {getClass().getName(), typeElement.getQualifiedName()});
6370
}
6471
}
72+
73+
private String getStackTraceAsString(Throwable throwable) {
74+
Writer stringWriter = new StringWriter();
75+
throwable.printStackTrace(new PrintWriter(stringWriter));
76+
return stringWriter.toString();
77+
}
6578
}

src/main/java/org/seasar/doma/message/Message.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ public enum Message implements MessageResource {
278278
DOMA4014("Cannot annotate @Dao to anything but interfaces."),
279279
DOMA4015("Cannot annotate @Entity to anything but classes."),
280280
DOMA4016(
281-
"An unexpected error has occurred. Check the logs for more information. For example, if you use Eclipse, see the error log view."),
281+
"An unexpected error has occurred. It may be a bug in the Doma framework. Report the following stacktrace: {0}"),
282282
DOMA4017("The Dao interface must be a top level interface."),
283283
DOMA4019("The file[{0}] is not found from the classpath. The absolute path is \"{1}\"."),
284284
DOMA4020("The SQL file[{0}] is empty."),
@@ -301,7 +301,7 @@ public enum Message implements MessageResource {
301301
DOMA4038(
302302
"The type argument[{1}] of EntityListener[{0}] must be supertype of the entity class[{2}]."),
303303
DOMA4039(
304-
"The annotation processing is stopped because of compilation error. Check the error message from the execution environment such as Eclipse and javac."),
304+
"The annotation processing is stopped because of compilation error. Check the error message from your execution environment such as Eclipse and javac. Stacktrace: {0}"),
305305
DOMA4040("The return type must be the array of int that indicates the affected rows count."),
306306
DOMA4042("The parameter type must be the subtype of java.lang.Iterable."),
307307
DOMA4043("The type argument of the subtype of java.lang.Iterable must be the entity class."),
@@ -614,8 +614,6 @@ public enum Message implements MessageResource {
614614
DOMA4298(
615615
"The class[{0}] is not supported as a persistent type. If you intend to map the class to the external domain class with @ExternalDomain, the configuration may be not enough. Check the class that is annotated with @DomainConverters and the annotation processing option \"doma.domain.converters\"."),
616616
DOMA4299("The raw type of the class[{0}] cannot be used as a persistent property."),
617-
DOMA4300(
618-
"The annotation processing for the type[{0}] is failed. Are there any compilation errors that are unrelated to the annotation processing?"),
619617
DOMA4301(
620618
"The type argument of the class[{0}] that is a wildcard or type variable cannot be used as a persistent property."),
621619
DOMA4302("@Id cannot be annotated to the property whose type is annotated with @Embeddable."),

src/test/java/org/seasar/aptina/unit/AptinaTestCase.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ public abstract class AptinaTestCase extends TestCase {
197197

198198
Boolean compiledResult;
199199

200+
boolean compilationAssertion = true;
201+
200202
/** インスタンスを構築します. */
201203
protected AptinaTestCase() {}
202204

@@ -220,6 +222,14 @@ protected void tearDown() throws Exception {
220222
super.tearDown();
221223
}
222224

225+
protected void enableCompilationAssertion() {
226+
this.compilationAssertion = true;
227+
}
228+
229+
protected void disableCompilationAssertion() {
230+
this.compilationAssertion = false;
231+
}
232+
223233
/**
224234
* ロケールを返します.
225235
*
@@ -1042,7 +1052,7 @@ List<JavaFileObject> getCompilationUnits() throws IOException {
10421052
* @throws IllegalStateException {@link #compile()} が呼び出されていない場合
10431053
*/
10441054
void assertCompiled() throws IllegalStateException {
1045-
if (compiledResult == null) {
1055+
if (compilationAssertion && compiledResult == null) {
10461056
throw new IllegalStateException("not compiled");
10471057
}
10481058
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.seasar.doma.internal.apt.processor.error;
2+
3+
import org.seasar.doma.internal.apt.AptIllegalStateException;
4+
import org.seasar.doma.internal.apt.AptTestCase;
5+
import org.seasar.doma.message.Message;
6+
7+
public class AbstractProcessorTest extends AptTestCase {
8+
9+
@Override
10+
protected void setUp() throws Exception {
11+
super.setUp();
12+
disableCompilationAssertion();
13+
addSourcePath("src/main/java");
14+
addSourcePath("src/test/java");
15+
}
16+
17+
@Override
18+
protected void tearDown() throws Exception {
19+
enableCompilationAssertion();
20+
super.tearDown();
21+
}
22+
23+
public void testAptIllegalStateException() throws Exception {
24+
Class<?> target = Person.class;
25+
addCompilationUnit(target);
26+
addProcessor(
27+
new MyProcessor(
28+
__ -> {
29+
throw new AptIllegalStateException("hoge");
30+
}));
31+
try {
32+
compile();
33+
fail();
34+
} catch (Exception ignored) {
35+
}
36+
assertMessage(Message.DOMA4039);
37+
}
38+
39+
public void testRuntimeException() throws Exception {
40+
Class<?> target = Person.class;
41+
addCompilationUnit(target);
42+
addProcessor(
43+
new MyProcessor(
44+
__ -> {
45+
throw new NullPointerException("hoge");
46+
}));
47+
try {
48+
compile();
49+
fail();
50+
} catch (Exception ignored) {
51+
}
52+
assertMessage(Message.DOMA4016);
53+
}
54+
55+
public void testAssertionError() throws Exception {
56+
Class<?> target = Person.class;
57+
addCompilationUnit(target);
58+
addProcessor(
59+
new MyProcessor(
60+
__ -> {
61+
throw new AssertionError("hoge");
62+
}));
63+
try {
64+
compile();
65+
fail();
66+
} catch (Exception ignored) {
67+
}
68+
assertMessage(Message.DOMA4016);
69+
}
70+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package org.seasar.doma.internal.apt.processor.error;
2+
3+
public @interface MyAnnotation {}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.seasar.doma.internal.apt.processor.error;
2+
3+
import java.util.Set;
4+
import java.util.function.Consumer;
5+
import javax.annotation.processing.RoundEnvironment;
6+
import javax.annotation.processing.SupportedAnnotationTypes;
7+
import javax.lang.model.element.TypeElement;
8+
import javax.lang.model.util.ElementFilter;
9+
import org.seasar.doma.internal.apt.processor.AbstractProcessor;
10+
11+
@SupportedAnnotationTypes({"org.seasar.doma.internal.apt.processor.error.MyAnnotation"})
12+
public class MyProcessor extends AbstractProcessor {
13+
14+
private final Consumer<TypeElement> handler;
15+
16+
protected MyProcessor(Consumer<TypeElement> handler) {
17+
super(MyAnnotation.class);
18+
this.handler = handler;
19+
}
20+
21+
@Override
22+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
23+
if (roundEnv.processingOver()) {
24+
return true;
25+
}
26+
for (TypeElement a : annotations) {
27+
for (TypeElement t : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(a))) {
28+
handleTypeElement(t, handler);
29+
}
30+
}
31+
return true;
32+
}
33+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.seasar.doma.internal.apt.processor.error;
2+
3+
@MyAnnotation
4+
public class Person {}

0 commit comments

Comments
 (0)