@@ -473,14 +473,18 @@ With all of that done, the complete `SayHelloRecipe` looks like this:
473473``` java
474474package com.yourorg ;
475475
476- import com.fasterxml.jackson.annotation.JsonCreator ;
477- import com.fasterxml.jackson.annotation.JsonProperty ;
478476import lombok.EqualsAndHashCode ;
479477import lombok.Value ;
480- import org.openrewrite.* ;
478+ import org.openrewrite.ExecutionContext ;
479+ import org.openrewrite.Option ;
480+ import org.openrewrite.Recipe ;
481+ import org.openrewrite.TreeVisitor ;
481482import org.openrewrite.java.JavaIsoVisitor ;
482483import org.openrewrite.java.JavaTemplate ;
483484import org.openrewrite.java.tree.J ;
485+ import org.openrewrite.java.tree.TypeUtils ;
486+
487+ import java.util.Comparator ;
484488
485489// Making your recipe immutable helps make them idempotent and eliminates categories of possible bugs.
486490// Configuring your recipe in this way also guarantees that basic validation of parameters will be done for you by rewrite.
@@ -493,20 +497,14 @@ public class SayHelloRecipe extends Recipe {
493497 example = " com.yourorg.FooBar" )
494498 String fullyQualifiedClassName;
495499
496- // All recipes must be serializable. This is verified by RewriteTest.rewriteRun() in your tests.
497- @JsonCreator
498- public SayHelloRecipe (@JsonProperty (" fullyQualifiedClassName" ) String fullyQualifiedClassName ) {
499- this . fullyQualifiedClassName = fullyQualifiedClassName;
500- }
501-
502500 @Override
503501 public String getDisplayName () {
504502 return " Say 'Hello'" ;
505503 }
506504
507505 @Override
508506 public String getDescription () {
509- return " Adds a \" hello\" method to the specified class." ;
507+ return " Adds a ` hello` method to the specified class." ;
510508 }
511509
512510 @Override
@@ -515,34 +513,33 @@ public class SayHelloRecipe extends Recipe {
515513 return new JavaIsoVisitor<ExecutionContext > () {
516514
517515 @Override
518- public J .ClassDeclaration visitClassDeclaration (J .ClassDeclaration classDecl , ExecutionContext executionContext ) {
516+ public J .ClassDeclaration visitClassDeclaration (J .ClassDeclaration classDecl , ExecutionContext ctx ) {
519517 // Don't make changes to classes that don't match the fully qualified name
520- if (classDecl . getType() == null || ! classDecl. getType(). getFullyQualifiedName() . equals( fullyQualifiedClassName)) {
518+ if (! TypeUtils . isOfClassType( classDecl. getType(), fullyQualifiedClassName)) {
521519 return classDecl;
522520 }
523521
524522 // Check if the class already has a method named "hello".
525523 boolean helloMethodExists = classDecl. getBody(). getStatements(). stream()
526- .filter(statement - > statement instanceof J . MethodDeclaration )
524+ .filter(J . MethodDeclaration . class :: isInstance )
527525 .map(J . MethodDeclaration . class:: cast)
528- .anyMatch(methodDeclaration - > " hello" . equals(methodDeclaration. getName(). getSimpleName()));
526+ .map(J . MethodDeclaration :: getSimpleName)
527+ .anyMatch(" hello" :: equals);
529528
530529 // If the class already has a `hello()` method, don't make any changes to it.
531530 if (helloMethodExists) {
532531 return classDecl;
533532 }
534533
535- // Interpolate the fullyQualifiedClassName into the template and use the resulting LST to update the class body
536- J . Block block = JavaTemplate . apply(
534+ // insert the defined method into the existing class declaration
535+ return JavaTemplate . apply(
537536 " public String hello() { return \" Hello from #{}!\" ; }" ,
538- new Cursor (getCursor(), classDecl. getBody() ),
539- classDecl. getBody(). getCoordinates(). lastStatement( ),
537+ updateCursor( classDecl),
538+ classDecl. getBody(). getCoordinates(). addMethodDeclaration( Comparator . comparing( J . MethodDeclaration :: getSimpleName) ),
540539 fullyQualifiedClassName);
541- return classDecl. withBody(block);
542540 }
543541 };
544542 }
545-
546543}
547544```
548545</TabItem >
@@ -552,25 +549,28 @@ public class SayHelloRecipe extends Recipe {
552549``` java
553550package com.yourorg ;
554551
555- import com.fasterxml.jackson.annotation.JsonProperty ;
556- import org.openrewrite.* ;
552+ import org.openrewrite.ExecutionContext ;
553+ import org.openrewrite.Option ;
554+ import org.openrewrite.Recipe ;
555+ import org.openrewrite.TreeVisitor ;
557556import org.openrewrite.java.JavaIsoVisitor ;
558557import org.openrewrite.java.JavaTemplate ;
559558import org.openrewrite.java.tree.J ;
559+ import org.openrewrite.java.tree.TypeUtils ;
560560
561+ import java.util.Comparator ;
561562import java.util.Objects ;
562563
563564// Making your recipe immutable helps make them idempotent and eliminates categories of possible bugs.
564565// Configuring your recipe in this way also guarantees that basic validation of parameters will be done for you by rewrite.
565566// Also note: All recipes must be serializable. This is verified by RewriteTest.rewriteRun() in your tests.
566- public class SayHelloRecipe extends Recipe {
567- @Option (displayName = " Fully qualified class name " ,
568- description = " A fully qualified class name indicating which class to add a hello() method to." ,
569- example = " com.yourorg.FooBar" )
570- String fullyQualifiedClassName;
567+ public final class SayHelloRecipe extends Recipe {
568+ @Option (displayName = " Fully Qualified Class Name " ,
569+ description = " A fully qualified class name indicating which class to add a ` hello()` method to." ,
570+ example = " ` com.yourorg.FooBar` " )
571+ private final String fullyQualifiedClassName;
571572
572- // All recipes must be serializable. This is verified by RewriteTest.rewriteRun() in your tests.
573- public SayHelloRecipe (@JsonProperty (" fullyQualifiedClassName" ) String fullyQualifiedClassName ) {
573+ public SayHelloRecipe (String fullyQualifiedClassName ) {
574574 this . fullyQualifiedClassName = fullyQualifiedClassName;
575575 }
576576
@@ -581,7 +581,7 @@ public class SayHelloRecipe extends Recipe {
581581
582582 @Override
583583 public String getDescription () {
584- return " Adds a \" hello\" method to the specified class." ;
584+ return " Adds a ` hello` method to the specified class." ;
585585 }
586586
587587 @Override
@@ -590,40 +590,39 @@ public class SayHelloRecipe extends Recipe {
590590 return new JavaIsoVisitor<ExecutionContext > () {
591591
592592 @Override
593- public J .ClassDeclaration visitClassDeclaration (J .ClassDeclaration classDecl , ExecutionContext executionContext ) {
593+ public J .ClassDeclaration visitClassDeclaration (J .ClassDeclaration classDecl , ExecutionContext ctx ) {
594594 // Don't make changes to classes that don't match the fully qualified name
595- if (classDecl . getType() == null || ! classDecl. getType(). getFullyQualifiedName() . equals( fullyQualifiedClassName)) {
595+ if (! TypeUtils . isOfClassType( classDecl. getType(), fullyQualifiedClassName)) {
596596 return classDecl;
597597 }
598598
599599 // Check if the class already has a method named "hello".
600600 boolean helloMethodExists = classDecl. getBody(). getStatements(). stream()
601- .filter(statement - > statement instanceof J . MethodDeclaration )
601+ .filter(J . MethodDeclaration . class :: isInstance )
602602 .map(J . MethodDeclaration . class:: cast)
603- .anyMatch(methodDeclaration - > methodDeclaration. getName(). getSimpleName(). equals(" hello" ));
603+ .map(J . MethodDeclaration :: getSimpleName)
604+ .anyMatch(" hello" :: equals);
604605
605606 // If the class already has a `hello()` method, don't make any changes to it.
606607 if (helloMethodExists) {
607608 return classDecl;
608609 }
609610
610- // Interpolate the fullyQualifiedClassName into the template and use the resulting LST to update the class body
611- J . Block body = JavaTemplate . apply(
611+ // insert the defined method into the existing class declaration
612+ return JavaTemplate . apply(
612613 " public String hello() { return \" Hello from #{}!\" ; }" ,
613- new Cursor (getCursor(), classDecl. getBody() ),
614- classDecl. getBody(). getCoordinates(). lastStatement( ),
614+ updateCursor( classDecl),
615+ classDecl. getBody(). getCoordinates(). addMethodDeclaration( Comparator . comparing( J . MethodDeclaration :: getSimpleName) ),
615616 fullyQualifiedClassName);
616- return classDecl. withBody(body);
617617 }
618618 };
619619 }
620620
621- public String getFullyQualifiedClassName () {
622- return fullyQualifiedClassName;
623- }
624-
625- public void setFullyQualifiedClassName (String fullyQualifiedClassName ) {
626- this . fullyQualifiedClassName = fullyQualifiedClassName;
621+ @Override
622+ public String toString () {
623+ return " SayHelloRecipe{" +
624+ " fullyQualifiedClassName='" + fullyQualifiedClassName + ' \' ' +
625+ ' }' ;
627626 }
628627
629628 @Override
@@ -639,13 +638,6 @@ public class SayHelloRecipe extends Recipe {
639638 public int hashCode () {
640639 return Objects . hash(super . hashCode(), fullyQualifiedClassName);
641640 }
642-
643- @Override
644- public String toString () {
645- return " SayHelloRecipe{" +
646- " fullyQualifiedClassName='" + fullyQualifiedClassName + ' \' ' +
647- ' }' ;
648- }
649641}
650642```
651643</TabItem >
@@ -674,6 +666,7 @@ class FooBar {
674666---
675667type : specs.openrewrite.org/v1beta/recipe
676668name : com.yourorg.SayHelloToFooBar
669+ description : Add `hello` method to class `com.yourorg.FooBar`.
677670recipeList :
678671 - com.yourorg.SayHelloRecipe :
679672 fullyQualifiedClassName : com.yourorg.FooBar
0 commit comments