PsiElement接口是文件中光标所在的那个字段,或者光标所在的那个方法的抽象,例如下图中,PsiElement就是private String name
而下图中PsiElement就是public String getName()
下面的代码会演示:光标在方法上,就打印方法名字,光标在字段上,就打印字段名字,但是我们在写代码之前还要做一些其他工作,由于IntelliJ平台的变化,导致不在默认加载PsiMethodImpl
和PsiFieldImpl
两个类所在的jar包,而我们恰好要用到这两个类,所以需要手动依赖这两个类,我们在plugin.xml
增加如下依赖
// 下面这1行是项目创建的时候就自带的
<depends>com.intellij.modules.platform</depends>
// 下面这2行是我们刚刚添加的,我们需要的两个类就在下面的jar包下
<depends>com.intellij.modules.lang</depends>
<depends>com.intellij.modules.java</depends>
官网说明在这个地址
代码示例
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.source.PsiFieldImpl;
import com.intellij.psi.impl.source.PsiMethodImpl;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.keyFMap.KeyFMap;
import org.jetbrains.annotations.NotNull;
public class MyAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
PsiElement psiElement = e.getData(PlatformDataKeys.PSI_ELEMENT);
if (psiElement != null) {
PsiManager manager = psiElement.getManager();
IElementType elementType = psiElement.getNode().getElementType();
// 如果光标所在位置是一个方法
if ("METHOD".equals(elementType.toString())) {
PsiMethodImpl m = (PsiMethodImpl) psiElement;
System.out.println(m.getName());
}
// 如果光标所在位置是一个字段
if ("FIELD".equals(elementType.toString())) {
PsiFieldImpl f = (PsiFieldImpl) psiElement;
System.out.println(f.getName());
}
}
}
}
部分方法总结,前提示例代码如下:
public class UserEntity {
/**
* 怀念二抱
* 想念三抱
**/
private String name;
public String getName() {
return name;
}
}
获取name
字段的偏移量(光标必须在name上)
PsiElement psiElement = e.getData(PlatformDataKeys.PSI_ELEMENT);
PsiFieldImpl f = (PsiFieldImpl) psiElement;
int offset = f.getTextOffset();
获取UserEntity
的偏移量(实际得到的是字母U前面空格的偏移量,拿到结果自己+1即可)
PsiElement psiElement = e.getData(PlatformDataKeys.PSI_ELEMENT);
PsiFieldImpl f = (PsiFieldImpl) psiElement;
int offset = f.getStartOffsetInParent();
获取name
字段注释(光标必须在name上),也就是本示例的"怀念二抱"和"想念三抱"
PsiElement psiElement = e.getData(PlatformDataKeys.PSI_ELEMENT);
PsiFieldImpl f = (PsiFieldImpl) psiElement;
PsiDocComment javaDoc = f.getDocComment();
for (PsiElement descriptionElement : descriptionElements) {
// 因为是文本操作,所以我们只取我们写的注释,忽略斜杠星号什么的,所以此处if判断
// 只有PsiDocToken的子类PsiDocTokenImpl才是我们写的注释,这个if会进入2次,
// 1次是"怀念二抱"
// 1次是"想念三抱"
if(descriptionElement instanceof PsiDocToken){
System.out.println(descriptionElement.getText());
}
}