Skip to content

Commit

Permalink
Rewrite RPC can run recipes that have recipe lists
Browse files Browse the repository at this point in the history
  • Loading branch information
jkschneider committed Feb 26, 2025
1 parent 4f0f666 commit 04dd449
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 23 deletions.
8 changes: 4 additions & 4 deletions rewrite-core/src/main/java/org/openrewrite/Recipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ public List<Recipe> getRecipeList() {
}

/**
* Used to build up a recipe list programmatically. Using the
* Used to build up a recipe recipes programmatically. Using the
* methods on {@link RecipeList}, the appearance of a recipe
* that chains other recipes with options will be not strikingly
* different from defining it in a recipe.yml.
Expand All @@ -351,16 +351,16 @@ public List<Recipe> getRecipeList() {
* since these assistants are primarily optimized for providing completion
* assistance in a single file.
* <p>
* When creating a recipe with a fixed recipe list, either override
* When creating a recipe with a fixed recipe recipes, either override
* this method or {@link #getRecipeList()} but ideally not
* both, as their default implementations are interconnected.
*
* @param list A recipe list used to build up a series of recipes
* @param recipes A recipe recipes used to build up a series of recipes
* in code in a way that looks fairly declarative and
* therefore is more amenable to AI code completion.
*/
@SuppressWarnings("unused")
public void buildRecipeList(RecipeList list) {
public void buildRecipeList(RecipeList recipes) {
}

/**
Expand Down
14 changes: 0 additions & 14 deletions rewrite-core/src/main/java/org/openrewrite/ScanningRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
Expand Down Expand Up @@ -128,17 +127,4 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) {
}
};
}

/**
* For now, ScanningRecipes do not support `getRecipeList`, as the accumulator is not evaluated for these methods
*/
@Override
public final List<Recipe> getRecipeList() {
return super.getRecipeList();
}

@Override
public final void buildRecipeList(RecipeList list) {
super.buildRecipeList(list);
}
}
20 changes: 18 additions & 2 deletions rewrite-core/src/main/java/org/openrewrite/rpc/RpcRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,25 @@
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.openrewrite.*;
import org.openrewrite.config.OptionDescriptor;
import org.openrewrite.config.RecipeDescriptor;
import org.openrewrite.config.RecipeExample;

import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static java.util.Objects.requireNonNull;
import java.util.stream.Collectors;


@RequiredArgsConstructor
public class RpcRecipe extends ScanningRecipe<Integer> {
private final transient RewriteRpc rpc;

@Nullable
private transient List<Recipe> recipeList;

/**
* The ID that the remote is using to refer to this recipe.
*/
Expand Down Expand Up @@ -121,6 +125,18 @@ public TreeVisitor<?, ExecutionContext> getVisitor(Integer acc) {
};
}

@Override
public synchronized List<Recipe> getRecipeList() {
if (recipeList == null) {
recipeList = descriptor.getRecipeList().stream()
.map(r -> rpc.prepareRecipe(r.getName(), r.getOptions().stream()
.filter(opt -> opt.getValue() != null)
.collect(Collectors.toMap(OptionDescriptor::getName, OptionDescriptor::getValue))))
.collect(Collectors.toList());
}
return recipeList;
}

@Override
public void onComplete(ExecutionContext ctx) {
// This will merge data tables from the remote into the local context.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ public String getDescription() {
}

@Override
public void buildRecipeList(RecipeList list) {
list
public void buildRecipeList(RecipeList recipes) {
recipes
// TODO would these large option-set recipes
// benefit from builders?
.recipe(new FindAndReplace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.openrewrite.test.RewriteTest.toRecipe;
import static org.openrewrite.test.SourceSpecs.text;
Expand Down Expand Up @@ -90,7 +91,7 @@ void sendReceiveIdempotence() {
public Tree preVisit(@NonNull Tree tree, ExecutionContext ctx) {
Tree t = server.visit((SourceFile) tree, ChangeText.class.getName(), 0);
stopAfterPreVisit();
return t;
return requireNonNull(t);
}
})),
text(
Expand Down Expand Up @@ -161,6 +162,19 @@ void runScanningRecipeThatGenerates() {
);
}

@Test
void runRecipeWithRecipeList() {
rewriteRun(
spec -> spec
.recipe(server.prepareRecipe("org.openrewrite.rpc.RewriteRpcTest$RecipeWithRecipeList", Map.of()))
.validateRecipeSerialization(false),
text(
"hi",
"hello"
)
);
}

@Test
void getCursor() {
Cursor parent = new Cursor(null, Cursor.ROOT_VALUE);
Expand All @@ -179,4 +193,22 @@ public PlainText visitText(PlainText text, Integer p) {
return text.withText("Hello World!");
}
}

@SuppressWarnings("unused")
static class RecipeWithRecipeList extends Recipe {
@Override
public String getDisplayName() {
return "A recipe that has a recipe list";
}

@Override
public String getDescription() {
return "To verify that it is possible for a recipe list to be called over RPC.";
}

@Override
public void buildRecipeList(RecipeList recipes) {
recipes.recipe(new org.openrewrite.text.ChangeText("hello"));
}
}
}

0 comments on commit 04dd449

Please sign in to comment.