gpt4 book ai didi

JavaParser:解析并生成Java代码

转载 作者:行者123 更新时间:2023-11-30 05:25:57 26 4
gpt4 key购买 nike

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

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

if (x>4) { 
x=4;
}
else {
x=4;
}
while (i<x) {
i++;
}

解析之后我希望得到如下内容:

int countA=0; 
int countB=0;
if (x>4) {
x=4;
countA++;
}
else {
x=4;
countB++;
}
int countC=0;
while (i<x) {
i++;
countC++;
}

到目前为止我的代码:

public static void main (String[] args) throws Exception {          
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()) {
//System.out.println(statement.getChildNodes().get(0));
// System.out.println(statement.getParentNodeForChildren().toString());
// statement.getChildNodes().add(statement.getChildNodes().get(0));

// System.out.println(statement.toString());
}
if (statement.isWhileStmt()) {
// System.out.println();
}
});
System.out.println(cu);
}
}

我尝试了一些事情(推荐的行)但没有成功。我的主要问题是,我找不到在给定的 statementchildNodes 末尾注入(inject)任何代码行的方法,这应该是计数器的增量或在 parentNode 的末尾,这将是初始化。有什么办法可以实现我所描述的吗?

最佳答案

您的代码中的问题如下:

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循环
  • 此语句的父节点是该方法的主 block ,也是您要添加指令的位置
  • 此对象需要类转换为 BlockStm才能使用 addStatement 方法
  • StringLiteralExpr 是 Expression 的子类,此处用于从字符串创建实例。您可以探索许多其他不同的实现。

我复制了您的代码,制作了一个工作 JUnit 5,这就是我得到的结果

公共(public)类 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);
}

结果是

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++;
}
}

希望这有帮助。如果您需要有关如何构建这些对象的说明,请告诉我。当然有更聪明的方法和代码可以明显地重构,但我希望尽可能简单地为您说明。

干杯

编辑:为了支持语句嵌套并声明方法主 block 中的所有计数器变量,可以使用以下内容

statement.findRootNode().getChildNodes().get(0).getChildNodes().get(1).getChildNodes().get(2)

这种方法将从根部自上而下开始,并且始终指向主 block 。用它来添加计数器变量。

关于JavaParser:解析并生成Java代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58611706/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com