Skip to content

Commit

Permalink
Suggest alternatives when active recipes are not found (#4169)
Browse files Browse the repository at this point in the history
  • Loading branch information
timtebeek authored May 8, 2024
1 parent f83fd77 commit ec09e19
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 11 deletions.
29 changes: 18 additions & 11 deletions rewrite-core/src/main/java/org/openrewrite/config/Environment.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.openrewrite.config;

import org.apache.commons.lang3.StringUtils;
import org.openrewrite.Contributor;
import org.openrewrite.Recipe;
import org.openrewrite.RecipeException;
Expand All @@ -28,7 +29,10 @@
import java.util.*;

import static java.util.Collections.emptyList;
import static java.util.Comparator.comparingInt;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

public class Environment {
private final Collection<? extends ResourceLoader> resourceLoaders;
Expand Down Expand Up @@ -134,24 +138,27 @@ public Collection<RecipeDescriptor> listRecipeDescriptors() {
}

public Recipe activateRecipes(Iterable<String> activeRecipes) {
List<Recipe> allRecipes = listRecipes();
Map<String, Recipe> recipesByName = listRecipes().stream().collect(toMap(Recipe::getName, identity()));
List<String> recipesNotFound = new ArrayList<>();
List<Recipe> activatedRecipes = new ArrayList<>();
for (String activeRecipe : activeRecipes) {
boolean foundRecipe = false;
for (Recipe recipe : allRecipes) {
if (activeRecipe.equals(recipe.getName())) {
activatedRecipes.add(recipe);
foundRecipe = true;
break;
}
}
if (!foundRecipe) {
Recipe recipe = recipesByName.get(activeRecipe);
if (recipe == null) {
recipesNotFound.add(activeRecipe);
} else {
activatedRecipes.add(recipe);
}
}
if (!recipesNotFound.isEmpty()) {
throw new RecipeException("Recipes not found: " + String.join(", ", recipesNotFound));
List<String> suggestions = recipesNotFound.stream()
.map(r -> recipesByName.keySet().stream()
.min(comparingInt(a -> StringUtils.getLevenshteinDistance(a, r)))
.orElse(r))
.collect(toList());
String message = String.format("Recipes not found: %s\nDid you mean: %s",
String.join(", ", recipesNotFound),
String.join(", ", suggestions));
throw new RecipeException(message);
}
return new CompositeRecipe(activatedRecipes);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.Properties;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.openrewrite.test.SourceSpecs.text;

class EnvironmentTest implements RewriteTest {
Expand Down Expand Up @@ -100,6 +101,41 @@ void listRecipes() {
assertThat(changes).hasSize(1);
}

@Test
void activeRecipeNotFoundSuggestions() {
var env = Environment.builder()
.load(
new YamlResourceLoader(
//language=yml
new ByteArrayInputStream(
"""
type: specs.openrewrite.org/v1beta/recipe
name: test.ChangeTextToHello
displayName: Change text to hello
recipeList:
- org.openrewrite.text.ChangeText:
toText: Hello
---
type: specs.openrewrite.org/v1beta/recipe
name: test.ChangeTextToHelloWorld
displayName: Change text to hello world
recipeList:
- org.openrewrite.text.ChangeText:
toText: Hello
""".getBytes()
),
URI.create("rewrite.yml"),
new Properties()
)
)
.build();

assertThatExceptionOfType(RecipeException.class)
.isThrownBy(() -> env.activateRecipes("foo.ChangeTextToHelloWorld"))
.withMessageContaining("foo.ChangeTextToHelloWorld")
.withMessageContaining("test.ChangeTextToHelloWorld");
}

@Test
void recipeWithoutRequiredConfiguration() {
var env = Environment.builder()
Expand Down

0 comments on commit ec09e19

Please sign in to comment.