blob: 2541f473d174566af415d2300f34e5eb1dc04376 [file] [log] [blame]
// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
import java.util.ArrayList;
import java.util.Collection;
public class Reporter implements DiagnosticsHandler {
private final DiagnosticsHandler clientHandler;
private int errorCount = 0;
private Diagnostic lastError;
private final Collection<Throwable> suppressedExceptions = new ArrayList<>();
public Reporter() {
this(new DiagnosticsHandler() {});
}
public Reporter(DiagnosticsHandler clientHandler) {
this.clientHandler = clientHandler;
}
@Override
public synchronized void info(Diagnostic info) {
clientHandler.info(info);
}
@Override
public synchronized void warning(Diagnostic warning) {
clientHandler.warning(warning);
}
@Override
public synchronized void error(Diagnostic error) {
clientHandler.error(error);
lastError = error;
errorCount++;
}
public void error(String message) {
error(new StringDiagnostic(message));
}
public synchronized void error(Diagnostic error, Throwable suppressedException) {
clientHandler.error(error);
lastError = error;
errorCount++;
suppressedExceptions.add(suppressedException);
}
/**
* @throws AbortException always.
*/
public RuntimeException fatalError(String message) {
fatalError(new StringDiagnostic(message));
throw new Unreachable();
}
/**
* @throws AbortException always.
*/
public RuntimeException fatalError(Diagnostic error) {
error(error);
failIfPendingErrors();
throw new Unreachable();
}
/**
* @throws AbortException always.
*/
public RuntimeException fatalError(Diagnostic error, Throwable suppressedException) {
error(error, suppressedException);
failIfPendingErrors();
throw new Unreachable();
}
/**
* @throws AbortException if any error was reported.
*/
public void failIfPendingErrors() {
synchronized (this) {
if (errorCount != 0) {
AbortException abort;
if (lastError != null && lastError.getDiagnosticMessage() != null) {
StringBuilder builder = new StringBuilder("Error: ");
if (lastError.getOrigin() != Origin.unknown()) {
builder.append(lastError.getOrigin()).append(", ");
}
if (lastError.getPosition() != Position.UNKNOWN) {
builder.append(lastError.getPosition()).append(", ");
}
builder.append(lastError.getDiagnosticMessage());
abort = new AbortException(builder.toString());
} else {
abort = new AbortException();
}
throw addSuppressedExceptions(abort);
}
}
}
private <T extends Throwable> T addSuppressedExceptions(T t) {
suppressedExceptions.forEach(t::addSuppressed);
return t;
}
public void guard(Runnable action) throws CompilationFailedException {
try {
action.run();
} catch (CompilationError e) {
error(e.toStringDiagnostic());
throw addSuppressedExceptions(new CompilationFailedException());
} catch (AbortException e) {
throw new CompilationFailedException(e);
}
}
}