Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.openrewrite.java;


import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Preconditions;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.java.search.UsesJavaVersion;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.Statement;

import java.util.List;
@EqualsAndHashCode(callSuper = false)
@Value
public class RelocateSuperCall extends Recipe {

@Override
public String getDisplayName() {
return "Move `super()` after conditionals (Java 25+)";
}

@Override
public String getDescription() {
return "Relocates `super()` calls to occur after conditionals inside constructors, enabled by JEP 513 in Java 25+.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(
new UsesJavaVersion<>(25),
new RelocateSuperCallVisitor());
}

private static class RelocateSuperCallVisitor extends JavaIsoVisitor<ExecutionContext> {

@Override
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext ctx) {
if (!method.isConstructor() || method.getBody() == null) {
return method;
}

List<Statement> statements = method.getBody().getStatements();
if (statements.size() < 2) {
return method;
}

Statement first = statements.get(0);
if (!(first instanceof J.MethodInvocation)) {
return method;
}
J.MethodInvocation methodInvocation = (J.MethodInvocation) first;
if (!"super".equals(methodInvocation.getSimpleName())) {
return method;
}

// Move super() to the end
List<Statement> updated = new java.util.ArrayList<>(statements);
updated.remove(0);
updated.add(methodInvocation);

return method.withBody(method.getBody().withStatements(updated));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.openrewrite.java;

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

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

class RelocateSuperCallTest implements RewriteTest {

@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new RelocateSuperCall())
.allSources(src -> src.markers(javaVersion(25)));

}
@Test
void moveSuperAfterIf() {
rewriteRun(
java(
"""
class A {
public A(String bar) {
super();
if(bar.equals("test"))
throw new RuntimeException();
}
}
""",
"""
class A {
public A(String bar) {
if(bar.equals("test"))
throw new RuntimeException();
super();
}
}
"""
)
);
}

@Test
void moveSuperAfterIfStatement() {
rewriteRun(
java(
// language=java
"""
class Person {
final int age;
public Person(int age) {
if (age < 0) {
throw new IllegalArgumentException("Invalid age");
}
this.age = age;
}
}

class Employee extends Person {
public Employee(int age) {
super(age);
if (age < 18 || age > 67) {
throw new IllegalArgumentException("Invalid employee age");
}
}
}
""",
// Expected output
"""
class Person {
final int age;
public Person(int age) {
if (age < 0) {
throw new IllegalArgumentException("Invalid age");
}
this.age = age;
}
}

class Employee extends Person {
public Employee(int age) {
if (age < 18 || age > 67) {
throw new IllegalArgumentException("Invalid employee age");
}
super(age);
}
}
"""
)
);
}

@Test
void moveSuperAfterIf_withJdkBelow25Version() {
rewriteRun(
spec -> spec.recipe(new RelocateSuperCall())
.allSources(src -> src.markers(javaVersion(8))),
java(
"""
class A {
public A(String bar) {
super();
if(bar.equals("test"))
throw new RuntimeException();
}
}
""",
spec -> spec.markers(javaVersion(8))
)
);
}
}