查找 If/Else 块中的当前语句是否是 THEN 分支的最后一条语句
Find if the current statement in an If/Else block is the last statement of the THEN branch
我正在使用 JavaParser 来解析以下代码的内容并识别语句的顺序:
class X {
void x() {
int x = 1;
if (x>4) {
x=21;
} else {
if (x>1) {
x=3;
} else {
x=212;
}
}
if (x==4) {
x=3;
}
}}
我用来解析上面例子的代码:
private static void statements(BlockStmt block, State beforeState, State afterState) {
List<State> states = new ArrayList<>();
for (Statement statement : block.getStatements()) {
states.add(new State(statement));
}
beforeState.nextStates.add(states.get(0));
for (int i = 0; i < states.size(); i++) {
State currentState = states.get(i);
State nextState;
if (i == states.size() - 1) {
nextState = afterState;
} else {
nextState = states.get(i + 1);
}
currentState.statement.accept(new VoidVisitorWithDefaults<Void>() {
@Override
public void visit(ExpressionStmt n, Void arg) {
currentState.nextStates.add(nextState);
}
@Override
public void visit(IfStmt n, Void arg) {
statements(n.getThenStmt().asBlockStmt(), currentState, nextState);
n.getElseStmt().ifPresent(elseStmt ->
statements(elseStmt.asBlockStmt(), currentState, nextState));
}
}, null);
} }
我还想做的是判断当前语句是否是表达式语句(即赋值语句),如果是,则判断它是否是[=26的THEN块中包含的最后一条语句=] 语句。在上面的示例中,这将是语句 x=3;
。但是,我不确定如何实现。
到目前为止,我的思路是这样的:
ExpressionStmt exprStmt = (ExpressionStmt) currentState.statement;
Node exprStmtParent = exprStmt.getParent();
List<Node> exprStmtSibilings = exprStmtParent.getChildNodes();
Node lastNode = exprStmtSiblings.get(exprStmtSiblings.size() - 1);
boolean exprStmtIsLast = lastNode == ifStmt;
适用于 if 语句但不适用于赋值。关于如何处理这个问题有什么建议吗?
这个答案可能来晚了,但这是您可以解决问题的方法。
如果 n.getThenStmt() 的结果是一个 BlockStmt,您可以在其上调用 getStatements,returns 一个 NodeList,然后在列表上调用 getLast。
使用equals方法比较节点更安全
访问者需要调用super.visit方法才能完整访问节点(表达式或语句)。
下面是一个简化的例子。
public void test() {
String str = "class X {\r\n" +
" void x() {\r\n" +
" int x = 1;\r\n" +
" if (x>4) {\r\n" +
" x=21;\r\n" +
" } else {\r\n" +
" if (x>1) {\r\n" +
" x=3;\r\n" +
" } else {\r\n" +
" x=212;\r\n" +
" } \r\n" +
" } \r\n" +
" if (x==4) { \r\n" +
" x=3;\r\n" +
" }\r\n" +
"}}";
CompilationUnit cu = StaticJavaParser.parse(str);
VoidVisitor<Void> visitor = new VoidVisitorAdapter<Void>() {
ExpressionStmt currentStmt;
@Override
public void visit(ExpressionStmt n, Void arg) {
currentStmt = n;
super.visit(n, arg);
}
@Override
public void visit(IfStmt n, Void arg) {
Statement then = n.getThenStmt();
if (then instanceof BlockStmt) {
BlockStmt blockThenStmt = then.asBlockStmt();
super.visit(blockThenStmt, arg); // <-- visit statements in thenStmt
Optional<Statement> oStmt = blockThenStmt.getStatements().getLast();
if (oStmt.isPresent() && oStmt.get().equals(currentStmt)) {
System.out.println(String.format("--> %s expression is the last of %s", currentStmt.toString(), n.toString()));
}
}
super.visit(n, arg); // <-- visit nested ifStmt
}
};
cu.accept(visitor, null);
}
我正在使用 JavaParser 来解析以下代码的内容并识别语句的顺序:
class X {
void x() {
int x = 1;
if (x>4) {
x=21;
} else {
if (x>1) {
x=3;
} else {
x=212;
}
}
if (x==4) {
x=3;
}
}}
我用来解析上面例子的代码:
private static void statements(BlockStmt block, State beforeState, State afterState) {
List<State> states = new ArrayList<>();
for (Statement statement : block.getStatements()) {
states.add(new State(statement));
}
beforeState.nextStates.add(states.get(0));
for (int i = 0; i < states.size(); i++) {
State currentState = states.get(i);
State nextState;
if (i == states.size() - 1) {
nextState = afterState;
} else {
nextState = states.get(i + 1);
}
currentState.statement.accept(new VoidVisitorWithDefaults<Void>() {
@Override
public void visit(ExpressionStmt n, Void arg) {
currentState.nextStates.add(nextState);
}
@Override
public void visit(IfStmt n, Void arg) {
statements(n.getThenStmt().asBlockStmt(), currentState, nextState);
n.getElseStmt().ifPresent(elseStmt ->
statements(elseStmt.asBlockStmt(), currentState, nextState));
}
}, null);
} }
我还想做的是判断当前语句是否是表达式语句(即赋值语句),如果是,则判断它是否是[=26的THEN块中包含的最后一条语句=] 语句。在上面的示例中,这将是语句 x=3;
。但是,我不确定如何实现。
到目前为止,我的思路是这样的:
ExpressionStmt exprStmt = (ExpressionStmt) currentState.statement;
Node exprStmtParent = exprStmt.getParent();
List<Node> exprStmtSibilings = exprStmtParent.getChildNodes();
Node lastNode = exprStmtSiblings.get(exprStmtSiblings.size() - 1);
boolean exprStmtIsLast = lastNode == ifStmt;
适用于 if 语句但不适用于赋值。关于如何处理这个问题有什么建议吗?
这个答案可能来晚了,但这是您可以解决问题的方法。
如果 n.getThenStmt() 的结果是一个 BlockStmt,您可以在其上调用 getStatements,returns 一个 NodeList,然后在列表上调用 getLast。
使用equals方法比较节点更安全
访问者需要调用super.visit方法才能完整访问节点(表达式或语句)。
下面是一个简化的例子。
public void test() {
String str = "class X {\r\n" +
" void x() {\r\n" +
" int x = 1;\r\n" +
" if (x>4) {\r\n" +
" x=21;\r\n" +
" } else {\r\n" +
" if (x>1) {\r\n" +
" x=3;\r\n" +
" } else {\r\n" +
" x=212;\r\n" +
" } \r\n" +
" } \r\n" +
" if (x==4) { \r\n" +
" x=3;\r\n" +
" }\r\n" +
"}}";
CompilationUnit cu = StaticJavaParser.parse(str);
VoidVisitor<Void> visitor = new VoidVisitorAdapter<Void>() {
ExpressionStmt currentStmt;
@Override
public void visit(ExpressionStmt n, Void arg) {
currentStmt = n;
super.visit(n, arg);
}
@Override
public void visit(IfStmt n, Void arg) {
Statement then = n.getThenStmt();
if (then instanceof BlockStmt) {
BlockStmt blockThenStmt = then.asBlockStmt();
super.visit(blockThenStmt, arg); // <-- visit statements in thenStmt
Optional<Statement> oStmt = blockThenStmt.getStatements().getLast();
if (oStmt.isPresent() && oStmt.get().equals(currentStmt)) {
System.out.println(String.format("--> %s expression is the last of %s", currentStmt.toString(), n.toString()));
}
}
super.visit(n, arg); // <-- visit nested ifStmt
}
};
cu.accept(visitor, null);
}