我正在使用org.eclipse.jdt.core.dom来生成一些给定 Java 源代码的 AST。生成 AST 后,我有了根节点。
如何使用 anASTVisitor
来解析我的 AST 以获取所有叶节点?
我正在使用org.eclipse.jdt.core.dom来生成一些给定 Java 源代码的 AST。生成 AST 后,我有了根节点。
如何使用 anASTVisitor
来解析我的 AST 以获取所有叶节点?
如果您还不熟悉特定的设计模式,我建议您先阅读访问者模式。
本质上,它归结为使用双重调度来调用Visitor
类上的适当方法,将访问的对象作为参数传递。通常,它的实现方式与以下(YMMV)类似:
public interface Node {
void acceptVisitor(Visitor v);
Collection<Node> getChildren();
}
// Incomplete implementation, for demonstration only
public class SubNode implements Node {
@Override
public void acceptVisitor(Visitor v) {
if(v.preVisit(this)) {
v.visit(this);
v.postVisit(this);
}
getChildren().forEach(child -> child.accept(v));
}
}
public interface Visitor {
boolean preVisit(Node node);
void visit(Node node);
void visit(SubNode node);
void postVisit(Node node);
}
然后Visitor
实现接口,并将其传递给acceptVisitor
a 的方法Node
(通常,但不总是,树的根节点)。
要更全面地了解如何实现您的ASTVisitor
.
在您的特定情况下,您需要扩展org.eclipse.jdt.core.dom.ASTVisitor
类,覆盖您关心visit
的实现的方法。org.eclipse.jdt.core.dom.ASTNode
然后将 this 的一个实例传递给 AST 的根节点ASTVisitor
的方法。accept
由于您正在寻找叶节点(定义为没有子节点的 AST 节点),您可以执行以下操作来检索 an 的子节点ASTNode
:
public Object[] getChildren(ASTNode node) {
List list= node.structuralPropertiesForType();
for (int i= 0; i < list.size(); i++) {
StructuralPropertyDescriptor curr= (StructuralPropertyDescriptor) list.get(i);
Object child= node.getStructuralProperty(curr);
if (child instanceof List) {
return ((List) child).toArray();
} else if (child instanceof ASTNode) {
return new Object[] { child };
}
return new Object[0];
}
}
通过调用此方法并传递您检查的每个节点,您可以确定该节点是否没有子节点(length
返回数组的值为 0)并将它们添加到Collection
您的 a 中ASTVisitor
以跟踪它们。
这可能不是正确的方法,但这可以获取所有叶节点。
1)维护两组节点,比方说S1
和S2
。
2)遍历所有节点并将每个节点添加到S1
。
3) 如果node.getParent() != null
,则添加node.getParent()
到S2
4) 这意味着S1
跟踪所有节点,同时S2
拥有所有内部节点。所以叶节点是S1 - S2
。
希望能帮助到你。
一个例子是这样的:
package de.vogella.jdt.astsimple.handler;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.MethodDeclaration;
public class MethodVisitor extends ASTVisitor {
List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
@Override
public boolean visit(MethodDeclaration node) {
methods.add(node);
return super.visit(node);
}
public List<MethodDeclaration> getMethods() {
return methods;
}
}