JavaRefactor is used in our paper Evaluating the Generalizability of LLMs in Automated Program Repair @ICSE2025-NIER! If you think this repo is helpful, pls cite us😜!
JavaRefactor is a tool that can refactor java code while keeping original semantic.
- Rename Method
- Rename Variable
- Exchange Loop
- Insert LogStatement
- Insert UnusedStatement
- Negate Condition
- Reorder Condition
- SwitchToIf
This project is build by maven and has been tested on Java11. You can import it directly into your IDE (IDEA, Eclipse...), or directly use the Jar file like:
java -jar JavaRefactor.jar path/to/the/target/javafile.java path/to/the/transformed/result.java
As shown, JavaRefactor accept two parameters: the first one is the path of the file need to be transformed, the second one is the path of transformed result.
Note
The input file should be either a class which contains a function or just one function, here is an example. You can set the behavior of JavaRefactor by modifying this file.
.
├── d4j-info: JavaRefactor test on java codes from Defects4J.
├── out: The jar file.
├── src:
│ ├── main
│ │ ├── java
│ │ │ ├── transform: Serval transform visitors, the main logic of JavaRefactor
│ │ │ └── utils: Utilities functions.
│ │ └── resources: Setting files.
│ └── test
│ ├── java
│ │ └── transform: Junit testing methods on each visitor.
│ └── resources: Testcases extracted from Defects4j.
Caution
The SwitchToIf
module is complete, it will cause two types of bugs:
- When encountered with Enumerate object in switchCase, JavaRefactor may trigger a
can not find symbol ...
error. - Due to JavaRefactor change switchStatement to a bunch of IfStatement, compiler may not aware the equality of these, and report
uninitialized object
ormissing returnStatement
errors. The detailed explanations are below:
- When encountered with enum in switch cases, Java will inference the enum classes automatically, like this example from Java tutorial:
public class EnumTest {
Day day;
public EnumTest(Day day) {
this.day = day;
}
public void tellItLikeItIs() {
switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
case SATURDAY:
case SUNDAY:
System.out.println("Weekends are best.");
break;
default:
System.out.println("Midweek days are so-so.");
break;
}
}
}
The transformed version is like this:
...
if (day == MONDAY)
...
else if (day == FRIDAY)
....
....
We can directly find the transformed version can not pass the compiler. This project use a tricky way to solve this problem, it skip cases whose expression is all-uppercase.
- Uninitialized object or Missing ReturnStatement error
...
OneClass example;
switch (expr):
case x:
example = ...;
return null;
case y:
example = ...;
return example;
default:
example = ...;
return xxx;
...
the transformed version of this will be:
...
OneClass example;
if (condition1){
example = ...;
return null;
}
if (condition2){
example = ...;
return example;
}
if (condition3){
example = ...;
return xxx;
}
...
The compiler will report error after analysis even the semantic of this two versions of codes are identical. But these two kinds of codes are rare: only 4 bugs out of 438 defects4j bugs suffer from this.
Fell free to raise issues and submit pull requests! I will give you a quick response! :)
Thanks to the Defects4j project for providing real world java codes.