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