插件:如何在现有的PHP类中插入新方法?

时间:2016-04-03 20:14:47

标签: intellij-idea phpstorm intellij-14 intellij-plugin

我正在尝试创建一个IntelliJ插件(主要用于学习目的)。我的目标是通过按键盘快捷键,插件将在测试文件中生成相应的PHP单元测试方法存根。

因此,假设Db.php已打开,按下Ctrl+Shift+U插件将在DbTest.php中创建单元测试存根。

到目前为止,我已经找到了如何在光标处获取方法名称以及如何将相应的单元测试文件(即Db => DbTest)定位为PsiFile

PsiFile[] search = FilenameIndex.getFilesByName(project, testFileName, scope); //scope is the test directory
PsiFile testFile = search[0];

我无法弄清楚如何在testFile中插入生成的新方法存根,然后保存更改?

P.S。我看到存在createMethodFromText函数,但如何从PsiFile获取PsiClass?另外如何保存更改?

2 个答案:

答案 0 :(得分:1)

只需几个简单的步骤。

  1. 查找要插入新方法的PhpClass。如您已经PsiFile,您可以手动遍历树或使用PhpElementVisitor

    1.1。要手动遍历树,您可以使用PsiTreeUtil#findChildOfType方法。在您的情况下,您需要首先找到GroupStatement,然后找到您需要的课程。

    1.2。通过PsiElement#accept方式调用PsiFile方法(PsiElementPhpElementVisitor的一个实例),其中包含已覆盖的#visitPhpGroupStatement#visitPhpClass方法。

    < / LI>
  2. 使用PhpPsiElementFactory#createMethod从文本创建新方法。请注意,此类不是公共API的一部分,因此从理论上讲,它可以在将来轻松更改/移动/删除/无论如何。

  3. 使用PsiElement#addPhpClass也是PsiElement的实例)将方法插入到课程中。

  4. 这就是全部。您无需明确保存更改。

答案 1 :(得分:0)

这最终对我有用。谢谢大家的帮助

for (int i = 0; i < found.getTextLength(); i++) {
    PsiElement ele = found.findElementAt(i);
    PhpClass phpClass = PsiTreeUtil.getParentOfType(ele, PhpClass.class);

    if (phpClass != null) {
        Method methodExists = findMethod(phpClass, methodName);

        if (methodExists == null) {
            new WriteCommandAction.Simple(phpClass.getProject(), phpClass.getContainingFile()) {
                @Override
                protected void run() throws Throwable {
                    PsiElement brace = phpClass.getLastChild();

                    if (brace != null) {
                        Method method = PhpPsiElementFactory.createMethod(phpClass.getProject(), "public function " + methodName + "() {\n\n}");
                        CodeStyleManager styleManager = CodeStyleManager.getInstance(getProject());
                        styleManager.reformat(method);
                        PsiElement newMethod = phpClass.addBefore(method, brace);
                        PsiNavigateUtil.navigate(newMethod);
                    }
                }
            }.execute();
        } else {
            PsiNavigateUtil.navigate(methodExists);
        }

        break;
    }
}