JavaParser:解析和生成Java代码

JavaParser:解析和生成Java代码,java,javaparser,Java,Javaparser,我已经阅读了JavaParser,并开始构建自己的示例。我想要实现的是阅读Java代码并在其上插入新的代码行。具体地说,我想在每个if和while语句之前初始化一个计数器,并在语句体内部对计数器进行递增。我这样做的目的是为一组指定的运行运行运行新代码,并观察每个分支执行了多少次。我使用JavaParser来解析和添加代码,因为我想自动生成和运行所有东西 例如,我们有以下简单的代码: if (x>4) { x=4; } else { x=4; } while (i&l

我已经阅读了JavaParser,并开始构建自己的示例。我想要实现的是阅读Java代码并在其上插入新的代码行。具体地说,我想在每个
if
while
语句之前初始化一个计数器,并在语句体内部对计数器进行递增。我这样做的目的是为一组指定的运行运行运行新代码,并观察每个分支执行了多少次。我使用JavaParser来解析和添加代码,因为我想自动生成和运行所有东西

例如,我们有以下简单的代码:

if (x>4) { 
   x=4; 
} 
else { 
   x=4; 
} 
while (i<x) {
   i++;
} 
if(x>4){
x=4;
} 
否则{
x=4;
} 
而(i4){
x=4;
countA++;
} 
否则{
x=4;
countB++;
} 
int countC=0;
而{
if(语句.isIfStmt()){
//System.out.println(statement.getChildNodes().get(0));
//System.out.println(statement.getParentNodeForArchildren().toString());
//statement.getChildNodes().add(statement.getChildNodes().get(0));
//System.out.println(statement.toString());
}
if(语句.iswhilesmt()){
//System.out.println();
}
});
系统输出打印项次(cu);
}
}

我试过一些东西(推荐的外线),但没有成功。我的主要问题是,我找不到一种方法在给定的
语句的
childNodes
末尾注入任何代码行,这可能是计数器的增量,或者在
parentnodes
末尾注入任何代码行,这可能是初始化。有什么方法可以实现我所描述的吗?

代码中的问题如下:

