在插入符处获取上下文

Get context at caret

我正在开发一个 IntelliJ IDEA 插件来获取当前插入符处的上下文。更具体地说,我需要获取可在插入符处使用的变量类型和名称的列表。例如:

public static void main(String[] args) throws IOException {
    Workbook wb = new HSSFWorkbook();
    // caret 1
    Sheet sheet = wb.createSheet("new sheet");
    Row row = sheet.createRow((short) 1);
    for(int i = 0; i < 5; i++) {
        // caret 2
        row.createCell(i).setCellValue("X");
    }
    // caret 3
}

我需要在插入符号 1 处获取 wb: Workbook,在插入符号 2 处获取 wb: Workbook, sheet: Sheet, row: Row, i: int,在插入符号 3 处获取 wb: Workbook, sheet: Sheet, row: Row,因为 i: int 不再在范围内。

This link 似乎相关,它建议 file.findElementAt(editor.getCaretModel().getOffset())。此表达式 returns 一个 PsiElement 对象。但是,当我获取此对象的上下文并使用PsiRecursiveElementVisitor遍历上下文时,它将访问插入符号之后定义的元素,这不符合我上面的要求。

我的代码:

public class ContextView extends AnAction {

    public void actionPerformed(AnActionEvent event) {
        final Editor editor = event.getRequiredData(CommonDataKeys.EDITOR);
        final Project project = event.getRequiredData(CommonDataKeys.PROJECT);
        //Access document, caret, and selection
        final Document document = editor.getDocument();
        PsiJavaFile javaFile = (PsiJavaFile) PsiDocumentManager.getInstance(project).getPsiFile(document);

        PsiElement currentEle = javaFile.findElementAt(editor.getCaretModel().getOffset());
        PsiElement cxt = currentEle.getContext();

        cxt.accept(new PsiRecursiveElementVisitor() {
            @Override
            public void visitElement(PsiElement element) {
                System.out.println(element.toString());
                super.visitElement(element);
            }
        });
    }
}

那么如何解决问题呢?

This link seems related, it suggests file.findElementAt(editor.getCaretModel().getOffset()). This expression returns a PsiElement object. However, when I get context of this object and traverse the context using PsiRecursiveElementVisitor, it will visit elements defined after caret, which doesn't meet my requirement above.

你试过com.intellij.psi.util.PsiTreeUtil#getParentOfType(com.intellij.psi.PsiElement, java.lang.Class<T>)了吗?您可以用 findElementAt 的结果填充第一个参数,用 PsiDeclarationStatement.class 填充第二个参数,这是变量声明的 Psi class。

由此可以得到局部变量声明。您可以通过 sout(parent.getText())

进行测试