I created a custom recipe based on openwrite, why can't it run

93 views Asked by At
  1. my recipe
package com.yourorg;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.*;
import org.openrewrite.internal.lang.NonNull;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.tree.J;

// Making your recipe immutable helps make them idempotent and eliminates categories of possible bugs.
// Configuring your recipe in this way also guarantees that basic validation of parameters will be done for you by rewrite.
// Also note: All recipes must be serializable. This is verified by RewriteTest.rewriteRun() in your tests.
@Value
@EqualsAndHashCode(callSuper = false)
public class SayHelloRecipe extends Recipe {
    @Option(displayName = "Fully Qualified Class Name",
            description = "A fully qualified class name indicating which class to add a hello() method to.",
            example = "com.yourorg.FooBar")
    @NonNull
    String fullyQualifiedClassName;

    // All recipes must be serializable. This is verified by RewriteTest.rewriteRun() in your tests.
    @JsonCreator
    public SayHelloRecipe(@NonNull @JsonProperty("fullyQualifiedClassName") String fullyQualifiedClassName) {
        this.fullyQualifiedClassName = fullyQualifiedClassName;
    }

    @Override
    public String getDisplayName() {
        return "Say Hello";
    }

    @Override
    public String getDescription() {
        return "Adds a \"hello\" method to the specified class.";
    }

    @Override
    public TreeVisitor<?, ExecutionContext> getVisitor() {
        // getVisitor() should always return a new instance of the visitor
        return new SayHelloVisitor();
    }

    public class SayHelloVisitor extends JavaIsoVisitor<ExecutionContext> {
        private final JavaTemplate helloTemplate =
                JavaTemplate.builder( "public String hello() { return \"Hello from #{}!\"; }")
                        .build();

        @Override
        public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext executionContext) {
            // Don't make changes to classes that don't match the fully qualified name
            if (classDecl.getType() == null || !classDecl.getType().getFullyQualifiedName().equals(fullyQualifiedClassName)) {
                return classDecl;
            }

            // Check if the class already has a method named "hello".
            boolean helloMethodExists = classDecl.getBody().getStatements().stream()
                    .filter(statement -> statement instanceof J.MethodDeclaration)
                    .map(J.MethodDeclaration.class::cast)
                    .anyMatch(methodDeclaration -> methodDeclaration.getName().getSimpleName().equals("hello"));

            // If the class already has a `hello()` method, don't make any changes to it.
            if (helloMethodExists) {
                return classDecl;
            }



            // Interpolate the fullyQualifiedClassName into the template and use the resulting LST to update the class body
            classDecl = classDecl.withBody( helloTemplate.apply(new Cursor(getCursor(), classDecl.getBody()),
                    classDecl.getBody().getCoordinates().lastStatement(),
                    fullyQualifiedClassName ));

            return classDecl;
        }
    }
}

2.maven config

           <plugin>
                <groupId>org.openrewrite.maven</groupId>
                <artifactId>rewrite-maven-plugin</artifactId>
                <version>5.20.0</version>
                <configuration>
                    <activeRecipes>
                        <recipe>com.yourorg.sayHelloToFooBar</recipe>
                    </activeRecipes>
                </configuration>
            </plugin>

3.rewrite.yml

---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.sayHelloToFooBar
recipeList:
  - com.yourorg.SayHelloRecipe:
      fullyQualifiedClassName: com.yourorg.FooBar

4. the error info

[ERROR] Recipe validation error in com.yourorg.SayHelloRecipe: Recipe class com.yourorg.SayHelloRecipe cannot be found

[ERROR] Recipe validation error in com.yourorg.SayHelloRecipe: Recipe class com.yourorg.SayHelloRecipe cannot be found

[ERROR] Recipe validation error in com.yourorg.SayHelloRecipe: Recipe class com.yourorg.SayHelloRecipe cannot be found

[ERROR] Recipe validation errors detected as part of one or more activeRecipe(s). Execution will continue regardless.

I want to run the code successfully

1

There are 1 answers

4
Tim On

It seems you're developing a custom recipe. Did you run through the steps to publish it to your local Maven repository? https://github.com/moderneinc/rewrite-recipe-starter?tab=readme-ov-file#local-publishing-for-testing

Once your recipe is published to a jar in your local Maven repository, you'll need to add that jar as a <plugin> <dependency>. As seen on the above link:

<project>
    <build>
        <plugins>
            <plugin>
                <groupId>org.openrewrite.maven</groupId>
                <artifactId>rewrite-maven-plugin</artifactId>
                <version>RELEASE</version>
                <configuration>
                    <activeRecipes>
                        <recipe>com.yourorg.SayHelloToFooBar</recipe>
                    </activeRecipes>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>com.yourorg</groupId>
                        <artifactId>rewrite-recipe-starter</artifactId>
                        <version>0.1.0-SNAPSHOT</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

If you've already done all that it seems you have a casing issue in your configuration. You are using

<recipe>com.yourorg.sayHelloToFooBar</recipe>

Whereas your class uses an upper case S, like so:

<recipe>com.yourorg.SayHelloToFooBar</recipe>