Created
January 14, 2024 21:03
-
-
Save Bit-Flipper/50af8ea183d1c92140853fa6ca60ce2e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.example; | |
import lombok.EqualsAndHashCode; | |
import lombok.Getter; | |
import lombok.Value; | |
import org.openrewrite.ExecutionContext; | |
import org.openrewrite.Recipe; | |
import org.openrewrite.TreeVisitor; | |
import org.openrewrite.java.JavaIsoVisitor; | |
import org.openrewrite.java.JavaParser; | |
import org.openrewrite.java.JavaTemplate; | |
import org.openrewrite.java.tree.J; | |
import org.openrewrite.java.tree.JavaType; | |
import org.openrewrite.java.tree.Statement; | |
import org.openrewrite.java.tree.TypeTree; | |
import java.util.Comparator; | |
import java.util.List; | |
import java.util.Optional; | |
import java.util.Set; | |
import java.util.stream.Collectors; | |
@Value | |
@EqualsAndHashCode(callSuper = true) | |
public class JavaGetterToLombokGetter extends Recipe { | |
@Override | |
public String getDisplayName() { | |
return "Java getter to lombok getter"; | |
} | |
@Override | |
public String getDescription() { | |
return "Replaces simple Java getter methods with lombok @Getter annotations."; | |
} | |
private static final String GETTER_METHODS_TO_DELETE_KEY = "GETTER_METHODS_TO_DELETE_KEY"; | |
private static final String GET = "get"; | |
@Override | |
public TreeVisitor<?, ExecutionContext> getVisitor() { | |
return new JavaIsoVisitor<>() { | |
@Override | |
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext executionContext) { | |
multiVariable = super.visitVariableDeclarations(multiVariable, executionContext); | |
if (multiVariable.getVariables().size() != 1) { | |
return multiVariable; | |
} | |
J.ClassDeclaration classDeclaration = getCursor().dropParentUntil(p -> p instanceof J.ClassDeclaration).getValue(); | |
Set<J.MethodDeclaration> getterDeclarations = classDeclaration.getBody() | |
.getStatements() | |
.stream() | |
.filter(s -> s instanceof J.MethodDeclaration) | |
.map(s -> (J.MethodDeclaration) s) | |
.collect(Collectors.toSet()); | |
Optional<J.MethodDeclaration> maybeMethodDeclaration = findMatchingGetterDeclaration(multiVariable, getterDeclarations); | |
if (maybeMethodDeclaration.isEmpty()) { | |
return multiVariable; | |
} | |
executionContext.putMessageInSet(GETTER_METHODS_TO_DELETE_KEY, maybeMethodDeclaration.get()); | |
maybeAddImport(Getter.class.getTypeName(), false); | |
return addLombokGetterAnnotationTo(multiVariable); | |
} | |
private Optional<J.MethodDeclaration> findMatchingGetterDeclaration(J.VariableDeclarations multiVariable, Set<J.MethodDeclaration> methodDeclarations) { | |
for (J.MethodDeclaration methodDeclaration : methodDeclarations) { | |
J.VariableDeclarations.NamedVariable namedVariable = multiVariable.getVariables().get(0); | |
String simpleMethodName = methodDeclaration.getSimpleName(); | |
String fieldName = simpleMethodName.substring(GET.length()); | |
fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); | |
if (!simpleMethodName.startsWith(GET) || !fieldName.equals(namedVariable.getSimpleName())) { | |
continue; | |
} | |
TypeTree returnType = methodDeclaration.getReturnTypeExpression(); | |
if (!multiVariable.getType().equals(returnType.getType())) { | |
continue; | |
} | |
List<Statement> statements = methodDeclaration.getBody().getStatements(); | |
if (statements.size() != 1) { | |
continue; | |
} | |
Statement statement = statements.get(0); | |
if (!(statement instanceof J.Return) || !(((J.Return) statement).getExpression() instanceof J.Identifier)) { | |
continue; | |
} | |
JavaType.Variable methodFieldReturned = ((J.Identifier) ((J.Return) statement).getExpression()).getFieldType(); | |
JavaType.Variable field = multiVariable.getVariables().get(0).getVariableType(); | |
if (!methodFieldReturned.equals(field)) { | |
continue; | |
} | |
return Optional.of(methodDeclaration); | |
} | |
return Optional.empty(); | |
} | |
private J.VariableDeclarations addLombokGetterAnnotationTo(J.VariableDeclarations multiVariable) { | |
return JavaTemplate.builder("@Getter") | |
.javaParser(JavaParser.fromJavaVersion()) | |
.build() | |
.apply(getCursor(), multiVariable.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::toString))); | |
} | |
@Override | |
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) { | |
method = super.visitMethodDeclaration(method, executionContext); | |
Set<J.MethodDeclaration> methodDeclarationsToDelete = executionContext.getMessage(GETTER_METHODS_TO_DELETE_KEY, Set.of()); | |
if (methodDeclarationsToDelete.contains(method)) { | |
return null; | |
} | |
return method; | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment