PSI导航
PSI导航
PSI导航分为3种方式:
从上向下:当你需要查询PSI文件或PSI元素的 子PSI元素 时(例如:查找它某个方法包含的变量)
从下向上:当你需要查找某一个PSI元素的父PSI元素时(例如:查找某个变量所在的方法)
引用:如果一个PSI元素是引用对象,可以导航到它的本体(声明该对象的地方),也可以从本体查找所有引用它的PSI元素。详情查看文档: PSI引用
从上向下导航
从上向下导航常用Visitor 。
下面方法可以获取到某个PSI元素内包含的所有JAVA局部变量:
// 1. 新建一个 Visitor的实现类(一般使用匿名内部类。Visitor跟编程语言有关,例如:JAVA使用JavaRecursiveElementVisitor,xml使用XmlElementVisitor),重写它的方法,在方法中过滤你想要的PSI元素,并处理业务逻辑
// 2. 在 PsiElement.accept() 方法中传入 上一步的实现类
PsiElement.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitLocalVariable(PsiLocalVariable variable) {
super.visitLocalVariable(variable);
System.out.println("Found a variable at offset " + variable.getTextRange().getStartOffset());
}
});
大多数情况下,你也可以使用特定的API进行导航。例如:可以直接使用 PsiClass.getMethods() 来获取一个java class的所有方法
PsiTreeUtil 提供了很多通用的,跟编程语言无关的方法,例如 findChildrenOfType()
从下向上导航
从下向上导航的时候,需要知道从哪个 PSI元素或 偏移量(offset) 开始。
如何你有偏移量(offset),可以直接使用 PsiFile.findElementAt() 方法获取到 PSI元素。这个方法返回的是具体的 PSI元素,如果你还需要访问它的前后关系,可以使用PSI树进行查找
大多数情况下,使用 PsiTreeUtil.getParentOfType() 方法进行自下而上的查找,这个方法从它自己开始访问它的所有父元素,直到找到对应的元素类型即返回。例如:可以使用 PsiTreeUtil.getParentOfType(element, PsiMethod.class) 查询PSI元素 所在的方法
有时候,也可以使用特定的查找方法,例如:PsiMethod.getContainingClass() 可以查找方法所在的类
下面的方法经常一起使用:
PsiFile psiFile = anActionEvent.getData(CommonDataKeys.PSI_FILE);
PsiElement element = psiFile.findElementAt(offset);
PsiMethod containingMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
PsiClass containingClass = containingMethod.getContainingClass();
PSI导航代码示例: PsiNavigationDemoAction