Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.time.Duration;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;

import static java.util.Collections.emptyList;
import static org.openrewrite.Validated.invalid;
Expand Down Expand Up @@ -162,16 +161,12 @@ private void initializeDeclarativeRecipe(DeclarativeRecipe declarativeRecipe, St
}
}

@JsonIgnore
private transient ThreadLocal<Accumulator> accumulator = new ThreadLocal<>();

@Override
public Accumulator getInitialValue(ExecutionContext ctx) {
Accumulator acc = new Accumulator();
for (Recipe precondition : preconditions) {
registerNestedScanningRecipes(precondition, acc, ctx);
}
accumulator.set(acc);
return acc;
}

Expand Down Expand Up @@ -223,27 +218,43 @@ static class PreconditionBellwether extends Recipe {
String description = "Evaluates a precondition and makes that result available to the preconditions of other recipes. " +
"\"bellwether\", noun - One that serves as a leader or as a leading indicator of future trends.";

Supplier<TreeVisitor<?, ExecutionContext>> precondition;
DeclarativeRecipe declarativeRecipe;

@NonFinal
transient boolean preconditionApplicable;

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return new TreeVisitor<Tree, ExecutionContext>() {
final TreeVisitor<?, ExecutionContext> p = precondition.get();
@Nullable
TreeVisitor<?, ExecutionContext> p;

@Override
public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) {
return p.isAcceptable(sourceFile, ctx);
// p is lazily resolved in visit() where the cursor is available.
// Before that, conservatively accept all source files.
return p == null || p.isAcceptable(sourceFile, ctx);
}

@Override
public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
Tree t = p.visit(tree, ctx);
Tree t = resolve(ctx).visit(tree, ctx);
preconditionApplicable = t != tree;
return tree;
}

private TreeVisitor<?, ExecutionContext> resolve(ExecutionContext ctx) {
if (p == null) {
Cursor rootCursor = getCursor().getRoot();
List<TreeVisitor<?, ExecutionContext>> andVisitors = new ArrayList<>();
for (Recipe precondition : declarativeRecipe.preconditions) {
andVisitors.add(declarativeRecipe.orVisitors(precondition, rootCursor, ctx));
}
//noinspection unchecked
p = Preconditions.and(andVisitors.toArray(new TreeVisitor[0]));
}
return p;
}
};
}
}
Expand Down Expand Up @@ -496,36 +507,30 @@ public final List<Recipe> getRecipeList() {
return recipeList;
}

List<Supplier<TreeVisitor<?, ExecutionContext>>> andPreconditions = new ArrayList<>();
for (Recipe precondition : preconditions) {
andPreconditions.add(() -> orVisitors(precondition));
}
//noinspection unchecked
PreconditionBellwether bellwether = new PreconditionBellwether(Preconditions.and(andPreconditions.toArray(new Supplier[]{})));
PreconditionBellwether bellwether = new PreconditionBellwether(this);
List<Recipe> recipeListWithBellwether = new ArrayList<>(recipeList.size() + 1);
recipeListWithBellwether.add(bellwether);
recipeListWithBellwether.addAll(decorateWithPreconditionBellwether(bellwether, recipeList));
return recipeListWithBellwether;
}

private TreeVisitor<?, ExecutionContext> orVisitors(Recipe recipe) {
@SuppressWarnings({"rawtypes", "unchecked"})
private TreeVisitor<?, ExecutionContext> orVisitors(Recipe recipe, Cursor rootCursor, ExecutionContext ctx) {
List<TreeVisitor<?, ExecutionContext>> conditions = new ArrayList<>();
if (recipe instanceof ScanningRecipe) {
//noinspection rawtypes
ScanningRecipe scanning = (ScanningRecipe) recipe;
//noinspection unchecked
Accumulator acc = accumulator.get();
conditions.add(scanning.getVisitor(acc != null ? acc.recipeToAccumulator.get(scanning) : null));
Accumulator acc = getAccumulator(rootCursor, ctx);
Object recipeAcc = acc.recipeToAccumulator.get(scanning);
conditions.add(scanning.getVisitor(recipeAcc));
} else {
conditions.add(recipe.getVisitor());
}
for (Recipe r : recipe.getRecipeList()) {
conditions.add(orVisitors(r));
conditions.add(orVisitors(r, rootCursor, ctx));
}
if (conditions.size() == 1) {
return conditions.get(0);
}
//noinspection unchecked
return Preconditions.or(conditions.toArray(new TreeVisitor[0]));
}

Expand Down Expand Up @@ -608,16 +613,9 @@ private static class LazyLoadedRecipe extends Recipe {
String description = "Recipe that is loaded lazily.";
}

@Override
public void onComplete(ExecutionContext ctx) {
accumulator.remove();
}

@Override
public DeclarativeRecipe clone() {
DeclarativeRecipe cloned = (DeclarativeRecipe) super.clone();
cloned.accumulator = new ThreadLocal<>();
return cloned;
return (DeclarativeRecipe) super.clone();
}

@Override
Expand Down