org.gradle.internal.buildevents.BuildExceptionReporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.internal.buildevents;
import org.gradle.BuildAdapter;
import org.gradle.BuildResult;
import org.gradle.api.Action;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.configuration.LoggingConfiguration;
import org.gradle.api.logging.configuration.ShowStacktrace;
import org.gradle.execution.MultipleBuildFailures;
import org.gradle.initialization.BuildClientMetaData;
import org.gradle.internal.exceptions.FailureResolutionAware;
import org.gradle.internal.exceptions.LocationAwareException;
import org.gradle.internal.logging.LoggingCommandLineConverter;
import org.gradle.internal.logging.text.BufferingStyledTextOutput;
import org.gradle.internal.logging.text.LinePrefixingStyledTextOutput;
import org.gradle.internal.logging.text.StyledTextOutput;
import org.gradle.internal.logging.text.StyledTextOutputFactory;
import org.gradle.util.GUtil;
import org.gradle.util.TreeVisitor;
import java.util.List;
import static org.gradle.internal.logging.text.StyledTextOutput.Style.*;
/**
* A {@link org.gradle.BuildListener} which reports the build exception, if any.
*/
public class BuildExceptionReporter extends BuildAdapter implements Action {
private enum ExceptionStyle {
NONE, FULL
}
private final StyledTextOutputFactory textOutputFactory;
private final LoggingConfiguration loggingConfiguration;
private final BuildClientMetaData clientMetaData;
public BuildExceptionReporter(StyledTextOutputFactory textOutputFactory, LoggingConfiguration loggingConfiguration, BuildClientMetaData clientMetaData) {
this.textOutputFactory = textOutputFactory;
this.loggingConfiguration = loggingConfiguration;
this.clientMetaData = clientMetaData;
}
public void buildFinished(BuildResult result) {
Throwable failure = result.getFailure();
if (failure == null) {
return;
}
execute(failure);
}
public void execute(Throwable failure) {
if (failure instanceof MultipleBuildFailures) {
renderMultipleBuildExceptions((MultipleBuildFailures) failure);
return;
}
renderSingleBuildException(failure);
}
private void renderMultipleBuildExceptions(MultipleBuildFailures multipleFailures) {
List extends Throwable> causes = multipleFailures.getCauses();
StyledTextOutput output = textOutputFactory.create(BuildExceptionReporter.class, LogLevel.ERROR);
output.println();
output.withStyle(Failure).format("FAILURE: Build completed with %s failures.", causes.size());
output.println();
for (int i = 0; i < causes.size(); i++) {
Throwable cause = causes.get(i);
FailureDetails details = constructFailureDetails("Task", cause);
output.println();
output.withStyle(Failure).format("%s: ", i + 1);
details.summary.writeTo(output.withStyle(Failure));
output.println();
output.text("-----------");
writeFailureDetails(output, details);
output.println("==============================================================================");
}
}
private void renderSingleBuildException(Throwable failure) {
StyledTextOutput output = textOutputFactory.create(BuildExceptionReporter.class, LogLevel.ERROR);
FailureDetails details = constructFailureDetails("Build", failure);
output.println();
output.withStyle(Failure).text("FAILURE: ");
details.summary.writeTo(output.withStyle(Failure));
output.println();
writeFailureDetails(output, details);
}
private FailureDetails constructFailureDetails(String granularity, Throwable failure) {
FailureDetails details = new FailureDetails(failure);
reportBuildFailure(granularity, failure, details);
return details;
}
private void reportBuildFailure(String granularity, Throwable failure, FailureDetails details) {
if (loggingConfiguration.getShowStacktrace() != ShowStacktrace.INTERNAL_EXCEPTIONS) {
details.exceptionStyle = ExceptionStyle.FULL;
}
formatGenericFailure(granularity, failure, details);
}
private void formatGenericFailure(String granularity, Throwable failure, final FailureDetails details) {
details.summary.format("%s failed with an exception.", granularity);
fillInFailureResolution(details);
if (failure instanceof LocationAwareException) {
final LocationAwareException scriptException = (LocationAwareException) failure;
details.failure = scriptException.getCause();
if (scriptException.getLocation() != null) {
details.location.text(scriptException.getLocation());
}
scriptException.visitReportableCauses(new TreeVisitor() {
int depth;
@Override
public void node(final Throwable node) {
if (node == scriptException) {
details.details.text(getMessage(scriptException.getCause()));
} else {
final LinePrefixingStyledTextOutput output = getLinePrefixingStyledTextOutput();
output.text(getMessage(node));
}
}
@Override
public void startChildren() {
depth++;
}
@Override
public void endChildren() {
depth--;
}
private LinePrefixingStyledTextOutput getLinePrefixingStyledTextOutput() {
details.details.format("%n");
StringBuilder prefix = new StringBuilder();
for (int i = 1; i < depth; i++) {
prefix.append(" ");
}
details.details.text(prefix);
prefix.append(" ");
details.details.style(Info).text("> ").style(Normal);
return new LinePrefixingStyledTextOutput(details.details, prefix, false);
}
});
} else {
details.details.text(getMessage(failure));
}
}
private void fillInFailureResolution(FailureDetails details) {
if (details.failure instanceof FailureResolutionAware) {
((FailureResolutionAware) details.failure).appendResolution(details.resolution, clientMetaData);
if (details.resolution.getHasContent()) {
details.resolution.append(' ');
}
}
if (details.exceptionStyle == ExceptionStyle.NONE) {
details.resolution.text("Run with ");
details.resolution.withStyle(UserInput).format("--%s", LoggingCommandLineConverter.STACKTRACE_LONG);
details.resolution.text(" option to get the stack trace. ");
}
if (loggingConfiguration.getLogLevel() != LogLevel.DEBUG) {
details.resolution.text("Run with ");
if (loggingConfiguration.getLogLevel() != LogLevel.INFO) {
details.resolution.withStyle(UserInput).format("--%s", LoggingCommandLineConverter.INFO_LONG);
details.resolution.text(" or ");
}
details.resolution.withStyle(UserInput).format("--%s", LoggingCommandLineConverter.DEBUG_LONG);
details.resolution.text(" option to get more log output.");
}
}
private String getMessage(Throwable throwable) {
String message = throwable.getMessage();
if (GUtil.isTrue(message)) {
return message;
}
return String.format("%s (no error message)", throwable.getClass().getName());
}
private void writeFailureDetails(StyledTextOutput output, FailureDetails details) {
if (details.location.getHasContent()) {
output.println();
output.println("* Where:");
details.location.writeTo(output);
output.println();
}
if (details.details.getHasContent()) {
output.println();
output.println("* What went wrong:");
details.details.writeTo(output);
output.println();
}
if (details.resolution.getHasContent()) {
output.println();
output.println("* Try:");
details.resolution.writeTo(output);
output.println();
}
Throwable exception = null;
switch (details.exceptionStyle) {
case NONE:
break;
case FULL:
exception = details.failure;
break;
}
if (exception != null) {
output.println();
output.println("* Exception is:");
output.exception(exception);
output.println();
}
}
private static class FailureDetails {
Throwable failure;
final BufferingStyledTextOutput summary = new BufferingStyledTextOutput();
final BufferingStyledTextOutput details = new BufferingStyledTextOutput();
final BufferingStyledTextOutput location = new BufferingStyledTextOutput();
final BufferingStyledTextOutput resolution = new BufferingStyledTextOutput();
ExceptionStyle exceptionStyle = ExceptionStyle.NONE;
public FailureDetails(Throwable failure) {
this.failure = failure;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy