├── .gitignore ├── README.md ├── build.xml ├── pom.xml ├── run.sh └── src └── main └── java ├── BooleanExchange.java ├── Common.java ├── LogStatement.java ├── LoopExchange.java ├── Main.java ├── PermuteStatement.java ├── ReorderCondition.java ├── SwitchToIf.java ├── TryCatch.java ├── UnusedStatement.java └── VariableRenaming.java /.gitignore: -------------------------------------------------------------------------------- 1 | # OS file 2 | .DS_Store 3 | 4 | # Generated files 5 | /target/ 6 | .idea/ 7 | *.iml 8 | 9 | # Compiled class file 10 | *.class 11 | 12 | # Log file 13 | *.log 14 | 15 | # BlueJ files 16 | *.ctxt 17 | 18 | # Mobile Tools for Java (J2ME) 19 | .mtj.tmp/ 20 | 21 | # Package Files # 22 | *.jar 23 | *.war 24 | *.nar 25 | *.ear 26 | *.zip 27 | *.tar.gz 28 | *.rar 29 | 30 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 31 | hs_err_pid* 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaTransformer 2 | A tool to apply program transformations on Java **(\*.java)** methods for generating semantic-preserving transformed programs. 3 | - - - 4 | 5 | # Used Version(s): 6 | - openjdk 1.8.0_222 7 | - javaparser 3.24.4 8 | 9 | # JavaTransformer.jar: 10 | 11 | - Create Jar file with Maven: 12 | ``` 13 | $ mvn clean compile assembly:single 14 | # Output: target/jar/JavaTransformer.jar 15 | ``` 16 | 17 | - Create Jar file with Ant: 18 | ``` 19 | $ mvn dependency:copy-dependencies 20 | $ ant jar 21 | # Output: build/jar/JavaTransformer.jar 22 | ``` 23 | 24 | - Given input and output path, execute jar: 25 | ``` 26 | # input_path = Input directory to the original programs. 27 | # output_path = Output directory to the transformed programs. 28 | $ java -jar JavaTransformer.jar "input_path" "output_path" 29 | ``` 30 | Note: 31 | > The scope of transformation is at the method level, so each **(\*.java)** file should contain only a single method. 32 | > To modify the scope, first check [getParseUnit](https://github.com/mdrafiqulrabin/JavaTransformer/blob/31bab80927b9b86de0650cc1c0f659edae89ebdc/src/main/java/Common.java#L48) for CompilationUnit. 33 | > Or, convert java files into single method-only files using [JavaMethodExtractor](https://github.com/mdrafiqulrabin/tnpa-generalizability/tree/master/JavaMethodExtractor) before applying transformation. 34 | 35 | ## Transformations: 36 | 37 | - BooleanExchange 38 | - LogStatement 39 | - LoopExchange 40 | - PermuteStatement 41 | - ReorderCondition 42 | - SwitchToIf 43 | - TryCatch 44 | - UnusedStatement 45 | - VariableRenaming 46 | 47 | # References: 48 | 49 | - Testing Neural Program Analyzers [[Paper](https://arxiv.org/abs/1908.10711)] [[GitHub](https://github.com/mdrafiqulrabin/tnpa-framework)] 50 | - On the generalizability of Neural Program Models with respect to semantic-preserving program transformations [[Paper](https://arxiv.org/abs/2008.01566)] [[GitHub](https://github.com/mdrafiqulrabin/tnpa-generalizability)] 51 | - JavaParser: https://github.com/javaparser/javaparser 52 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.uhserg.tnpa.javatransformer 8 | JavaTransformer 9 | 1.0 10 | 11 | 12 | 13 | 14 | maven-assembly-plugin 15 | 16 | jar/JavaTransformer 17 | false 18 | 19 | 20 | Main 21 | 22 | 23 | 24 | jar-with-dependencies 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-compiler-plugin 31 | 32 | 1.8 33 | 1.8 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | com.github.javaparser 42 | javaparser-core 43 | 3.24.4 44 | 45 | 46 | junit 47 | junit 48 | 4.13.2 49 | 50 | 51 | commons-io 52 | commons-io 53 | 2.11.0 54 | 55 | 56 | org.apache.commons 57 | commons-lang3 58 | 3.12.0 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | clear 3 | echo "Creating JavaTransformer.jar" 4 | mvn clean compile assembly:single 5 | java -jar target/jar/JavaTransformer.jar > target/default.log 6 | echo "Saved JAR into target/jar/" 7 | -------------------------------------------------------------------------------- /src/main/java/BooleanExchange.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.StaticJavaParser; 2 | import com.github.javaparser.ast.CompilationUnit; 3 | import com.github.javaparser.ast.Node; 4 | import com.github.javaparser.ast.body.VariableDeclarator; 5 | import com.github.javaparser.ast.expr.*; 6 | import com.github.javaparser.ast.stmt.Statement; 7 | import com.github.javaparser.ast.type.PrimitiveType; 8 | import com.github.javaparser.ast.visitor.TreeVisitor; 9 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 10 | 11 | import java.io.File; 12 | import java.util.ArrayList; 13 | import java.util.Objects; 14 | 15 | public class BooleanExchange extends VoidVisitorAdapter { 16 | private final Common mCommon; 17 | private File mJavaFile = null; 18 | private String mSavePath = ""; 19 | private final ArrayList mBooleanNodes = new ArrayList<>(); 20 | 21 | BooleanExchange() { 22 | //System.out.println("\n[ BooleanExchange ]\n"); 23 | mCommon = new Common(); 24 | } 25 | 26 | public void inspectSourceCode(File javaFile) { 27 | this.mJavaFile = javaFile; 28 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 29 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 30 | if (root != null) { 31 | this.visit(root.clone(), null); 32 | } 33 | } 34 | 35 | @Override 36 | public void visit(CompilationUnit com, Object obj) { 37 | locateBooleanVariables(com); 38 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mBooleanNodes); 39 | super.visit(com, obj); 40 | } 41 | 42 | private void locateBooleanVariables(CompilationUnit com) { 43 | new TreeVisitor() { 44 | @Override 45 | public void process(Node node) { 46 | Node booleanNode = getBooleanVariable(node); 47 | if (booleanNode != null) { 48 | mBooleanNodes.add(booleanNode); 49 | } 50 | } 51 | }.visitPreOrder(com); 52 | //System.out.println("BooleanVariable : " + mBooleanList); 53 | } 54 | 55 | public CompilationUnit applyTransformation(CompilationUnit com, Node bolNode) { 56 | new TreeVisitor() { 57 | @Override 58 | public void process(Node node) { 59 | if (node != null && node.toString().equals(bolNode.toString())) { 60 | if (node instanceof NameExpr) { 61 | if (node.getParentNode().orElse(null) instanceof UnaryExpr) { 62 | // i.e. !x -> x 63 | node.getParentNode().orElse(null).replace(node); 64 | } else if (node.getParentNode().orElse(null) instanceof BinaryExpr 65 | || node.getParentNode().orElse(null) instanceof Statement 66 | || node.getParentNode().orElse(null) instanceof VariableDeclarator 67 | || node.getParentNode().orElse(null) instanceof MethodCallExpr) { 68 | // i.e. x == true -> !x == true; call(x) -> call(!x) 69 | ((NameExpr) node).setName(getNotExpStr(node)); 70 | } else if (node.getParentNode().orElse(null) instanceof AssignExpr) { 71 | AssignExpr parNode = (AssignExpr) node.getParentNode().orElse(null); 72 | if (parNode.getValue().toString().equals(bolNode.toString())) { 73 | // i.e. y = x; -> y = !x; 74 | parNode.setValue(StaticJavaParser.parseExpression(getNotExpStr(parNode.getValue()))); 75 | } else if (parNode.getTarget().toString().equals(bolNode.toString())) { 76 | // i.e. x = r() && x; -> x = !(r() && !x); 77 | new TreeVisitor() { 78 | @Override 79 | public void process(Node node) { 80 | if (node != null && node.toString().equals(bolNode.toString())) { 81 | if (node.getParentNode().orElse(null) instanceof UnaryExpr) { 82 | node.getParentNode().orElse(null).replace(node); 83 | } else if (node instanceof NameExpr) { 84 | ((NameExpr) node).setName(getNotExpStr(node)); 85 | } 86 | } 87 | } 88 | }.visitPreOrder(parNode.getValue()); 89 | parNode.setValue(StaticJavaParser.parseExpression(getNotExpStr(parNode.getValue()))); 90 | } 91 | } 92 | } else if (node instanceof SimpleName) { 93 | if (node.getParentNode().isPresent() && node.getParentNode().orElse(null) instanceof VariableDeclarator) { 94 | VariableDeclarator parNode = (VariableDeclarator) node.getParentNode().orElse(null); 95 | if (parNode.getName().asString().equals(bolNode.toString()) && parNode.getInitializer().isPresent()) { 96 | //i.e. boolean x = true; -> boolean x = false; 97 | Expression expVal = parNode.getInitializer().get(); 98 | expVal.replace(StaticJavaParser.parseExpression(getNotExpStr(expVal))); 99 | } 100 | } 101 | } 102 | } 103 | } 104 | }.visitPreOrder(com); 105 | return com; 106 | } 107 | 108 | private String getNotExpStr(Node node) { 109 | if (node instanceof BooleanLiteralExpr) { 110 | boolean val = !((BooleanLiteralExpr) node).getValue(); 111 | return String.valueOf(val); 112 | } else { 113 | String expStr = "!"; 114 | if (node.toString().length() > 1) { 115 | expStr += "(" + node + ")"; 116 | } else { 117 | expStr += node; 118 | } 119 | return expStr; 120 | } 121 | } 122 | 123 | private Node getBooleanVariable(Node node) { 124 | if (node.toString().equalsIgnoreCase(PrimitiveType.booleanType().asString()) 125 | && node.getParentNode().orElse(null) instanceof VariableDeclarator) { 126 | VariableDeclarator parentNode = (VariableDeclarator) node.getParentNode().get(); 127 | if (parentNode.getInitializer().isPresent()) { 128 | for (SimpleName sn : Objects.requireNonNull(node.getParentNode() 129 | .orElse(null)).findAll(SimpleName.class)) { 130 | if (!sn.toString().equalsIgnoreCase(PrimitiveType.booleanType().asString())) { 131 | return sn; 132 | } 133 | } 134 | } 135 | } 136 | return null; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/Common.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.StaticJavaParser; 2 | import com.github.javaparser.ast.CompilationUnit; 3 | import com.github.javaparser.ast.Node; 4 | import com.github.javaparser.ast.body.MethodDeclaration; 5 | import com.github.javaparser.ast.stmt.*; 6 | 7 | import java.io.*; 8 | import java.nio.file.Files; 9 | import java.util.ArrayList; 10 | 11 | public final class Common { 12 | static String mRootInputPath = ""; 13 | static String mRootOutputPath = ""; 14 | 15 | public CompilationUnit getParseUnit(File javaFile) { 16 | CompilationUnit root = null; 17 | try { 18 | StaticJavaParser.getConfiguration().setAttributeComments(false); 19 | String txtCode = new String(Files.readAllBytes(javaFile.toPath())); 20 | if (!txtCode.startsWith("class")) txtCode = "class T { \n" + txtCode + "\n}"; 21 | root = StaticJavaParser.parse(txtCode); 22 | } catch (Exception ignore) {} 23 | return root; 24 | } 25 | 26 | public void applyToPlace(Object obj, String savePath, 27 | CompilationUnit com, File javaFile, ArrayList nodeList) { 28 | for (int i = 0; i < nodeList.size(); i++) { 29 | Node node = nodeList.get(i); 30 | CompilationUnit newCom = applyByObj(obj, com.clone(), javaFile, node.clone()); 31 | if (newCom != null && this.checkTransformation(com, newCom)) { 32 | this.saveTransformation(savePath, newCom, javaFile, String.valueOf(i + 1)); 33 | } 34 | } 35 | } 36 | 37 | private CompilationUnit applyByObj(Object obj, CompilationUnit com, File javaFile, Node node) { 38 | CompilationUnit newCom = null; 39 | try { 40 | if (obj instanceof VariableRenaming) { 41 | newCom = ((VariableRenaming) obj).applyTransformation(com, node); 42 | } else if (obj instanceof BooleanExchange) { 43 | newCom = ((BooleanExchange) obj).applyTransformation(com, node); 44 | } else if (obj instanceof LoopExchange) { 45 | newCom = ((LoopExchange) obj).applyTransformation(com, node); 46 | } else if (obj instanceof SwitchToIf) { 47 | newCom = ((SwitchToIf) obj).applyTransformation(com, node); 48 | } else if (obj instanceof ReorderCondition) { 49 | newCom = ((ReorderCondition) obj).applyTransformation(com, node); 50 | } else if (obj instanceof PermuteStatement) { 51 | newCom = ((PermuteStatement) obj).applyTransformation(com); 52 | } else if (obj instanceof UnusedStatement) { 53 | newCom = ((UnusedStatement) obj).applyTransformation(com); 54 | } else if (obj instanceof LogStatement) { 55 | newCom = ((LogStatement) obj).applyTransformation(com); 56 | } else if (obj instanceof TryCatch) { 57 | newCom = ((TryCatch) obj).applyTransformation(com); 58 | } 59 | } catch (Exception ex) { 60 | System.out.println("\n" + "Exception: " + javaFile.getPath()); 61 | ex.printStackTrace(); 62 | } 63 | return newCom; 64 | } 65 | 66 | private Boolean checkTransformation(CompilationUnit bRoot, CompilationUnit aRoot) { 67 | MethodDeclaration mdBefore = (MethodDeclaration) (bRoot.getChildNodes().get(0)).getChildNodes().get(1); 68 | String mdBeforeStr = mdBefore.toString().replaceAll("\\s+", ""); 69 | MethodDeclaration mdAfter = (MethodDeclaration) (aRoot.getChildNodes().get(0)).getChildNodes().get(1); 70 | String mdAfterStr = mdAfter.toString().replaceAll("\\s+", ""); 71 | return mdBeforeStr.compareTo(mdAfterStr) != 0; 72 | } 73 | 74 | public void saveTransformation(String savePath, CompilationUnit aRoot, File javaFile, String place) { 75 | String output_dir = savePath + javaFile.getPath().replaceFirst(Common.mRootInputPath, ""); 76 | output_dir = output_dir.substring(0, output_dir.lastIndexOf(".java")) + "_" + place + ".java"; 77 | MethodDeclaration mdAfter = (MethodDeclaration) (aRoot.getChildNodes().get(0)).getChildNodes().get(1); 78 | this.writeSourceCode(mdAfter, output_dir); 79 | } 80 | 81 | private void writeSourceCode(MethodDeclaration md, String codePath) { 82 | File targetFile = new File(codePath).getParentFile(); 83 | if (targetFile.exists() || targetFile.mkdirs()) { 84 | try (PrintStream ps = new PrintStream(codePath)) { 85 | String tfSourceCode = md.toString(); 86 | ps.println(tfSourceCode); 87 | } catch (FileNotFoundException ex) { 88 | ex.printStackTrace(); 89 | } 90 | } 91 | } 92 | 93 | public boolean isNotPermeableStatement(Node node) { 94 | return (node instanceof EmptyStmt 95 | || node instanceof LabeledStmt 96 | || node instanceof BreakStmt 97 | || node instanceof ContinueStmt 98 | || node instanceof ReturnStmt); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/LogStatement.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.StaticJavaParser; 2 | import com.github.javaparser.ast.CompilationUnit; 3 | import com.github.javaparser.ast.Node; 4 | import com.github.javaparser.ast.body.MethodDeclaration; 5 | import com.github.javaparser.ast.stmt.BlockStmt; 6 | import com.github.javaparser.ast.stmt.EmptyStmt; 7 | import com.github.javaparser.ast.stmt.Statement; 8 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 9 | 10 | import java.io.File; 11 | import java.util.ArrayList; 12 | import java.util.Random; 13 | 14 | public class LogStatement extends VoidVisitorAdapter { 15 | private final Common mCommon; 16 | private File mJavaFile = null; 17 | private String mSavePath = ""; 18 | private final ArrayList mDummyNodes = new ArrayList<>(); 19 | 20 | LogStatement() { 21 | //System.out.println("\n[ LogStatement ]\n"); 22 | mCommon = new Common(); 23 | } 24 | 25 | public void inspectSourceCode(File javaFile) { 26 | this.mJavaFile = javaFile; 27 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 28 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 29 | if (root != null) { 30 | this.visit(root.clone(), null); 31 | } 32 | } 33 | 34 | @Override 35 | public void visit(CompilationUnit com, Object obj) { 36 | mDummyNodes.add(new EmptyStmt()); 37 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mDummyNodes); 38 | super.visit(com, obj); 39 | } 40 | 41 | public CompilationUnit applyTransformation(CompilationUnit com) { 42 | if (com.findFirst(MethodDeclaration.class).isPresent() && 43 | com.findFirst(MethodDeclaration.class).flatMap(MethodDeclaration::getBody).isPresent()) { 44 | BlockStmt blockStmt = new BlockStmt(); 45 | for (Statement statement : com.findFirst(MethodDeclaration.class) 46 | .flatMap(MethodDeclaration::getBody).get().getStatements()) { 47 | blockStmt.addStatement(statement); 48 | } 49 | int min = 0, max = blockStmt.getStatements().size() - 1; 50 | int place = new Random().nextInt(max - min + 1) + min; 51 | blockStmt.addStatement(place, getLogStatement()); 52 | MethodDeclaration md = com.findFirst(MethodDeclaration.class).get(); 53 | md.setBody(blockStmt); 54 | } 55 | return com; 56 | } 57 | 58 | private Statement getLogStatement() { 59 | String logStr = "System.out.println(\"log\");"; 60 | return StaticJavaParser.parseStatement(logStr); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/LoopExchange.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.ast.CompilationUnit; 2 | import com.github.javaparser.ast.Node; 3 | import com.github.javaparser.ast.expr.BooleanLiteralExpr; 4 | import com.github.javaparser.ast.expr.Expression; 5 | import com.github.javaparser.ast.stmt.BlockStmt; 6 | import com.github.javaparser.ast.stmt.ForStmt; 7 | import com.github.javaparser.ast.stmt.Statement; 8 | import com.github.javaparser.ast.stmt.WhileStmt; 9 | import com.github.javaparser.ast.visitor.TreeVisitor; 10 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 11 | 12 | import java.io.File; 13 | import java.util.ArrayList; 14 | 15 | public class LoopExchange extends VoidVisitorAdapter { 16 | private final Common mCommon; 17 | private File mJavaFile = null; 18 | private String mSavePath = ""; 19 | private final ArrayList mLoopNodes = new ArrayList<>(); 20 | 21 | LoopExchange() { 22 | //System.out.println("\n[ LoopExchange ]\n"); 23 | mCommon = new Common(); 24 | } 25 | 26 | public void inspectSourceCode(File javaFile) { 27 | this.mJavaFile = javaFile; 28 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 29 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 30 | if (root != null) { 31 | this.visit(root.clone(), null); 32 | } 33 | } 34 | 35 | @Override 36 | public void visit(CompilationUnit com, Object obj) { 37 | locateLoops(com); 38 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mLoopNodes); 39 | super.visit(com, obj); 40 | } 41 | 42 | private void locateLoops(CompilationUnit com) { 43 | new TreeVisitor() { 44 | @Override 45 | public void process(Node node) { 46 | if (node instanceof WhileStmt || node instanceof ForStmt) { 47 | mLoopNodes.add(node); 48 | } 49 | } 50 | }.visitPreOrder(com); 51 | //System.out.println("LoopNodes : " + mLoopNodes.size()); 52 | } 53 | 54 | public CompilationUnit applyTransformation(CompilationUnit com, Node loopNode) { 55 | new TreeVisitor() { 56 | @Override 57 | public void process(Node node) { 58 | if (node.equals(loopNode)) { 59 | if (loopNode instanceof WhileStmt) { 60 | ForStmt nodeForStmt = new ForStmt(); 61 | nodeForStmt.setCompare(((WhileStmt) node).getCondition()); 62 | nodeForStmt.setBody(((WhileStmt) node).getBody()); 63 | node.replace(nodeForStmt); 64 | } else if (loopNode instanceof ForStmt) { 65 | if (((ForStmt) node).getInitialization().size() != 0) { 66 | BlockStmt outerBlockStmt = new BlockStmt(); 67 | for (Expression exp : ((ForStmt) node).getInitialization()) { 68 | outerBlockStmt.addStatement(exp); 69 | } 70 | WhileStmt nodeWhileStmt = getWhileStmt(node); 71 | outerBlockStmt.addStatement(nodeWhileStmt); 72 | node.replace(outerBlockStmt); 73 | } else { 74 | node.replace(getWhileStmt(node)); 75 | } 76 | } 77 | } 78 | } 79 | }.visitPreOrder(com); 80 | return com; 81 | } 82 | 83 | private WhileStmt getWhileStmt(Node loopNode) { 84 | WhileStmt nodeWhileStmt = new WhileStmt(); 85 | nodeWhileStmt.setCondition(((ForStmt) loopNode).getCompare().orElse(new BooleanLiteralExpr(true))); 86 | if (((ForStmt) loopNode).getBody().getChildNodes().size() == 0 && ((ForStmt) loopNode).getUpdate().size() == 0) { 87 | //i.e. for(?;?;); or for(?;?;){} 88 | nodeWhileStmt.setBody(((ForStmt) loopNode).getBody()); 89 | } else { 90 | BlockStmt innerBlockStmt; 91 | if (((ForStmt) loopNode).getBody().getChildNodes().size() != 0) { 92 | //i.e. for(?;?;?){...} 93 | Statement forStmtBody = ((ForStmt) loopNode).getBody(); 94 | if (forStmtBody instanceof BlockStmt) { 95 | innerBlockStmt = (BlockStmt) forStmtBody; 96 | } else { 97 | innerBlockStmt = new BlockStmt(); 98 | innerBlockStmt.addStatement(forStmtBody); 99 | } 100 | } else { 101 | //i.e. for(?;?;...); or for(?;?;...){} 102 | innerBlockStmt = new BlockStmt(); 103 | } 104 | for (Expression exp : ((ForStmt) loopNode).getUpdate()) { 105 | innerBlockStmt.addStatement(exp); 106 | } 107 | nodeWhileStmt.setBody(innerBlockStmt); 108 | } 109 | return nodeWhileStmt; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import org.apache.commons.io.FileUtils; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | public class Main { 7 | public static void main(String[] args) { 8 | /* arg[0]: root path for input folder, ie, ~/data/methods/ 9 | * arg[1]: root path for output folder, ie, ~/data/transforms/ 10 | * 11 | * extracted single method of project should be in 'methods' folder 12 | * separate folder for each refactoring will be created in 'transforms' folder 13 | */ 14 | 15 | if (args.length == 2) { 16 | String inputPath = args[0]; 17 | if (!inputPath.endsWith("/")) { 18 | inputPath += "/"; 19 | } 20 | Common.mRootInputPath = inputPath; 21 | 22 | String outputPath = args[1]; 23 | if (!outputPath.endsWith("/")) { 24 | outputPath += "/"; 25 | } 26 | Common.mRootOutputPath = outputPath; 27 | 28 | inspectDataset(); 29 | } else { 30 | String msg = "Error (args):" + 31 | "\n\targ[0]: root path for input folder" + 32 | "\n\targ[1]: root path for output folder"; 33 | System.out.println(msg); 34 | } 35 | } 36 | 37 | private static void inspectDataset() { 38 | String input_dir = Common.mRootInputPath; 39 | ArrayList javaFiles = new ArrayList<>( 40 | FileUtils.listFiles( 41 | new File(input_dir), 42 | new String[]{"java"}, 43 | true) 44 | ); 45 | 46 | javaFiles.parallelStream().forEach((javaFile) -> { 47 | try { 48 | new VariableRenaming().inspectSourceCode(javaFile); 49 | new BooleanExchange().inspectSourceCode(javaFile); 50 | new LoopExchange().inspectSourceCode(javaFile); 51 | new SwitchToIf().inspectSourceCode(javaFile); 52 | new ReorderCondition().inspectSourceCode(javaFile); 53 | new PermuteStatement().inspectSourceCode(javaFile); 54 | new UnusedStatement().inspectSourceCode(javaFile); 55 | new LogStatement().inspectSourceCode(javaFile); 56 | new TryCatch().inspectSourceCode(javaFile); 57 | } catch (Exception ex) { 58 | System.out.println("Exception: " + javaFile); 59 | ex.printStackTrace(); 60 | } 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/PermuteStatement.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.ast.CompilationUnit; 2 | import com.github.javaparser.ast.Node; 3 | import com.github.javaparser.ast.expr.MethodCallExpr; 4 | import com.github.javaparser.ast.expr.SimpleName; 5 | import com.github.javaparser.ast.stmt.EmptyStmt; 6 | import com.github.javaparser.ast.stmt.ExpressionStmt; 7 | import com.github.javaparser.ast.stmt.Statement; 8 | import com.github.javaparser.ast.visitor.TreeVisitor; 9 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 10 | 11 | import java.io.File; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | public class PermuteStatement extends VoidVisitorAdapter { 17 | private final Common mCommon; 18 | private File mJavaFile = null; 19 | private String mSavePath = ""; 20 | private ArrayList> mBasicBlockNodes = new ArrayList<>(); 21 | private final ArrayList mDummyNodes = new ArrayList<>(); 22 | 23 | PermuteStatement() { 24 | //System.out.println("\n[ PermuteStatement ]\n"); 25 | mCommon = new Common(); 26 | } 27 | 28 | public void inspectSourceCode(File javaFile) { 29 | this.mJavaFile = javaFile; 30 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 31 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 32 | if (root != null) { 33 | this.visit(root.clone(), null); 34 | } 35 | } 36 | 37 | @Override 38 | public void visit(CompilationUnit com, Object obj) { 39 | mBasicBlockNodes = locateBasicBlockStatements(com); 40 | mDummyNodes.add(new EmptyStmt()); 41 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mDummyNodes); 42 | super.visit(com, obj); 43 | } 44 | 45 | private ArrayList> locateBasicBlockStatements(CompilationUnit com) { 46 | ArrayList innerStatementNodes = new ArrayList<>(); 47 | ArrayList> basicBlockNodes = new ArrayList<>(); 48 | new TreeVisitor() { 49 | @Override 50 | public void process(Node node) { 51 | if (node instanceof Statement) { 52 | if (node instanceof ExpressionStmt 53 | && node.findAll(MethodCallExpr.class).size() == 0 54 | && !mCommon.isNotPermeableStatement(node)) { 55 | innerStatementNodes.add(node); 56 | } else { 57 | if (innerStatementNodes.size() > 1) { 58 | basicBlockNodes.add(new ArrayList<>(innerStatementNodes)); 59 | } 60 | innerStatementNodes.clear(); 61 | } 62 | } 63 | } 64 | }.visitBreadthFirst(com); 65 | return basicBlockNodes; 66 | } 67 | 68 | public CompilationUnit applyTransformation(CompilationUnit com) { 69 | int cnt = 0; 70 | for (int k = 0; k < mBasicBlockNodes.size(); k++) { 71 | ArrayList basicBlockNodes = mBasicBlockNodes.get(k); 72 | for (int i = 0; i < basicBlockNodes.size(); i++) { 73 | for (int j = i + 1; j < basicBlockNodes.size(); j++) { 74 | Statement stmt_i = (Statement) basicBlockNodes.get(i); 75 | Statement stmt_j = (Statement) basicBlockNodes.get(j); 76 | if (stmt_i.getParentNode().equals(stmt_j.getParentNode())) { 77 | List iIdentifiers = stmt_i.findAll(SimpleName.class); 78 | List jIdentifiers = stmt_j.findAll(SimpleName.class); 79 | List ijIdentifiers = iIdentifiers.stream() 80 | .filter(jIdentifiers::contains).collect(Collectors.toList()); 81 | if (ijIdentifiers.size() == 0) { //dependency check between i & j statement 82 | List bIdentifiers = new ArrayList<>(); 83 | for (int b = i + 1; b < j; b++) { 84 | Statement stmt_b = (Statement) basicBlockNodes.get(b); 85 | bIdentifiers.addAll(stmt_b.findAll(SimpleName.class)); 86 | } 87 | List ibIdentifiers = iIdentifiers.stream() 88 | .filter(bIdentifiers::contains).collect(Collectors.toList()); 89 | if (ibIdentifiers.size() == 0) { //dependency check among i & internal statements 90 | List jbIdentifiers = jIdentifiers.stream() 91 | .filter(bIdentifiers::contains).collect(Collectors.toList()); 92 | if (jbIdentifiers.size() == 0) { //dependency check among j & internal statements 93 | swapStatementNodes(com, k, i, j, ++cnt); 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | return null; 102 | } 103 | 104 | private void swapStatementNodes(CompilationUnit com, int k, int i, int j, int cnt) { 105 | CompilationUnit newCom = com.clone(); 106 | ArrayList> statementNodes = locateBasicBlockStatements(newCom); 107 | Statement stmt_i = (Statement) statementNodes.get(k).get(i); 108 | Statement stmt_j = (Statement) statementNodes.get(k).get(j); 109 | stmt_i.replace(stmt_j.clone()); 110 | stmt_j.replace(stmt_i.clone()); 111 | mCommon.saveTransformation(mSavePath, newCom, mJavaFile, String.valueOf(cnt)); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/ReorderCondition.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.ast.CompilationUnit; 2 | import com.github.javaparser.ast.Node; 3 | import com.github.javaparser.ast.expr.BinaryExpr; 4 | import com.github.javaparser.ast.visitor.TreeVisitor; 5 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 6 | 7 | import java.io.File; 8 | import java.util.ArrayList; 9 | 10 | public class ReorderCondition extends VoidVisitorAdapter { 11 | private final Common mCommon; 12 | private File mJavaFile = null; 13 | private String mSavePath = ""; 14 | private final ArrayList mOperatorNodes = new ArrayList<>(); 15 | 16 | ReorderCondition() { 17 | //System.out.println("\n[ ReorderCondition ]\n"); 18 | mCommon = new Common(); 19 | } 20 | 21 | public void inspectSourceCode(File javaFile) { 22 | this.mJavaFile = javaFile; 23 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 24 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 25 | if (root != null) { 26 | this.visit(root.clone(), null); 27 | } 28 | } 29 | 30 | @Override 31 | public void visit(CompilationUnit com, Object obj) { 32 | locateOperators(com); 33 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mOperatorNodes); 34 | super.visit(com, obj); 35 | } 36 | 37 | private void locateOperators(CompilationUnit com) { 38 | new TreeVisitor() { 39 | @Override 40 | public void process(Node node) { 41 | if (node instanceof BinaryExpr && isAugmentationApplicable(((BinaryExpr) node).getOperator())) { 42 | mOperatorNodes.add(node); 43 | } 44 | } 45 | }.visitPreOrder(com); 46 | //System.out.println("OperatorNodes : " + mOperatorNodes.size()); 47 | } 48 | 49 | public CompilationUnit applyTransformation(CompilationUnit com, Node opNode) { 50 | new TreeVisitor() { 51 | @Override 52 | public void process(Node node) { 53 | if (node.equals(opNode)) { 54 | BinaryExpr replNode = (BinaryExpr) opNode.clone(); 55 | switch (((BinaryExpr) node).getOperator()) { 56 | case LESS: 57 | replNode.setOperator(BinaryExpr.Operator.GREATER); 58 | replNode.setLeft(((BinaryExpr) node).getRight()); 59 | replNode.setRight(((BinaryExpr) node).getLeft()); 60 | break; 61 | case LESS_EQUALS: 62 | replNode.setOperator(BinaryExpr.Operator.GREATER_EQUALS); 63 | replNode.setLeft(((BinaryExpr) node).getRight()); 64 | replNode.setRight(((BinaryExpr) node).getLeft()); 65 | break; 66 | case GREATER: 67 | replNode.setOperator(BinaryExpr.Operator.LESS); 68 | replNode.setLeft(((BinaryExpr) node).getRight()); 69 | replNode.setRight(((BinaryExpr) node).getLeft()); 70 | break; 71 | case GREATER_EQUALS: 72 | replNode.setOperator(BinaryExpr.Operator.LESS_EQUALS); 73 | replNode.setLeft(((BinaryExpr) node).getRight()); 74 | replNode.setRight(((BinaryExpr) node).getLeft()); 75 | break; 76 | case EQUALS: 77 | case NOT_EQUALS: 78 | case OR: 79 | case AND: 80 | case PLUS: 81 | case MULTIPLY: 82 | replNode.setLeft(((BinaryExpr) node).getRight()); 83 | replNode.setRight(((BinaryExpr) node).getLeft()); 84 | break; 85 | } 86 | node.replace(replNode); 87 | } 88 | } 89 | }.visitPreOrder(com); 90 | return com; 91 | } 92 | 93 | private boolean isAugmentationApplicable(BinaryExpr.Operator op) { 94 | switch (op) { 95 | case LESS: 96 | case LESS_EQUALS: 97 | case GREATER: 98 | case GREATER_EQUALS: 99 | case EQUALS: 100 | case NOT_EQUALS: 101 | case OR: 102 | case AND: 103 | case PLUS: 104 | case MULTIPLY: 105 | return true; 106 | } 107 | return false; 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/SwitchToIf.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.ast.CompilationUnit; 2 | import com.github.javaparser.ast.Node; 3 | import com.github.javaparser.ast.expr.BinaryExpr; 4 | import com.github.javaparser.ast.expr.Expression; 5 | import com.github.javaparser.ast.stmt.*; 6 | import com.github.javaparser.ast.visitor.TreeVisitor; 7 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 8 | 9 | import java.io.File; 10 | import java.util.ArrayList; 11 | 12 | public class SwitchToIf extends VoidVisitorAdapter { 13 | private final Common mCommon; 14 | private File mJavaFile = null; 15 | private String mSavePath = ""; 16 | private final ArrayList mSwitchNodes = new ArrayList<>(); 17 | 18 | SwitchToIf() { 19 | //System.out.println("\n[ SwitchToIf ]\n"); 20 | mCommon = new Common(); 21 | } 22 | 23 | public void inspectSourceCode(File javaFile) { 24 | this.mJavaFile = javaFile; 25 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 26 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 27 | if (root != null) { 28 | this.visit(root.clone(), null); 29 | } 30 | } 31 | 32 | @Override 33 | public void visit(CompilationUnit com, Object obj) { 34 | locateConditionals(com); 35 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mSwitchNodes); 36 | super.visit(com, obj); 37 | } 38 | 39 | private void locateConditionals(CompilationUnit com) { 40 | new TreeVisitor() { 41 | @Override 42 | public void process(Node node) { 43 | if (node instanceof SwitchStmt) { 44 | mSwitchNodes.add(node); 45 | } 46 | } 47 | }.visitPreOrder(com); 48 | //System.out.println("SwitchNodes : " + mSwitchNodes.size()); 49 | } 50 | 51 | public CompilationUnit applyTransformation(CompilationUnit com, Node switchNode) { 52 | new TreeVisitor() { 53 | @Override 54 | public void process(Node node) { 55 | if (node.equals(switchNode)) { 56 | ArrayList ifStmts = new ArrayList<>(); 57 | if (((SwitchStmt) node).getEntries().size() == 0) { 58 | // empty 59 | ifStmts.add(getIfStmt(node, null)); 60 | } else { 61 | BlockStmt defaultBlockStmt = null; 62 | for (SwitchEntry switchEntry : ((SwitchStmt) node).getEntries()) { 63 | if (switchEntry.getLabels().size() != 0) { 64 | // cases 65 | ifStmts.add(getIfStmt(node, switchEntry)); 66 | } else { 67 | if (((SwitchStmt) node).getEntries().size() == 1) { 68 | // default without cases 69 | ifStmts.add(getIfStmt(node, switchEntry)); 70 | } else { 71 | // default with cases 72 | defaultBlockStmt = getBlockStmt(switchEntry); 73 | } 74 | } 75 | } 76 | if (defaultBlockStmt != null) ifStmts.add(defaultBlockStmt); // default at end with cases 77 | for (int i = 0; i < ifStmts.size() - 1; i++) { 78 | ((IfStmt) ifStmts.get(i)).setElseStmt((Statement) ifStmts.get(i + 1)); 79 | } 80 | } 81 | node.replace((IfStmt) ifStmts.get(0)); 82 | } 83 | } 84 | }.visitPreOrder(com); 85 | return com; 86 | } 87 | 88 | private Expression getBinaryExpr(Node switchNode, SwitchEntry switchEntry) { 89 | BinaryExpr binaryExpr = new BinaryExpr(); 90 | binaryExpr.setLeft(((SwitchStmt) switchNode).getSelector()); 91 | binaryExpr.setOperator(BinaryExpr.Operator.EQUALS); 92 | if (switchEntry != null && switchEntry.getLabels().size() != 0) { 93 | binaryExpr.setRight(switchEntry.getLabels().get(0)); // case(?) 94 | } else { 95 | binaryExpr.setRight(((SwitchStmt) switchNode).getSelector()); // only default 96 | } 97 | return binaryExpr; 98 | } 99 | 100 | private BlockStmt getBlockStmt(SwitchEntry switchEntry) { 101 | BlockStmt blockStmt = new BlockStmt(); 102 | if (switchEntry != null) { 103 | switchEntry.getStatements().forEach((stmt) -> { 104 | if (!(stmt instanceof BreakStmt)) blockStmt.addStatement(stmt); 105 | }); 106 | } 107 | return blockStmt; 108 | } 109 | 110 | private IfStmt getIfStmt(Node switchNode, SwitchEntry switchEntry) { 111 | IfStmt ifStmt = new IfStmt(); 112 | ifStmt.setCondition(getBinaryExpr(switchNode, switchEntry)); 113 | ifStmt.setThenStmt(getBlockStmt(switchEntry)); 114 | return ifStmt; 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/TryCatch.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.StaticJavaParser; 2 | import com.github.javaparser.ast.CompilationUnit; 3 | import com.github.javaparser.ast.Node; 4 | import com.github.javaparser.ast.body.MethodDeclaration; 5 | import com.github.javaparser.ast.body.VariableDeclarator; 6 | import com.github.javaparser.ast.expr.MethodCallExpr; 7 | import com.github.javaparser.ast.stmt.*; 8 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 9 | 10 | import java.io.File; 11 | import java.util.ArrayList; 12 | import java.util.Random; 13 | 14 | public class TryCatch extends VoidVisitorAdapter { 15 | private final Common mCommon; 16 | private File mJavaFile = null; 17 | private String mSavePath = ""; 18 | private final ArrayList mDummyNodes = new ArrayList<>(); 19 | 20 | TryCatch() { 21 | //System.out.println("\n[ TryCatch ]\n"); 22 | mCommon = new Common(); 23 | } 24 | 25 | public void inspectSourceCode(File javaFile) { 26 | this.mJavaFile = javaFile; 27 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 28 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 29 | if (root != null) { 30 | this.visit(root.clone(), null); 31 | } 32 | } 33 | 34 | @Override 35 | public void visit(CompilationUnit com, Object obj) { 36 | mDummyNodes.add(new EmptyStmt()); 37 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mDummyNodes); 38 | super.visit(com, obj); 39 | } 40 | 41 | public CompilationUnit applyTransformation(CompilationUnit com) { 42 | if (com.findAll(TryStmt.class).size() > 0 43 | || com.findAll(MethodCallExpr.class).size() == 0) { 44 | return com; 45 | } 46 | 47 | if (com.findFirst(MethodDeclaration.class).isPresent() && 48 | com.findFirst(MethodDeclaration.class).flatMap(MethodDeclaration::getBody).isPresent()) { 49 | BlockStmt blockStmt = new BlockStmt(); 50 | BlockStmt tcNodes = new BlockStmt(); 51 | for (Statement statement : com.findFirst(MethodDeclaration.class) 52 | .flatMap(MethodDeclaration::getBody).get().getStatements()) { 53 | boolean flag = true; 54 | if (mCommon.isNotPermeableStatement(statement) 55 | || statement.findAll(MethodCallExpr.class).size() == 0) { 56 | flag = false; 57 | } else if (statement instanceof ExpressionStmt) { 58 | for (Node node : statement.getChildNodes()) { 59 | if (node.findFirst(VariableDeclarator.class).isPresent()) { 60 | flag = false; 61 | break; 62 | } 63 | } 64 | } 65 | if (flag) { 66 | tcNodes.addStatement(statement); 67 | } 68 | blockStmt.addStatement(statement); 69 | } 70 | 71 | if (tcNodes.getStatements().size() > 0) { 72 | int min = 0, max = tcNodes.getStatements().size() - 1; 73 | int place = new Random().nextInt(max - min + 1) + min; 74 | Statement tcStmt = tcNodes.getStatements().get(place); 75 | blockStmt.replace(tcStmt, getTryCatchStatement(tcStmt)); 76 | } 77 | 78 | MethodDeclaration md = com.findFirst(MethodDeclaration.class).get(); 79 | md.setBody(blockStmt); 80 | } 81 | return com; 82 | } 83 | 84 | private Statement getTryCatchStatement(Statement stmt) { 85 | String tryStr = "try {\n" + 86 | stmt + "\n" + 87 | "} catch (Exception ex) {\n" + 88 | "ex.printStackTrace();\n" + 89 | "}"; 90 | return StaticJavaParser.parseStatement(tryStr); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/UnusedStatement.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.StaticJavaParser; 2 | import com.github.javaparser.ast.CompilationUnit; 3 | import com.github.javaparser.ast.Node; 4 | import com.github.javaparser.ast.body.MethodDeclaration; 5 | import com.github.javaparser.ast.stmt.BlockStmt; 6 | import com.github.javaparser.ast.stmt.EmptyStmt; 7 | import com.github.javaparser.ast.stmt.Statement; 8 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 9 | 10 | import java.io.File; 11 | import java.util.ArrayList; 12 | import java.util.Random; 13 | 14 | public class UnusedStatement extends VoidVisitorAdapter { 15 | private final Common mCommon; 16 | private File mJavaFile = null; 17 | private String mSavePath = ""; 18 | private final ArrayList mDummyNodes = new ArrayList<>(); 19 | 20 | UnusedStatement() { 21 | //System.out.println("\n[ UnusedStatement ]\n"); 22 | mCommon = new Common(); 23 | } 24 | 25 | public void inspectSourceCode(File javaFile) { 26 | this.mJavaFile = javaFile; 27 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 28 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 29 | if (root != null) { 30 | this.visit(root.clone(), null); 31 | } 32 | } 33 | 34 | @Override 35 | public void visit(CompilationUnit com, Object obj) { 36 | mDummyNodes.add(new EmptyStmt()); 37 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mDummyNodes); 38 | super.visit(com, obj); 39 | } 40 | 41 | public CompilationUnit applyTransformation(CompilationUnit com) { 42 | if (com.findFirst(MethodDeclaration.class).isPresent() && 43 | com.findFirst(MethodDeclaration.class).flatMap(MethodDeclaration::getBody).isPresent()) { 44 | BlockStmt blockStmt = new BlockStmt(); 45 | for (Statement statement : com.findFirst(MethodDeclaration.class) 46 | .flatMap(MethodDeclaration::getBody).get().getStatements()) { 47 | blockStmt.addStatement(statement); 48 | } 49 | int min = 0, max = blockStmt.getStatements().size() - 1; 50 | int place = new Random().nextInt(max - min + 1) + min; 51 | blockStmt.addStatement(place, getUnusedStatement()); 52 | MethodDeclaration md = com.findFirst(MethodDeclaration.class).get(); 53 | md.setBody(blockStmt); 54 | } 55 | return com; 56 | } 57 | 58 | private Statement getUnusedStatement() { 59 | String unusedStr = "if (false) { temp = 1; }"; 60 | return StaticJavaParser.parseStatement(unusedStr); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/VariableRenaming.java: -------------------------------------------------------------------------------- 1 | import com.github.javaparser.ast.CompilationUnit; 2 | import com.github.javaparser.ast.Node; 3 | import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 4 | import com.github.javaparser.ast.body.MethodDeclaration; 5 | import com.github.javaparser.ast.body.Parameter; 6 | import com.github.javaparser.ast.body.VariableDeclarator; 7 | import com.github.javaparser.ast.expr.SimpleName; 8 | import com.github.javaparser.ast.visitor.TreeVisitor; 9 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 10 | 11 | import java.io.File; 12 | import java.util.ArrayList; 13 | 14 | public class VariableRenaming extends VoidVisitorAdapter { 15 | private final Common mCommon; 16 | private File mJavaFile = null; 17 | private String mSavePath = ""; 18 | private final ArrayList mVariableNodes = new ArrayList<>(); 19 | private String mNewVariableName = ""; 20 | 21 | VariableRenaming() { 22 | //System.out.println("\n[ VariableRenaming ]\n"); 23 | mCommon = new Common(); 24 | } 25 | 26 | public void inspectSourceCode(File javaFile) { 27 | this.mJavaFile = javaFile; 28 | mSavePath = Common.mRootOutputPath + this.getClass().getSimpleName() + "/"; 29 | CompilationUnit root = mCommon.getParseUnit(mJavaFile); 30 | if (root != null) { 31 | this.visit(root.clone(), null); 32 | } 33 | } 34 | 35 | @Override 36 | public void visit(CompilationUnit com, Object obj) { 37 | locateVariableRenaming(com); 38 | mCommon.applyToPlace(this, mSavePath, com, mJavaFile, mVariableNodes); 39 | super.visit(com, obj); 40 | } 41 | 42 | private void locateVariableRenaming(CompilationUnit com) { 43 | final int[] variableId = {0}; 44 | mNewVariableName = "var"; 45 | new TreeVisitor() { 46 | @Override 47 | public void process(Node node) { 48 | if (isTargetVariable(node)) { 49 | mVariableNodes.add(node); 50 | if (node.toString().equals(mNewVariableName)) { 51 | variableId[0]++; 52 | mNewVariableName = "var" + variableId[0]; 53 | } 54 | } 55 | } 56 | }.visitPreOrder(com); 57 | //System.out.println("TargetVariable : " + mVariableList); 58 | } 59 | 60 | private boolean isTargetVariable(Node node) { 61 | return (node instanceof SimpleName && 62 | (node.getParentNode().orElse(null) instanceof Parameter 63 | || node.getParentNode().orElse(null) instanceof VariableDeclarator)); 64 | } 65 | 66 | public CompilationUnit applyTransformation(CompilationUnit com, Node varNode) { 67 | new TreeVisitor() { 68 | @Override 69 | public void process(Node node) { 70 | String oldName = varNode.toString(); 71 | if (node.toString().equals(oldName)) { 72 | if (node instanceof SimpleName 73 | && !(node.getParentNode().orElse(null) instanceof MethodDeclaration) 74 | && !(node.getParentNode().orElse(null) instanceof ClassOrInterfaceDeclaration)) { 75 | ((SimpleName) node).setIdentifier(mNewVariableName); 76 | } 77 | } 78 | } 79 | }.visitPreOrder(com); 80 | return com; 81 | } 82 | } 83 | --------------------------------------------------------------------------------