|
26 | 26 | import java.time.Duration; |
27 | 27 | import java.util.*; |
28 | 28 | import java.util.function.Function; |
29 | | -import java.util.function.Supplier; |
30 | 29 |
|
31 | 30 | import static java.util.Collections.emptyList; |
32 | 31 | import static org.openrewrite.Validated.invalid; |
@@ -162,16 +161,12 @@ private void initializeDeclarativeRecipe(DeclarativeRecipe declarativeRecipe, St |
162 | 161 | } |
163 | 162 | } |
164 | 163 |
|
165 | | - @JsonIgnore |
166 | | - private transient ThreadLocal<Accumulator> accumulator = new ThreadLocal<>(); |
167 | | - |
168 | 164 | @Override |
169 | 165 | public Accumulator getInitialValue(ExecutionContext ctx) { |
170 | 166 | Accumulator acc = new Accumulator(); |
171 | 167 | for (Recipe precondition : preconditions) { |
172 | 168 | registerNestedScanningRecipes(precondition, acc, ctx); |
173 | 169 | } |
174 | | - accumulator.set(acc); |
175 | 170 | return acc; |
176 | 171 | } |
177 | 172 |
|
@@ -223,27 +218,43 @@ static class PreconditionBellwether extends Recipe { |
223 | 218 | String description = "Evaluates a precondition and makes that result available to the preconditions of other recipes. " + |
224 | 219 | "\"bellwether\", noun - One that serves as a leader or as a leading indicator of future trends."; |
225 | 220 |
|
226 | | - Supplier<TreeVisitor<?, ExecutionContext>> precondition; |
| 221 | + DeclarativeRecipe declarativeRecipe; |
227 | 222 |
|
228 | 223 | @NonFinal |
229 | 224 | transient boolean preconditionApplicable; |
230 | 225 |
|
231 | 226 | @Override |
232 | 227 | public TreeVisitor<?, ExecutionContext> getVisitor() { |
233 | 228 | return new TreeVisitor<Tree, ExecutionContext>() { |
234 | | - final TreeVisitor<?, ExecutionContext> p = precondition.get(); |
| 229 | + @Nullable |
| 230 | + TreeVisitor<?, ExecutionContext> p; |
235 | 231 |
|
236 | 232 | @Override |
237 | 233 | public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { |
238 | | - return p.isAcceptable(sourceFile, ctx); |
| 234 | + // p is lazily resolved in visit() where the cursor is available. |
| 235 | + // Before that, conservatively accept all source files. |
| 236 | + return p == null || p.isAcceptable(sourceFile, ctx); |
239 | 237 | } |
240 | 238 |
|
241 | 239 | @Override |
242 | 240 | public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx) { |
243 | | - Tree t = p.visit(tree, ctx); |
| 241 | + Tree t = resolve(ctx).visit(tree, ctx); |
244 | 242 | preconditionApplicable = t != tree; |
245 | 243 | return tree; |
246 | 244 | } |
| 245 | + |
| 246 | + private TreeVisitor<?, ExecutionContext> resolve(ExecutionContext ctx) { |
| 247 | + if (p == null) { |
| 248 | + Cursor rootCursor = getCursor().getRoot(); |
| 249 | + List<TreeVisitor<?, ExecutionContext>> andVisitors = new ArrayList<>(); |
| 250 | + for (Recipe precondition : declarativeRecipe.preconditions) { |
| 251 | + andVisitors.add(declarativeRecipe.orVisitors(precondition, rootCursor, ctx)); |
| 252 | + } |
| 253 | + //noinspection unchecked |
| 254 | + p = Preconditions.and(andVisitors.toArray(new TreeVisitor[0])); |
| 255 | + } |
| 256 | + return p; |
| 257 | + } |
247 | 258 | }; |
248 | 259 | } |
249 | 260 | } |
@@ -496,36 +507,30 @@ public final List<Recipe> getRecipeList() { |
496 | 507 | return recipeList; |
497 | 508 | } |
498 | 509 |
|
499 | | - List<Supplier<TreeVisitor<?, ExecutionContext>>> andPreconditions = new ArrayList<>(); |
500 | | - for (Recipe precondition : preconditions) { |
501 | | - andPreconditions.add(() -> orVisitors(precondition)); |
502 | | - } |
503 | | - //noinspection unchecked |
504 | | - PreconditionBellwether bellwether = new PreconditionBellwether(Preconditions.and(andPreconditions.toArray(new Supplier[]{}))); |
| 510 | + PreconditionBellwether bellwether = new PreconditionBellwether(this); |
505 | 511 | List<Recipe> recipeListWithBellwether = new ArrayList<>(recipeList.size() + 1); |
506 | 512 | recipeListWithBellwether.add(bellwether); |
507 | 513 | recipeListWithBellwether.addAll(decorateWithPreconditionBellwether(bellwether, recipeList)); |
508 | 514 | return recipeListWithBellwether; |
509 | 515 | } |
510 | 516 |
|
511 | | - private TreeVisitor<?, ExecutionContext> orVisitors(Recipe recipe) { |
| 517 | + @SuppressWarnings({"rawtypes", "unchecked"}) |
| 518 | + private TreeVisitor<?, ExecutionContext> orVisitors(Recipe recipe, Cursor rootCursor, ExecutionContext ctx) { |
512 | 519 | List<TreeVisitor<?, ExecutionContext>> conditions = new ArrayList<>(); |
513 | 520 | if (recipe instanceof ScanningRecipe) { |
514 | | - //noinspection rawtypes |
515 | 521 | ScanningRecipe scanning = (ScanningRecipe) recipe; |
516 | | - //noinspection unchecked |
517 | | - Accumulator acc = accumulator.get(); |
518 | | - conditions.add(scanning.getVisitor(acc != null ? acc.recipeToAccumulator.get(scanning) : null)); |
| 522 | + Accumulator acc = getAccumulator(rootCursor, ctx); |
| 523 | + Object recipeAcc = acc.recipeToAccumulator.get(scanning); |
| 524 | + conditions.add(scanning.getVisitor(recipeAcc)); |
519 | 525 | } else { |
520 | 526 | conditions.add(recipe.getVisitor()); |
521 | 527 | } |
522 | 528 | for (Recipe r : recipe.getRecipeList()) { |
523 | | - conditions.add(orVisitors(r)); |
| 529 | + conditions.add(orVisitors(r, rootCursor, ctx)); |
524 | 530 | } |
525 | 531 | if (conditions.size() == 1) { |
526 | 532 | return conditions.get(0); |
527 | 533 | } |
528 | | - //noinspection unchecked |
529 | 534 | return Preconditions.or(conditions.toArray(new TreeVisitor[0])); |
530 | 535 | } |
531 | 536 |
|
@@ -608,16 +613,9 @@ private static class LazyLoadedRecipe extends Recipe { |
608 | 613 | String description = "Recipe that is loaded lazily."; |
609 | 614 | } |
610 | 615 |
|
611 | | - @Override |
612 | | - public void onComplete(ExecutionContext ctx) { |
613 | | - accumulator.remove(); |
614 | | - } |
615 | | - |
616 | 616 | @Override |
617 | 617 | public DeclarativeRecipe clone() { |
618 | | - DeclarativeRecipe cloned = (DeclarativeRecipe) super.clone(); |
619 | | - cloned.accumulator = new ThreadLocal<>(); |
620 | | - return cloned; |
| 618 | + return (DeclarativeRecipe) super.clone(); |
621 | 619 | } |
622 | 620 |
|
623 | 621 | @Override |
|
0 commit comments