From 2db435f47ef6f3a9ee1ff8d340ed2fe0e486fcdf Mon Sep 17 00:00:00 2001 From: aboyko Date: Fri, 14 Oct 2022 13:01:37 -0400 Subject: [PATCH] Proper recipe class lookup mechanism for plugged in recipes --- .../commands/RewriteRefactoringsHandler.java | 5 +++-- .../rewrite/test/HelloMethodRenameRecipe.java | 5 +++++ .../ide/vscode/commons/rewrite/LoadUtils.java | 18 +++++++++--------- .../vscode/commons/rewrite/LoadUtilsTest.java | 9 ++++++++- .../java/rewrite/RewriteRecipeRepository.java | 7 ++++--- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java index 21d509b17..e987fabf3 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java @@ -27,6 +27,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.lsp4e.LanguageServiceAccessor; @@ -36,7 +37,6 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.handlers.HandlerUtil; import org.springframework.tooling.boot.ls.BootLanguageServerPlugin; -import org.springsource.ide.eclipse.commons.livexp.util.Log; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -130,7 +130,7 @@ public class RewriteRefactoringsHandler extends AbstractHandler { .toArray(CompletableFuture[]::new)).get(); } } catch (Exception e) { - Log.log(e); + throw new InvocationTargetException(e); } finally { monitor.done(); } @@ -138,6 +138,7 @@ public class RewriteRefactoringsHandler extends AbstractHandler { } catch (CoreException | InvocationTargetException | InterruptedException e) { BootLanguageServerPlugin.getDefault().getLog().error(e.getMessage(), e); + MessageDialog.openError(Display.getCurrent().getActiveShell(), "Error", "Failed to apply Rewrite recipe(s). See error log for more details."); } } }); diff --git a/headless-services/commons/commons-rewrite-test/src/main/java/org/springframework/rewrite/test/HelloMethodRenameRecipe.java b/headless-services/commons/commons-rewrite-test/src/main/java/org/springframework/rewrite/test/HelloMethodRenameRecipe.java index e7f5d9822..eb622dcb0 100644 --- a/headless-services/commons/commons-rewrite-test/src/main/java/org/springframework/rewrite/test/HelloMethodRenameRecipe.java +++ b/headless-services/commons/commons-rewrite-test/src/main/java/org/springframework/rewrite/test/HelloMethodRenameRecipe.java @@ -23,6 +23,11 @@ public class HelloMethodRenameRecipe extends Recipe { public String getDisplayName() { return "Rename hello method into bye"; } + + @Override + public String getDescription() { + return "Renames methods with name 'hello' into same signature methods named 'bye'"; + } @Override protected TreeVisitor getVisitor() { diff --git a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/LoadUtils.java b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/LoadUtils.java index 559109af6..323f38c5a 100644 --- a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/LoadUtils.java +++ b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/LoadUtils.java @@ -19,6 +19,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.function.Function; import org.openrewrite.Recipe; import org.openrewrite.config.DeclarativeRecipe; @@ -50,18 +51,17 @@ public class LoadUtils { } } - @SuppressWarnings("unchecked") - public static Recipe createRecipe(RecipeDescriptor d) { - try { - Class recipeClazz = (Class) Class.forName(d.getName()); - Recipe recipe = constructRecipe(recipeClazz, d.getOptions()); - return recipe; - } catch (ClassNotFoundException e) { - DeclarativeRecipe recipe = new DeclarativeRecipe(d.getName(), d.getDisplayName(), d.getDescription(), d.getTags(), d.getEstimatedEffortPerOccurrence(), d.getSource(), false); + public static Recipe createRecipe(RecipeDescriptor d, Function> getRecipeClass) { + Class recipeClazz = getRecipeClass.apply(d.getName()); + if (recipeClazz == null) { + DeclarativeRecipe recipe = new DeclarativeRecipe(d.getName(), d.getDisplayName(), d.getDescription(), + d.getTags(), d.getEstimatedEffortPerOccurrence(), d.getSource(), false); for (RecipeDescriptor subDescriptor : d.getRecipeList()) { - recipe.doNext(createRecipe(subDescriptor)); + recipe.doNext(createRecipe(subDescriptor, getRecipeClass)); } return recipe; + } else { + return constructRecipe(recipeClazz, d.getOptions()); } } diff --git a/headless-services/commons/commons-rewrite/src/test/java/org/springframework/ide/vscode/commons/rewrite/LoadUtilsTest.java b/headless-services/commons/commons-rewrite/src/test/java/org/springframework/ide/vscode/commons/rewrite/LoadUtilsTest.java index 2e7b9df31..a1390b957 100644 --- a/headless-services/commons/commons-rewrite/src/test/java/org/springframework/ide/vscode/commons/rewrite/LoadUtilsTest.java +++ b/headless-services/commons/commons-rewrite/src/test/java/org/springframework/ide/vscode/commons/rewrite/LoadUtilsTest.java @@ -31,12 +31,19 @@ public class LoadUtilsTest { env = Environment.builder().scanRuntimeClasspath().build(); } + @SuppressWarnings("unchecked") @Test public void createRecipeTest() throws Exception { Recipe r = env.listRecipes().stream().filter(d -> "org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0".equals(d.getName())).findFirst().orElse(null); RecipeDescriptor recipeDescriptor = r.getDescriptor(); assertNotNull(recipeDescriptor); - r = LoadUtils.createRecipe(recipeDescriptor); + r = LoadUtils.createRecipe(recipeDescriptor, id -> { + try { + return (Class) Class.forName(id); + } catch (ClassNotFoundException e) { + return null; + } + }); assertTrue(r instanceof DeclarativeRecipe); assertEquals("org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0", r.getName()); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java index 06de40574..a660d9301 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java @@ -48,6 +48,7 @@ import org.openrewrite.Result; import org.openrewrite.SourceFile; import org.openrewrite.TreeVisitor; import org.openrewrite.Validated; +import org.openrewrite.config.DeclarativeRecipe; import org.openrewrite.config.RecipeDescriptor; import org.openrewrite.config.YamlResourceLoader; import org.openrewrite.java.JavaParser; @@ -338,10 +339,10 @@ public class RewriteRecipeRepository implements ApplicationContextAware { RecipeDescriptor d = serializationGson.fromJson(recipesJson, RecipeDescriptor.class); - Recipe aggregateRecipe = LoadUtils.createRecipe(d); + Recipe aggregateRecipe = LoadUtils.createRecipe(d, id -> getRecipe(id).map(r -> r.getClass()).orElse(null)); - if (aggregateRecipe.getRecipeList().isEmpty()) { - throw new RuntimeException("Not recipes to execute!"); + if (aggregateRecipe instanceof DeclarativeRecipe && aggregateRecipe.getRecipeList().isEmpty()) { + throw new RuntimeException("No recipes found to perform!"); } else if (aggregateRecipe.getRecipeList().size() == 1) { Recipe r = aggregateRecipe.getRecipeList().get(0); String progressToken = params.getWorkDoneToken() == null || params.getWorkDoneToken().getLeft() == null ? r.getName() : params.getWorkDoneToken().getLeft();