Skip to content

Commit ae3448a

Browse files
MBoegersmike-solomontimtebeek
authored
Align SayHelloRecipe in writing-a-java-refactoring-recipe.md with current best practices (#448)
* align references to IntelliJ settings to JetBrains default and make them clickable * Update writing-a-java-refactoring-recipe.md example to use: - available utils - simpler streams - direct `JavaTemplate` usage * adding a description to the declarative usage example to be schema compliant. * merge master and resolve * recapitalize option name * remove `NonNull` as they are usually marked vie the *package-info.java* files. * Update docs/authoring-recipes/writing-a-java-refactoring-recipe.md Co-authored-by: Tim te Beek <[email protected]> --------- Co-authored-by: Mike Solomon <[email protected]> Co-authored-by: Tim te Beek <[email protected]>
1 parent 96c9506 commit ae3448a

File tree

1 file changed

+45
-52
lines changed

1 file changed

+45
-52
lines changed

docs/authoring-recipes/writing-a-java-refactoring-recipe.md

Lines changed: 45 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -473,14 +473,18 @@ With all of that done, the complete `SayHelloRecipe` looks like this:
473473
```java
474474
package com.yourorg;
475475

476-
import com.fasterxml.jackson.annotation.JsonCreator;
477-
import com.fasterxml.jackson.annotation.JsonProperty;
478476
import lombok.EqualsAndHashCode;
479477
import 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;
481482
import org.openrewrite.java.JavaIsoVisitor;
482483
import org.openrewrite.java.JavaTemplate;
483484
import 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
553550
package 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;
557556
import org.openrewrite.java.JavaIsoVisitor;
558557
import org.openrewrite.java.JavaTemplate;
559558
import org.openrewrite.java.tree.J;
559+
import org.openrewrite.java.tree.TypeUtils;
560560

561+
import java.util.Comparator;
561562
import 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
---
675667
type: specs.openrewrite.org/v1beta/recipe
676668
name: com.yourorg.SayHelloToFooBar
669+
description: Add `hello` method to class `com.yourorg.FooBar`.
677670
recipeList:
678671
- com.yourorg.SayHelloRecipe:
679672
fullyQualifiedClassName: com.yourorg.FooBar

0 commit comments

Comments
 (0)