Skip to content

Commit

Permalink
Maven exception handling / fixes #2334
Browse files Browse the repository at this point in the history
  • Loading branch information
jkschneider committed Oct 23, 2022
1 parent b818b09 commit 3bcafba
Show file tree
Hide file tree
Showing 71 changed files with 1,623 additions and 758 deletions.
17 changes: 7 additions & 10 deletions rewrite-core/src/main/java/org/openrewrite/FindParseFailures.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,31 @@

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.marker.Markup;

import java.util.Optional;

@Value
@EqualsAndHashCode(callSuper = true)
public class FindParseFailures extends Recipe {

@Override
public String getDisplayName() {
return "Find source files with `ParseExceptionResult` markers";
}

@Override
public String getDescription() {
return "Find source files with `ParseExceptionResult` markers.";
return "This recipe explores parse failures after an AST is produced for classifying the types of " +
"failures that can occur and prioritizing fixes according to the most common problems.";
}

@Override
protected TreeVisitor<?, ExecutionContext> getVisitor() {
return new TreeVisitor<Tree, ExecutionContext>() {
@Override
public @Nullable Tree visitSourceFile(SourceFile sourceFile, ExecutionContext executionContext) {
Optional<ParseExceptionResult> parseExceptionResult = sourceFile.getMarkers().findFirst(ParseExceptionResult.class);
if (parseExceptionResult.isPresent()) {
return Markup.error(sourceFile, parseExceptionResult.get().getMessage(), null);
}
return sourceFile;
public Tree visitSourceFile(SourceFile sourceFile, ExecutionContext executionContext) {
return sourceFile.getMarkers().findFirst(ParseExceptionResult.class)
.<Tree>map(exceptionResult -> Markup.info(sourceFile, exceptionResult.getMessage()))
.orElse(sourceFile);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,22 @@
*/
package org.openrewrite;

import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Value;
import lombok.With;
import org.openrewrite.internal.ExceptionUtils;
import org.openrewrite.marker.Marker;

import java.util.UUID;

import static org.openrewrite.Tree.randomId;

@Value
@With
public class ParseExceptionResult implements Marker {
UUID id;

String message;

public ParseExceptionResult(Throwable t) {
this(Tree.randomId(), t);
}

public ParseExceptionResult(UUID id, Throwable t) {
//noinspection ConstantConditions
this(id, (t == null) ? "" : new RecipeRunException(t).getSanitizedStackTrace());
}

@JsonCreator
public ParseExceptionResult(UUID id, String message) {
this.id = id;
this.message = message;
public static ParseExceptionResult build(Parser<?> parser, Throwable t) {
return new ParseExceptionResult(randomId(), ExceptionUtils.sanitizeStackTrace(t, parser.getClass()));
}
}
12 changes: 10 additions & 2 deletions rewrite-core/src/main/java/org/openrewrite/PrintOutputCapture.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@

import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.marker.Marker;
import org.openrewrite.marker.Markup;

import java.util.function.UnaryOperator;

public class PrintOutputCapture<P> implements Cloneable{
public class PrintOutputCapture<P> implements Cloneable {
private final P p;
private final MarkerPrinter markerPrinter;
public final StringBuilder out = new StringBuilder();
Expand Down Expand Up @@ -71,7 +72,14 @@ public interface MarkerPrinter {
MarkerPrinter DEFAULT = new MarkerPrinter() {
@Override
public String beforeSyntax(Marker marker, Cursor cursor, UnaryOperator<String> commentWrapper) {
return marker.print(cursor, commentWrapper);
return marker.print(cursor, commentWrapper, false);
}
};

MarkerPrinter VERBOSE = new MarkerPrinter() {
@Override
public String beforeSyntax(Marker marker, Cursor cursor, UnaryOperator<String> commentWrapper) {
return marker.print(cursor, commentWrapper, true);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.openrewrite.internal.FindRecipeRunException;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.internal.MetricsHelper;
import org.openrewrite.internal.RecipeRunException;
import org.openrewrite.marker.Generated;
import org.openrewrite.marker.Markup;
import org.openrewrite.marker.RecipesThatMadeChanges;
Expand Down Expand Up @@ -246,7 +247,7 @@ default <S extends SourceFile> List<S> scheduleVisit(RecipeRunStats runStats,
} else if (afterFile != null) {
// The applicable test threw an exception, but it was not in a visitor. It cannot be associated to any specific line of code,
// and instead we add a marker to the top of the source file to record the exception message.
afterFile = Markup.error(afterFile,"Recipe applicable test failed with an exception.", new RecipeRunException(t));
afterFile = Markup.error(afterFile, t);
}
}

Expand Down Expand Up @@ -391,7 +392,7 @@ public static <S extends SourceFile> List<S> handleUncaughtException(Stack<Recip
.parse("Rewrite encountered an uncaught recipe error in " + recipe.getName() + ".")
.get(0)
.withSourcePath(Paths.get("recipe-exception-" + ctx.incrementAndGetUncaughtExceptionCount() + ".txt"));
exception = Markup.error(exception, "Recipe applicable test failed with an exception.", new RecipeRunException(t));
exception = Markup.error(exception, t);
recipeThatAddedOrDeletedSourceFile.put(exception.getId(), recipeStack);
return ListUtils.concat(before, exception);
}
Expand Down
4 changes: 2 additions & 2 deletions rewrite-core/src/main/java/org/openrewrite/Result.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public class Result {
@Nullable
private Path relativeTo;

public List<RecipeRunException> getRecipeErrors() {
List<RecipeRunException> exceptions = new ArrayList<>();
public List<Throwable> getRecipeErrors() {
List<Throwable> exceptions = new ArrayList<>();
new TreeVisitor<Tree, Integer>() {
@Nullable
@Override
Expand Down
2 changes: 1 addition & 1 deletion rewrite-core/src/main/java/org/openrewrite/SourceFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ default <P> String printAll(P p) {
}

default <P> String printAll(PrintOutputCapture<P> out) {
return print(new Cursor(null, this), out);
return print(new Cursor(null, "root"), out);
}

default String printAll() {
Expand Down
4 changes: 4 additions & 0 deletions rewrite-core/src/main/java/org/openrewrite/TreeVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Timer;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.internal.RecipeRunException;
import org.openrewrite.internal.TreeVisitorAdapter;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.marker.Marker;
import org.openrewrite.marker.Markers;
import org.openrewrite.marker.Markup;

import java.beans.Transient;
import java.lang.reflect.ParameterizedType;
Expand Down Expand Up @@ -203,6 +205,7 @@ public T visitNonNull(Tree tree, P p, Cursor parent) {
@Incubating(since = "7.31.0")
public static <R extends Tree, C extends Collection<R>> C collect(TreeVisitor<?, ExecutionContext> visitor,
Tree tree, C initial) {
//noinspection unchecked
return collect(visitor, tree, initial, Tree.class, t -> (R) t);
}

Expand Down Expand Up @@ -321,6 +324,7 @@ public T visit(@Nullable Tree tree, P p) {
// bubbling up from lower in the tree
throw e;
}

throw new RecipeRunException(e, getCursor());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public List<Binary> parseInputs(Iterable<Input> sources, @Nullable Path relative
null,
readAllBytes(source.getSource(ctx))));
} catch (Exception e) {
ParsingExecutionContextView.view(ctx).parseFailure(path, e);
ParsingExecutionContextView.view(ctx).parseFailure(path, this, e);
ctx.getOnError().accept(e);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2022 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.openrewrite.internal;

import java.util.StringJoiner;

public class ExceptionUtils {
/**
* Shorten a stack trace to the first invocation of a particular class.
*
* @param t The original exception
* @param until Cut the stack trace when it reaches a method in this class.
* @return The sanitized stack trace
*/
public static String sanitizeStackTrace(Throwable t, Class<?> until) {
StringJoiner sanitized = new StringJoiner("\n");
Throwable cause = t instanceof RecipeRunException ? t.getCause() : t;
sanitized.add(cause.getClass().getName() + ": " + cause.getLocalizedMessage());

int i = 0;
for (StackTraceElement stackTraceElement : cause.getStackTrace()) {
if (stackTraceElement.getClassName().equals(until.getName())) {
break;
}
if (i++ >= 8) {
sanitized.add(" ...");
break;
}
sanitized.add(" " + stackTraceElement);
}
return sanitized.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.openrewrite.Tree;
import org.openrewrite.TreeVisitor;
import org.openrewrite.marker.Markup;
import org.openrewrite.RecipeRunException;

import static java.util.Objects.requireNonNull;

Expand All @@ -35,7 +34,7 @@ public FindRecipeRunException(RecipeRunException rre) {
@Override
public Tree preVisit(Tree tree, Integer integer) {
if (tree == nearestTree) {
return Markup.error(tree, "Recipe failed with an exception.", vt);
return Markup.error(tree, vt.getCause());
}
return tree;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite;
package org.openrewrite.internal;

import lombok.Getter;
import org.openrewrite.Cursor;
import org.openrewrite.RecipeScheduler;
import org.openrewrite.internal.lang.Nullable;

import java.util.StringJoiner;
import java.util.UUID;

public class RecipeRunException extends RuntimeException {
@Getter
private final UUID id = UUID.randomUUID();

/**
* Null if the exception occurs outside a visitor in an applicable test, etc.
*/
Expand All @@ -38,26 +31,4 @@ public RecipeRunException(Throwable cause, @Nullable Cursor cursor) {
super(cause);
this.cursor = cursor;
}

public RecipeRunException(Throwable cause) {
this(cause, null);
}

public String getSanitizedStackTrace() {
StringJoiner sanitized = new StringJoiner("\n");
sanitized.add(getCause().getClass().getName() + ": " + getCause().getLocalizedMessage());

int i = 0;
for (StackTraceElement stackTraceElement : getCause().getStackTrace()) {
if (stackTraceElement.getClassName().equals(RecipeScheduler.class.getName())) {
break;
}
if (i++ >= 8) {
sanitized.add(" ...");
break;
}
sanitized.add(" " + stackTraceElement);
}
return sanitized.toString();
}
}
36 changes: 36 additions & 0 deletions rewrite-core/src/main/java/org/openrewrite/internal/Throwing.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2022 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.openrewrite.internal;

import java.util.function.Consumer;

public final class Throwing {
private Throwing() {
}

public static <T> Consumer<T> rethrow(ThrowingConsumer<T> consumer) {
return consumer;
}

/**
* The compiler sees the signature with the throws T inferred to a RuntimeException type, so it
* allows the unchecked exception to propagate. {@see http://www.baeldung.com/java-sneaky-throws}.
*/
@SuppressWarnings("unchecked")
public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
throw (E) e;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2022 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.openrewrite.internal;

import java.util.function.Consumer;

@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

@Override
default void accept(final T e) {
try {
accept0(e);
} catch (Throwable ex) {
Throwing.sneakyThrow(ex);
}
}

void accept0(T e) throws Throwable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public interface Marker {
* @param commentWrapper A function that wraps arbitrary text in a multi-line comment that is language-specific.
* @return The printed representation of the marker.
*/
default String print(Cursor cursor, UnaryOperator<String> commentWrapper) {
default String print(Cursor cursor, UnaryOperator<String> commentWrapper, boolean verbose) {
return "";
}
}

0 comments on commit 3bcafba

Please sign in to comment.