Idea 外掛開發常用的方法

JosenQiao發表於2017-11-12

建立檔案時用到的方法

獲取常用工具類

myFactory = JavaPsiFacade.getElementFactory(mProject);複製程式碼

獲取滑鼠選中的目錄

通過AnActionEvent獲取到Ideview,然後呼叫getOrChooseDiretory() 獲取滑鼠右擊選中的目錄

IdeView ideView = anActionEvent.getRequiredData(LangDataKeys.IDE_VIEW);
PsiDirectory directory = ideView.getOrChooseDirectory();複製程式碼

建立Java類

通過DirectoryService建立Java類

myDirectoryService = JavaDirectoryService.getInstance();
PsiClass psiClass = myDirectoryService.createClass(directory, "Text", JavaTemplateUtil.INTERNAL_CLASS_TEMPLATE_NAME);複製程式碼

設定包名

PsiJavaFile javaFile = (PsiJavaFile) psiClass.getContainingFile();
PsiPackage psiPackage = myDirectoryService.getPackage(directory);
javaFile.setPackageName(psiPackage.getQualifiedName());複製程式碼

設定類的許可權

psiClass.getModifierList().setModifierProperty(PsiModifier.PUBLIC,true);複製程式碼

psiClass類中新增介面

PsiClass view = myFactory.createInterface("View");
psiClass.add(view);複製程式碼

根據名字全域性查詢PsiClass

private PsiClass getPsiClassByName(String name) {

        PsiClass[] psiClasses = myShortNamesCache.getClassesByName(name, myProjectScope);//NotNull
        PsiClass psiClass = null;
        if (psiClasses.length != 0) {//if the class already exist.
            psiClass = psiClasses[0];
        }//and
        return psiClass;
    }複製程式碼

根據PsiFile查詢PsiClass

  if ((psiFile1 instanceof PsiJavaFile) && ((PsiJavaFile) psiFile1).getClasses().length > 0) {
                psiClass = ((PsiJavaFile) psiFile1).getClasses()[0];
            }複製程式碼

手動設定Action的名字和圖示

Presentation presentation = getTemplatePresentation();
presentation.setText(fileType);
presentation.setIcon(IconLoader.getIcon("/icons/icon_tf.png"));複製程式碼

其中icons要放到Resource目錄下:

注意圖片的命名規則

在ActionGroup中手動新增Acton

public class AddMVPFile extends DefaultActionGroup implements DumbAware {

    public AddMVPFile() {
        setPopup(true);
        Presentation presentation = getTemplatePresentation();
        presentation.setText("MVPFile");
        presentation.setIcon(IconLoader.getIcon("/icons/icon_tf.png"));


        List<String> fileTypes = new ArrayList<>();
        fileTypes.add("Contract");
        fileTypes.add("PresenterImpl");
        fileTypes.add("ModelImpl");

        for (String fileType:fileTypes){
            add(new AddFile(fileType));
        }
    }
}複製程式碼

其中AddFile是Acton,要實現如下所示的效果,需要加入 setPopup(true);否則Action是平鋪開來的,沒辦法放到MVPFile下

通過複寫Action 的 update 來控制Action是否可見

@Override
    public void update(AnActionEvent e) {
        super.update(e);
        IdeView ideView = e.getRequiredData(LangDataKeys.IDE_VIEW);
        PsiDirectory directory = ideView.getOrChooseDirectory();
        if (directory.getName().equals("contract"))
            e.getPresentation().setEnabledAndVisible(true);
        else
            e.getPresentation().setEnabledAndVisible(false);

    }複製程式碼

e.getPresentation().setEnabled(true);用來設定該Action是否可用,
e.getPresentation().setEnabledAndVisible(true);用來設定該Action可用並且可見,可以靈活選用

顯示錯誤資訊

Messages.showErrorDialog("Generation failed, " +
                            "your class name MUST END WITH 'Contract' or 'Presenter'.",
                    "Class Name Error");複製程式碼

Dialog 設定

//設定Dialog的標題
setTitle("New Mvp File");

//設定Dialog的最小大小
setMinimumSize(new Dimension(260, 120));

//設定Dialog在螢幕中間,public void setLocationRelativeTo(Component c)設定視窗相對於指定元件的位置。 
//如果元件當前未顯示,或者 c 為 null,則此視窗將置於螢幕的中央。
setLocationRelativeTo(null);複製程式碼

setLocationRelativeTo(null)可以使其螢幕居中,但如果IDE不全屏,顯示的效果就不好看了,想使Dialog在IDE視窗居中顯示,可以這樣設定:

setLocationRelativeTo(WindowManager.getInstance().getFrame(actionEvent.getProject())

注意setMinimumSize和setLocationRelativeTo的先後位置,如果setLocationRelativeTo在前,則建立出來的視窗的左上角居中,因為這時視窗還沒有大小。

匯入需要的類

要想使用如下的方法匯入import,前提條件是需要匯入的類必須包含包名,例如Log.e需要寫成android.util.Log.e(TAG,field.toString());

JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
styleManager.optimizeImports(file);
styleManager.shortenClassReferences(targetClass);複製程式碼

獲取PsiElment下所有的PsiStatement

for (PsiStatement psiStatement : psiMethod.getBody().getStatements()) {
    EventLogger.log(psiStatement.getText());
   // 查詢setContentView
    if (psiStatement.getFirstChild() instanceof PsiMethodCallExpression) {
        PsiReferenceExpression methodExpression = ((PsiMethodCallExpression) psiStatement.getFirstChild()).getMethodExpression();
        if (methodExpression.getText().equals("setContentView")) {
           setContentViewStatement = psiStatement;
        } else if (methodExpression.getText().equals("initView")) {
           hasInitViewStatement = true;               

        }            

    }
}複製程式碼

c

相關文章