OpenRewrite

Automated Refactorings

Java Software Engineer

Line of Business Public

Merlin Bögershausen / @mboegie

Was ist Refactoring?

Refactoring is a controlled technique for improving the design of an existing code base. Its essence is applying a series of small behavior-preserving transformations, each of which "too small to be worth doing".
— Fowler

Multiline Strings

Klassisch

String query =
  "SELECT * FROM\n" +
  "my_table\n" +
  "WHERE something = 1;";

Java 15+

String query = """
  SELECT * FROM
  my_table
  WHERE something = 1;\
  """;

Framework Migration

Spring Boot 2.7 Migration Guide

Migration Types

Komplexitaet verteiling

Lösung: OpenRewrite

Open Rewrite Logo

Let’s dive in!

Upgrade Spring Boot 2.7 to 3.0 in Spring Pet Clinic Screenshot

Configure Plugin

Auch für Gradle und ohne Modifikationen, siehe Getting Started

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run
<plugin>
  <groupId>org.openrewrite.maven</groupId>
  <artifactId>rewrite-maven-plugin</artifactId>
  <version>4.45.0</version>
</plugin>

Activate Recipe

Komplette Liste verfügbar im Recipe Katalog

-Drewrite.activeRecipes=\
 org.openrewrite.java.RemoveUnusedImports
<configuration>
  <activeRecipes>
    <recipe>
      org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0
    </recipe>
  </activeRecipes>
</configuration>

Refactor!

./mvnw rewrite:run
Changes have been made to .github/workflows/maven-build.yml by:
 org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0
  org.openrewrite.java.spring.boot3.MavenPomUpgrade
   org.openrewrite.java.migrate.JavaVersion17
    org.openrewrite.java.migrate.UpgradeJavaVersion:
      {version=17}
  org.openrewrite.java.migrate.UpgradeToJava17
   org.openrewrite.github.SetupJavaUpgradeJavaVersion

LST

Sicht auf die Dinge, der Lossless Semantic Tree

class A {
  void test() {
    int a;
    a = 0;
  }
}
-J.CompilationUnit
 \-J.ClassDeclaration
   |-J.Identifier | "A"
   \-J.Block
     \-J.MethodDeclaration | "MethodDeclaration{A{name=test,return=void,parameters=[]}}"
       |---J.Primitive | "void"
       |---J.Identifier | "test"

Recipe

Ausführbare Einheit in OpenRewrite, ein Recipe

public class MakePublic extends Recipe {
  @Override
  protected JavaVisitor<ExecutionContext> getVisitor() {
    return new ChangeTypeVisitor();
  }
  public String getDisplayName() {
    return "Make Class Public";
  }
  private class MakePublicVisitor
    extends JavaVisitor<ExecutionContext> {}
}

Visitor

Bearbeite den LST mit Visitors

class JavaVisitor<P> extends TreeVisitor<J, P> {
  J visitStatement(Statement statement) {}
  J visitAnnotatedType(J.AnnotatedType annotatedType)  {}
  J visitAnnotation(J.Annotation annotation) {}
  J visitAssert(J.Assert azzert) {}
  J visitAssignment(J.Assignment assign) {}
  J visitAssignmentOperation(J.AssignmentOperation assignOp) {}
  //...
}

Visitor Implementation

new JavaIsoVisitor<ExecutionContext> {
  public J.ClassDeclaration visitClassDeclaration(
          J.ClassDeclaration cd, ExecutionContext ctx) {
    cd = super.visitClassDeclaration(cd, ctx);
    List<J.Modifier> modifiers = cd.getModifiers();
    modifiers.removeIf(
            m -> J.Modifier.Type.Private.equals(m.getType()));
    // and Protected & Public
    modifiers.add(PUBLIC_MODIFIER);
    return cd.withModifiers(modifiers);
  }
}

Declarative YAML

Wenn es declarative geht, mach es deklarativ

---
type: specs.openrewrite.org/v1beta/recipe
name: io.github.mboegers.rewrite.MakePublic
displayName: Change method access level to public
recipeList:
  - org.openrewrite.java.ChangeMethodAccessLevel:
      methodPattern: *
      newAccessLevel: public
      matchOverrides: null

Styles

type: specs.openrewrite.org/v1beta/style
name: io.moderne.spring.style
styleConfigs:
  - org.openrewrite.java.style.NeedBracesStyle:
      allowSingleLineStatement: false
      allowEmptyLoopBody: true
for(int i = 0; i < 10; i++);
if(success()) return false;
for(int i = 0; i < 10; i++);
if(success()){
    return false;
}

Takeaways

600

Abilities

powerOfRewrite

When?

  • Vereinheitlichung bei unterschiedlichen Adaptionsniveaus 🧐

  • Modernisierung bei Major Updates 🤢

  • Sonar Qube Silencer 🙃

Moderne UI

moderne ui screenshot

Future

  • Basic JavaScript Support in 8.0.0 🥳

  • Var Usage Recipe(s) 🤹‍

  • C# denkbar 😉

.stretch

Image Credits

  • Project Logos from respective Project Page

  • Migration Types from Moderne Prove of Value

  • Moderne UI Screenshot by Author