diff --git a/java/com/google/turbine/binder/Processing.java b/java/com/google/turbine/binder/Processing.java index 984dee66..0c24d2eb 100644 --- a/java/com/google/turbine/binder/Processing.java +++ b/java/com/google/turbine/binder/Processing.java @@ -21,7 +21,6 @@ import com.google.auto.value.AutoValue; import com.google.common.base.Joiner; import com.google.common.base.Stopwatch; -import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -296,9 +295,8 @@ static SupportedAnnotationTypes create(Processor processor) { private static void logProcessorCrash(TurbineLog log, Processor processor, Throwable t) { log.diagnostic( Diagnostic.Kind.ERROR, - String.format( - "An exception occurred in %s:\n%s", - processor.getClass().getCanonicalName(), Throwables.getStackTraceAsString(t))); + String.format("An exception occurred in %s:", processor.getClass().getCanonicalName()), + t); } /** Returns a map from annotations present in the compilation to the annotated elements. */ diff --git a/java/com/google/turbine/diag/TurbineDiagnostic.java b/java/com/google/turbine/diag/TurbineDiagnostic.java index c47cbebf..06369282 100644 --- a/java/com/google/turbine/diag/TurbineDiagnostic.java +++ b/java/com/google/turbine/diag/TurbineDiagnostic.java @@ -21,6 +21,7 @@ import static java.util.Objects.requireNonNull; import com.google.common.base.CharMatcher; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.diag.TurbineError.ErrorKind; @@ -37,18 +38,21 @@ public class TurbineDiagnostic { private final ImmutableList args; private final @Nullable SourceFile source; private final int position; + private final @Nullable Throwable cause; private TurbineDiagnostic( Diagnostic.Kind severity, ErrorKind kind, ImmutableList args, @Nullable SourceFile source, - int position) { + int position, + @Nullable Throwable cause) { this.severity = requireNonNull(severity); this.kind = requireNonNull(kind); this.args = requireNonNull(args); this.source = source; this.position = position; + this.cause = cause; } /** The diagnostic kind. */ @@ -85,6 +89,9 @@ public String diagnostic() { sb.append(": ").append(severity); } sb.append(": ").append(message()); + if (cause != null) { + sb.append(System.lineSeparator()).append(Throwables.getStackTraceAsString(cause)); + } if (position != -1) { sb.append(System.lineSeparator()); sb.append(lineSource()); @@ -104,7 +111,8 @@ private static TurbineDiagnostic create( ErrorKind kind, ImmutableList args, SourceFile source, - int position) { + int position, + @Nullable Throwable cause) { switch (kind) { case SYMBOL_NOT_FOUND -> checkArgument( @@ -114,13 +122,31 @@ private static TurbineDiagnostic create( args); default -> {} } - return new TurbineDiagnostic(severity, kind, args, source, position); + return new TurbineDiagnostic(severity, kind, args, source, position, cause); + } + + private static TurbineDiagnostic create( + Diagnostic.Kind severity, + ErrorKind kind, + ImmutableList args, + SourceFile source, + int position) { + return create(severity, kind, args, source, position, null); + } + + public @Nullable Throwable cause() { + return cause; } public static TurbineDiagnostic format(Diagnostic.Kind severity, ErrorKind kind, String message) { return create(severity, kind, ImmutableList.of(message), null, -1); } + public static TurbineDiagnostic format( + Diagnostic.Kind severity, ErrorKind kind, String message, Throwable cause) { + return create(severity, kind, ImmutableList.of(message), null, -1, cause); + } + public static TurbineDiagnostic format(Diagnostic.Kind severity, ErrorKind kind) { return create(severity, kind, ImmutableList.of(), null, -1); } @@ -149,7 +175,7 @@ public static TurbineDiagnostic format( } public TurbineDiagnostic withPosition(SourceFile source, int position) { - return new TurbineDiagnostic(severity, kind, args, source, position); + return new TurbineDiagnostic(severity, kind, args, source, position, cause); } @Override diff --git a/java/com/google/turbine/diag/TurbineLog.java b/java/com/google/turbine/diag/TurbineLog.java index 46e41ab4..2af0a970 100644 --- a/java/com/google/turbine/diag/TurbineLog.java +++ b/java/com/google/turbine/diag/TurbineLog.java @@ -98,6 +98,13 @@ public void diagnostic(Diagnostic.Kind severity, String message) { add(TurbineDiagnostic.format(severity, ErrorKind.PROC, message)); } + /** + * Reports an annotation processing diagnostic with no position information, retaining the cause. + */ + public void diagnostic(Diagnostic.Kind severity, String message, Throwable t) { + add(TurbineDiagnostic.format(severity, ErrorKind.PROC, message, t)); + } + public void add(TurbineDiagnostic diagnostic) { synchronized (lock) { diagnostics.add(diagnostic); diff --git a/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java b/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java index a4802f3f..34bdeb57 100644 --- a/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java +++ b/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java @@ -125,7 +125,11 @@ public void crash() throws IOException { e.diagnostics().stream().map(TurbineDiagnostic::message).collect(toImmutableList()); assertThat(messages).hasSize(2); assertThat(messages.getFirst()).contains("could not resolve NoSuch"); - assertThat(messages.get(1)).contains("crash!"); + assertThat(messages.get(1)) + .contains( + "An exception occurred in" + + " com.google.turbine.processing.ProcessingIntegrationTest.CrashingProcessor:"); + assertThat(e.diagnostics().get(1).cause()).hasMessageThat().contains("crash!"); } @SupportedAnnotationTypes("*")