IDEA外掛開發學習

月光邊境發表於2018-01-18

一.開發環境

由於Android Studio是無法建立idea plugin 專案的,所以需要先安裝IDEA

  1. 新建一個Intellij Platform Plugin Project,如果是第一次建立需要點選new設定Project SDK。
    IDEA外掛開發學習
  2. 在Project的resources/META-INF目錄下有一個plugin.xml檔案,這個檔案作用是儲存外掛的所有配置資訊,相當於Android 的AndroidManifest.xml檔案。
  3. 在src目錄下新建一個Action:src>右鍵>new>Action:
    IDEA外掛開發學習
  • Action ID :Action的唯一表示,建議以PluginName.ID的格式命名
  • Class Name : Action的類名
  • Name : Action顯示在工具欄的名字
  • Description : Action的功能描述 不是必須填寫的
  • Groups : 將Action 新增的一個分組,可選的有很多,我這裡選擇GenerateGroup,最後就可以在Generate這一組Action中看到:
    IDEA外掛開發學習
  • Keyboard Shortcuts : 觸發Action的快捷鍵

然後plugin中會自動生成配置資訊:

  <actions>
    <!-- Add your actions here -->
    <action id="Test.ID" class="TestAction" text="Test">
      <add-to-group group-id="GenerateGroup" anchor="last"/>
      <keyboard-shortcut keymap="$default" first-keystroke="shift alt V"/>
    </action>
  </actions>
複製程式碼

4 .actionPerformed方法是程式的入口,從這裡開始實現外掛的功能,在這裡先簡單的彈出一個對話方塊。

public class TestAction extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        // TODO: insert action logic here
        Messages.showMessageDialog("Hello!", "Information", Messages.getInformationIcon());
    }
}
複製程式碼

5.點選Run,然後會重新啟動一個Idea,在這裡我們可以測試我們的程式 6.打包外掛程式,右鍵工程目錄>Prepare Plugin Module 'Test' For Deployment,然後可以得到一個jar檔案,這個jar就是外掛的安裝包,idea可以通過Settings>Plugins>Install plugin from disk來安裝外掛

IDEA外掛開發學習
7.釋出到idea 外掛倉庫:

  • 首先需要註冊一個帳號https://account.jetbrains.com/login
  • 上傳外掛https://plugins.jetbrains.com/idea/plugin/add 然後在兩個工作日之後就可以在idea 的外掛倉庫搜尋到上傳的外掛了

二.外掛開發一些API

獲取當前編輯的檔案 PsiFile psiFile = event.getData(LangDataKeys.PSI_FILE); 可以通過下面兩種方式對檔案的進行操作:

        new WriteCommandAction.Simple(event.getProject(), psiFile) {
            @Override
            protected void run() throws Throwable {
                //do something
            }
        }.execute();
複製程式碼
        WriteCommandAction.runWriteCommandAction(event.getProject(), new Runnable() {
            @Override
            public void run() {
                //do something
            }
        });
複製程式碼

獲取當前編輯的class物件

        PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset());
        PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
複製程式碼

獲取類名

        String className = psiClass.getNameIdentifier().getText();
複製程式碼

獲得PsiElementFactory 物件 可以通過這個工廠類建立成員變數 方法 類等等

        PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
複製程式碼

新增一個方法

        String methodText = buildMethodText(className);
        PsiMethod psiMethod = elementFactory.createMethodFromText(methodText, psiClass);
        psiClass.add(psiMethod);
複製程式碼
        private String buildMethodText (String className){
            return "public static " + className + " getInstance() {\n" +
                    "        return " + buildFiledText() + ";\n" +
                    "    }";
        }
複製程式碼

新增一個構造方法

        PsiMethod constructor = elementFactory.createConstructor();
        psiClass.add(constructor);
複製程式碼

新增一個成員變數,PsiType表示變數的型別,PsiModifierList代表變數的修飾符,可以通過setInitializer設定變數初始化方式

        PsiType psiType = PsiType.getTypeByName(className, project
                , GlobalSearchScope.EMPTY_SCOPE);
        PsiField psiField = elementFactory.createField("mInstance", psiType);
        PsiExpression psiInitializer = elementFactory.createExpressionFromText("new " + className + "()", psiField);
        psiField.setInitializer(psiInitializer);
        PsiModifierList modifierList = psiField.getModifierList();
        if (modifierList != null) {
            modifierList.setModifierProperty(PsiModifier.STATIC, true);
        }
        psiClass.add(psiField);
複製程式碼

新增一個內部類

        PsiClass innerClass = elementFactory.createClass(innerClassName);
        PsiModifierList classModifierList = innerClass.getModifierList();
        if (classModifierList != null) {
            classModifierList.setModifierProperty(PsiModifier.PRIVATE, true);
            classModifierList.setModifierProperty(PsiModifier.STATIC, true);
        }
		psiClass.add(innerClass);
複製程式碼

其他

        //建立列舉
        PsiClass anEnum = elementFactory.createEnum("TestEnum");
        //建立一個列舉常量
        PsiEnumConstant enumConstant= elementFactory.createEnumConstantFromText("TEST",anEnum);
        //建立介面
        elementFactory.createInterface("TestInterface");
複製程式碼

格式化程式碼

        CodeStyleManager.getInstance(project).reformat(psiClass);
複製程式碼

外掛的UI都是使用java Swing來實現,比如建立一個Dialog:src>new>Dialog;然後會生成一個JDialog的java類和一個Dialog的from檔案。然後在Action中使用:

        TestDialog dialog = new TestDialog();
        dialog.setBounds(new Rectangle(300, 200));
        //讓dialog居中
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
複製程式碼

三. 一個生成單例程式碼的外掛

為了練手,寫了個小外掛,可以自動生成五種單例模式(IDEA自帶生成單例程式碼的功能,不過只有一種模式):懶漢式,餓漢式,雙重檢查,靜態內部類和列舉。 在Android Studio或者IDEA中使用:Settings>Plugins>Browse repositories 搜尋singleton,如下圖,點選install 然後重啟Android Studio 或者IDEA就可以使用了。

IDEA外掛開發學習
選單欄選擇Code>Generate或者使用你設定的快捷鍵:
IDEA外掛開發學習
選擇一種單例模式:
IDEA外掛開發學習
自動生成的程式碼:
IDEA外掛開發學習


intellij官方文件 GitHub地址

相關文章