Skip to content

Commit

Permalink
Add recipe to remove mutable static fields from Recipes (#4557)
Browse files Browse the repository at this point in the history
* Add recipe to remove mutable static fields from Recipes

* Update NoMutableStaticFieldsInRecipes.java
  • Loading branch information
timtebeek authored Oct 8, 2024
1 parent 5e2a0a3 commit 6c1f5c3
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.java.recipes;

import org.openrewrite.ExecutionContext;
import org.openrewrite.Preconditions;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.search.UsesType;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.TypeUtils;

public class NoMutableStaticFieldsInRecipes extends Recipe {
@Override
public String getDisplayName() {
return "Recipe classes should not have mutable `static` fields";
}

@Override
public String getDescription() {
return "Remove mutable static fields from Recipe classes to discourage their use.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(
new UsesType<>("org.openrewrite.Recipe", true),
new JavaIsoVisitor<ExecutionContext>() {
@Override
public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ctx) {
J.ClassDeclaration cd = super.visitClassDeclaration(classDecl, ctx);
if (TypeUtils.isAssignableTo("org.openrewrite.Recipe", cd.getType())) {
return cd.withBody(cd.getBody().withStatements(ListUtils.map(cd.getBody().getStatements(), stmt -> {
if (stmt instanceof J.VariableDeclarations) {
J.VariableDeclarations field = (J.VariableDeclarations) stmt;
if (field.hasModifier(J.Modifier.Type.Static) && !field.hasModifier(J.Modifier.Type.Final)) {
// We want to discourage the use of mutable static fields in recipes,
// so rather than make them immutable, we'll just remove the field.
// Any fields that were intended as constants should be made final.
return null;
}
}
return stmt;
})
));
}
return cd;
}
}
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.java.recipes;

import org.junit.jupiter.api.Test;
import org.openrewrite.DocumentExample;
import org.openrewrite.java.JavaParser;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.java.Assertions.java;

class NoMutableStaticFieldsInRecipesTest implements RewriteTest {

@Override
public void defaults(RecipeSpec spec) {
spec
.recipe(new NoMutableStaticFieldsInRecipes())
.parser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()));
}

@Test
@DocumentExample
void removeNonFinalStaticFields() {
rewriteRun(
java(
"""
import org.openrewrite.Recipe;
public class A extends Recipe {
static final int immutable = 0;
static int mutable = 0;
}
""",
"""
import org.openrewrite.Recipe;
public class A extends Recipe {
static final int immutable = 0;
}
"""
)
);
}

@Test
void retainFieldsOutsideRecipes() {
rewriteRun(
java(
"""
import org.openrewrite.Recipe;
public class A {
static final int immutable = 0;
static int mutable = 0;
}
"""
)
);
}
}

0 comments on commit 6c1f5c3

Please sign in to comment.