openrewrite / rewrite-jenkins

OpenRewrite recipes to continuously modernize Jenkins plugins.
Apache License 2.0
7 stars 8 forks source link

Translate existing refactoring rules from Jackpot #6

Open jglick opened 1 year ago

jglick commented 1 year ago

Jenkins core already contains some Jackpot-based rules in the META-INF/upgrade pseudo-package. These are offered automatically to plugin developers using the NetBeans IDE. It would be better to delete that and create analogous rules in this repo that anyone could use.

timtebeek commented 1 year ago

Thanks for chiming in here @jglick !

Refaster recipes

I've had a quick look at the .hint files in Jenkins, and it appears to me like quite a few of those would be a candidate for our simplified recipe definitions using the Refaster annotations. See for example UseStringIsEmpty.java:

import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;

public class UseStringIsEmpty {
    @BeforeTemplate
    boolean before(String s) {
        return s.length() > 0;
    }

    @AfterTemplate
    boolean after(String s) {
        return !s.isEmpty();
    }
}

We allow you to write tests for such recipes as well, as seen in UseStringIsEmptyTest.java

    @Test
    void lengthGreaterZero() {
        rewriteRun(
          java( // before
            """
              class Test {
                  void m(String s) {
                      boolean b = s.length() > 0;
                  }
              }
              """, // after
            """
              class Test {
                  void m(String s) {
                      boolean b = !s.isEmpty();
                  }
              }
              """
          )
        );
    }

I don't think it requires a lot of creativity to see how that could serve to similarly convert for instance the use of printStackTrace in META-INF/upgrade/Functions.hint

Declarative recipes

Other simpler one to one replacements can be achieved with a declarative yaml recipe only, such that you can achieve these replacements with three lines of yaml; for instance for META-INF/upgrade/JSR-305.hint

javax.annotation.CheckForNull => edu.umd.cs.findbugs.annotations.CheckForNull;;
javax.annotation.Nonnull => edu.umd.cs.findbugs.annotations.NonNull;;
javax.annotation.Nullable => edu.umd.cs.findbugs.annotations.Nullable;;

In this case, the change type recipe is likely what you need.

type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.ChangeTypeExample
displayName: Change type example
recipeList:
  - org.openrewrite.java.ChangeType:
      oldFullyQualifiedTypeName: javax.annotation.CheckForNull
      newFullyQualifiedTypeName: edu.umd.cs.findbugs.annotations.CheckForNull
  - org.openrewrite.java.ChangeType:
      oldFullyQualifiedTypeName: javax.annotation.Nonnull
      newFullyQualifiedTypeName: edu.umd.cs.findbugs.annotations.NonNull
  - org.openrewrite.java.ChangeType:
      oldFullyQualifiedTypeName: javax.annotation.Nullable
      newFullyQualifiedTypeName: edu.umd.cs.findbugs.annotations.Nullable

Hope that helps get you started! If you have any questions feel free to chime in here or on our public Slack.

sghill commented 1 year ago

I had not seen refaster recipes before - this is great!

Wanted to quickly note that the JSR-305 hint is implemented as org.openrewrite.jenkins.JavaxAnnotationsToSpotbugs with tests.