int countA=0; 
int countB=0;            
if (x>4) { 
   x=4; 
   countA++;
} 
else { 
   x=4; 
   countB++;
} 
int countC=0;
while (i<x) {
   i++;
   countC++;
} 
if (statement.isIfStmt()) {
该条件清楚地表明您正在处理if语句,因此实际上无法添加指令。 您需要做的是获取n+1元素(其中n是if语句的索引),然后使用:

cu.findAll(Statement.class).get(2).asBlockStmt().addStatement("countA++;")
有几种方法可以定义要添加的表达式,为了清晰起见,这里我使用了一个普通字符串,但请检查工作示例中的实际语法

暂时你可以使用同样的技术,但它会更复杂。为简单起见,将使用以下方法在方法开头添加计数器声明:

((BlockStmt)cu.findAll(Statement.class).get(6).getParentNode().get()).addStatement(0, new StringLiteralExpr("int b = 1;"));
剥蚀

  • 所有语句列表中的第六个语句是while循环
  • 此语句的父节点是该方法的主块,是要添加指令的地方
  • 需要将此对象类强制转换为BlockStmt才能使用addStatement方法
  • StringLiteralExpr是表达式的一个子类,在这里用于从字符串创建实例。您可以探索许多其他不同的实现
我复制了你的代码,制作了一个工作的JUnit5,这就是我得到的结果

公共类ParserTest{

String counterName = "count";
Integer counterIndex = 1;

@Test
public void main() {

    CompilationUnit cu = StaticJavaParser.parse("class X{void x(){" + "    if (x>4) {  " + "      x=4;  "
            + "    }  " + "    else {  " + "        x=4;  " + "    }  " + "    while (i<x) {  " + "        i++;  "
            + "    }  " + "    }}");

    cu.findAll(Statement.class).forEach(statement -> {
        if (statement.isIfStmt()) {

            // Add counter declaration in main block for the if
            String counterNameAndIndexIf = counterName + counterIndex++;
            // Create expression using StaticJavaParser
            Expression ifCounterExpression = StaticJavaParser
                    .parseVariableDeclarationExpr(" int " + counterNameAndIndexIf + " = 0");
            ((BlockStmt) statement.getParentNode().get()).addStatement(0, ifCounterExpression);

            // Add counter declaration in main block for the else
            String counterNameAndIndexElse = counterName + counterIndex++;
            // Create expression using StaticJavaParser
            Expression elseCounterExpression = StaticJavaParser
                    .parseVariableDeclarationExpr("int " + counterNameAndIndexElse + " = 0");
            ((BlockStmt) statement.getParentNode().get()).addStatement(0, elseCounterExpression);

            // Add if increment
            Expression ifIncrementExpression = StaticJavaParser.parseExpression(counterNameAndIndexIf + "++");
            ((BlockStmt) statement.getChildNodes().get(1)).addStatement(ifIncrementExpression);

            // Add else increment
            Expression elseIncrementExpression = StaticJavaParser.parseExpression(counterNameAndIndexElse + "++");
            ((BlockStmt) statement.getChildNodes().get(2)).addStatement(elseIncrementExpression);
        }
        if (statement.isWhileStmt()) {
            String counterNameAndIndexWhile = counterName + counterIndex++;
            Expression whileCounterExpression = StaticJavaParser
                    .parseVariableDeclarationExpr(" int " + counterNameAndIndexWhile + " = 0");
            ((BlockStmt) statement.getParentNode().get()).addStatement(0, whileCounterExpression);

            // Add while increment
            Expression whileIncrementExpression = StaticJavaParser.parseExpression(counterNameAndIndexWhile + "++");
            ((BlockStmt) statement.getChildNodes().get(1)).addStatement(whileIncrementExpression);

        }
    });
    System.out.println(cu);
}
这种方法将从根开始自上而下,始终指向主块。
使用它添加您的计数器变量。

可能是一个更复杂的示例,它将java代码转换为rust:这有助于理解。我通常不更改解析器创建的结构,但使用访问者创建一些新的内容。这是一个非常好且可理解的解决方案。它让我了解了如何在已存在的语法中分配新表达式现有代码。为了完成这个示例,我只有最后一个问题。当我添加另一个
if
while
语句时,在这个示例已经存在的
while
语句中,嵌套语句的计数器的初始化发生在父
节点
内。因此,每次执行sted语句并且再次满足父语句的条件,在再次输入嵌套语句之前,计数器将重置为零。如果我想在方法开始时分配所有计数器初始化,我是否应该使用
BlockStmt
?我正在描述的示例:
while(x<10){int count4=0;x++;如果(x<10){x++;count4++;}count3++;}
Hi@JohnStef确实,您描述的是我提供的代码的实际预期行为。我正在检查它如何支持在根上添加计数器的嵌套语句。为了计算语句的执行次数,不应该将所有初始化都放在方法的顶部,以防止重置为零吗(就像这种情况一样)?
String counterName = "count";
Integer counterIndex = 1;

@Test
public void main() {

    CompilationUnit cu = StaticJavaParser.parse("class X{void x(){" + "    if (x>4) {  " + "      x=4;  "
            + "    }  " + "    else {  " + "        x=4;  " + "    }  " + "    while (i<x) {  " + "        i++;  "
            + "    }  " + "    }}");

    cu.findAll(Statement.class).forEach(statement -> {
        if (statement.isIfStmt()) {

            // Add counter declaration in main block for the if
            String counterNameAndIndexIf = counterName + counterIndex++;
            // Create expression using StaticJavaParser
            Expression ifCounterExpression = StaticJavaParser
                    .parseVariableDeclarationExpr(" int " + counterNameAndIndexIf + " = 0");
            ((BlockStmt) statement.getParentNode().get()).addStatement(0, ifCounterExpression);

            // Add counter declaration in main block for the else
            String counterNameAndIndexElse = counterName + counterIndex++;
            // Create expression using StaticJavaParser
            Expression elseCounterExpression = StaticJavaParser
                    .parseVariableDeclarationExpr("int " + counterNameAndIndexElse + " = 0");
            ((BlockStmt) statement.getParentNode().get()).addStatement(0, elseCounterExpression);

            // Add if increment
            Expression ifIncrementExpression = StaticJavaParser.parseExpression(counterNameAndIndexIf + "++");
            ((BlockStmt) statement.getChildNodes().get(1)).addStatement(ifIncrementExpression);

            // Add else increment
            Expression elseIncrementExpression = StaticJavaParser.parseExpression(counterNameAndIndexElse + "++");
            ((BlockStmt) statement.getChildNodes().get(2)).addStatement(elseIncrementExpression);
        }
        if (statement.isWhileStmt()) {
            String counterNameAndIndexWhile = counterName + counterIndex++;
            Expression whileCounterExpression = StaticJavaParser
                    .parseVariableDeclarationExpr(" int " + counterNameAndIndexWhile + " = 0");
            ((BlockStmt) statement.getParentNode().get()).addStatement(0, whileCounterExpression);

            // Add while increment
            Expression whileIncrementExpression = StaticJavaParser.parseExpression(counterNameAndIndexWhile + "++");
            ((BlockStmt) statement.getChildNodes().get(1)).addStatement(whileIncrementExpression);

        }
    });
    System.out.println(cu);
}
class X {

void x() {
    int count3 = 0;
    int count2 = 0;
    int count1 = 0;
    if (x > 4) {
        x = 4;
        count1++;
    } else {
        x = 4;
        count2++;
    }
    while (i < x) {
        i++;
        count3++;
    }
}
statement.findRootNode().getChildNodes().get(0).getChildNodes().get(1).getChildNodes().get(2)