IDEA插件编写四(PsiAugmentProvider)

1.什么是PsiAugmentProvider

当用户在编辑器中输入.后,将在提示框中展示自定义的属性或者方法

2.创建PsiAugmentProvider项目

2.1 pom文件

<idea-plugin>
  <id>com.wangxb.plugin.MyPlugin</id>
  <name>我的插件</name>
  <version>1.0</version>
  <vendor email="wang5525369@sina.com" url="http://www.wangxb.com">wangxb</vendor>

  <description>我的插件我的插件我的插件我的插件我的插件我的插件我的插件说明主要是增加属性的说明</description>

  <change-notes>我的插件我的插件我的插件我的插件我的插件我的插件我的插件说明主要是增加属性的说明</change-notes>

  <!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
  <idea-version since-build="193.0"/>

  <!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
       on how to target different products -->
  <depends>com.intellij.modules.java</depends>

  <extensions defaultExtensionNs="com.intellij">
      <lang.psiAugmentProvider implementation="com.wangxb.plugin.MyPsiAugmentProvider"/>
  </extensions>

  <actions>
    
  </actions>


</idea-plugin>

2.2代码文件

package com.wangxb.plugin;

import com.intellij.ide.structureView.StructureViewExtension;
import com.intellij.lang.jvm.JvmParameter;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.impl.light.LightFieldBuilder;
import com.intellij.psi.impl.light.LightModifierList;
import com.intellij.psi.impl.light.LightParameter;
import com.intellij.psi.impl.light.LightParameterListBuilder;
import com.intellij.psi.impl.source.PsiExtensibleClass;
import com.intellij.psi.util.CachedValuesManager;
import com.wangxb.plugin.utils.MyFieldUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MyPsiAugmentProvider extends PsiAugmentProvider {
    String annotaionName = "com.wangxb.annotation.AddField";

    @Override
    @NotNull
    protected <Psi extends PsiElement> List<Psi> getAugments(@NotNull PsiElement psiElement, @NotNull Class<Psi> type) {
        final List<Psi> emptyResult = Collections.emptyList();

        if ((psiElement instanceof PsiClass) == false){
            return emptyResult;
        }

        PsiClass psiClass = (PsiClass) psiElement;
        PsiAnnotation psiAnnotation = MyFieldUtils.getAnnotation(psiClass,annotaionName);
        if (psiAnnotation == null) {
            return emptyResult;
        }

        if (PsiField.class.isAssignableFrom(type)) {
            String fieldName = MyFieldUtils.getAnnotationValue(psiAnnotation, "fieldName");
            if ("".equals(fieldName) == false) {
                PsiType psiType = MyFieldUtils.getPsiType(psiClass,"java.lang.String");
                PsiField psiField = MyFieldUtils.createCacheField(psiClass, fieldName,psiType);
                List<PsiElement> psiElementList = new ArrayList<>();
                psiElementList.add(psiField);

                return (List<Psi>) psiElementList;
            }
        }else if (PsiMethod.class.isAssignableFrom(type)){
            String fieldName = MyFieldUtils.getAnnotationValue(psiAnnotation, "fieldName");
            String methed = MyFieldUtils.getAnnotationValue(psiAnnotation, "methed");
            boolean addMethod = true;
            if (StringUtils.isNotBlank(methed)) {
                addMethod = new Boolean(methed);
            }

            if ("".equals(fieldName) == false) {
                List<PsiElement> psiElementList = new ArrayList<>();
                if (addMethod == true) {
                    PsiType psiType = MyFieldUtils.getPsiType(psiClass,"java.lang.String");
                    String methodName = "get" + fieldName;
                    //PsiType.VOID
                    PsiMethod psiMethod = MyFieldUtils.createCacheMethod(psiClass, methodName, null, psiType);
                    psiElementList.add(psiMethod);

                    methodName = "set" + fieldName;
                    List<PsiParameter> parameterList = Lists.newArrayList();
                    LightParameter lightParameter = new LightParameter(fieldName,psiType,psiClass);
                    parameterList.add(lightParameter);
                    psiMethod = MyFieldUtils.createCacheMethod(psiClass, methodName, parameterList, PsiType.VOID);
                    psiElementList.add(psiMethod);

                    return (List<Psi>) psiElementList;
                }
            }
        }
        return emptyResult;
    }
}
package com.wangxb.plugin.utils;

import com.intellij.lang.java.JavaLanguage;
import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightFieldBuilder;
import com.intellij.psi.impl.light.LightMethodBuilder;
import com.intellij.psi.impl.light.LightModifierList;
import com.intellij.psi.util.CachedValuesManager;
import com.sun.org.apache.xpath.internal.operations.Bool;
import com.wangxb.plugin.MyLightFieldBuilder;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.ObjectUtils;

import java.lang.reflect.Type;
import java.util.List;

public class MyFieldUtils {
    static public void addField(PsiJavaFile psiJavaFile,String annotaionName){

        PsiClass[] psiClasses = psiJavaFile.getClasses();
        if (null == psiClasses) {
            return;
        }
        for(PsiClass psiClass : psiClasses) {
            PsiAnnotation psiAnnotation = psiClass.getAnnotation(annotaionName);
            if (psiAnnotation == null) {
                continue;
            }
            String fieldName = getAnnotationValue(psiAnnotation,"fieldName");

            if ("".equals(fieldName) == true) {
                break;
            }

            boolean add = haveField(psiClass,fieldName);
            if (add) {
                createField(psiClass,fieldName);
            }


            boolean method = new Boolean(getAnnotationValue(psiAnnotation,"methed"));
            if (method == true){
                String methodName = "get" + fieldName;
                PsiType returnType = getPsiType(psiClass,"java.lang.String");
                add = haveMethod(psiClass,methodName,null,returnType);
                if (add) {
                    createMethod(psiClass,methodName,null,returnType);
                }
            }

            break;

        }
    }

    static public boolean haveAnnotation(PsiJavaFile psiJavaFile,String annotaionName){
        boolean bRet = false;
        PsiClass[] psiClasses = psiJavaFile.getClasses();
        if (null == psiClasses) {
            return bRet;
        }
        for(PsiClass psiClass : psiClasses) {
            PsiAnnotation psiAnnotation = getAnnotation(psiClass,annotaionName);
            if (psiAnnotation != null){
                bRet = true;
                break;
            }
        }
        return bRet;
    }

    static public PsiAnnotation getAnnotation(PsiClass psiClass,String annotaionName){
        PsiAnnotation psiAnnotation = psiClass.getAnnotation(annotaionName);
        return psiAnnotation;
    }

    static public PsiField createField(PsiClass psiClass,String fieldName){
        Project project = psiClass.getProject();
        PsiElementFactory psiElementFactory = JavaPsiFacade.getElementFactory(project);
        PsiType stringPsiType = psiElementFactory.createTypeFromText("java.lang.String", null);
        PsiField psiField = psiElementFactory.createField(fieldName, stringPsiType);
        psiField.getModifierList().setModifierProperty(PsiModifier.PUBLIC,true);

        WriteCommandAction.runWriteCommandAction(project, new Runnable() {
            @Override
            public void run() {
                psiClass.add(psiField);
            }
        });

        return psiField;
    }
    
    static public PsiField createCacheField(PsiClass psiClass,String fieldName,PsiType psiType){
        PsiManager psiManager = psiClass.getContainingFile().getManager();
        LightFieldBuilder lightFieldBuilder = new LightFieldBuilder(psiManager,fieldName, psiType);

        LightModifierList lightModifierList = (LightModifierList) lightFieldBuilder.getModifierList();
        lightModifierList.addModifier(PsiModifier.PUBLIC);

        lightFieldBuilder.setContainingClass(psiClass);

        return lightFieldBuilder;
    }

    static public String getAnnotationValue(PsiAnnotation psiAnnotation,String name){
        String value = null;
        PsiAnnotationParameterList psiAnnotationParameterList = psiAnnotation.getParameterList();
        for (PsiNameValuePair psiNameValuePair : psiAnnotationParameterList.getAttributes()) {
            String attributeName = psiNameValuePair.getAttributeName();

            if (attributeName.equals(name) == false) {
                continue;
            }
            value = psiNameValuePair.getLiteralValue();
            break;
        }
        return value;
    }

    static public boolean haveField(PsiClass psiClass,String fieldName){
        boolean bRet = false;
        PsiField[] psiFields = psiClass.getAllFields();
        PsiField lastPsiField = null;
        for (PsiField psiField : psiFields) {
            if (fieldName.equals(psiField.getName())) {
                bRet = true;
                break;
            }
        }
        return bRet;
    }

    static public boolean haveMethod(PsiClass psiClass,String methodName,List<PsiParameter> parameterList,PsiType returnType){
        boolean bRet = false;
        PsiMethod[] psiMethods = psiClass.getAllMethods();
        for (PsiMethod psiMethod : psiMethods) {
            if (methodName.equals(psiMethod.getName())) {
                PsiType psiType = psiMethod.getReturnType();
                if (psiType.equals(returnType) == false){
                    return bRet;
                }
                PsiParameterList psiParameterList = psiMethod.getParameterList();

                if (ObjectUtils.isEmpty(parameterList)){
                    parameterList = Lists.newArrayList();
                }

                if (parameterList.size() != psiParameterList.getParameters().length){
                    return bRet;
                }

                int i = 0;
                for(PsiParameter parameter : parameterList){
                    PsiParameter psiParameter = psiParameterList.getParameter(i);
                    if (parameter.getName().equals(psiParameter.getName()) == false){
                        return bRet;
                    }

                    if (parameter.getType().equals(psiParameter.getType()) == false){
                        return bRet;
                    }

                    i++;

                }
                bRet = true;
                break;
            }
        }
        return bRet;
    }

    static public PsiMethod createMethod(PsiClass psiClass,String methodName,List<PsiParameter> parameterList,PsiType returnType){
        Project project = psiClass.getProject();
        PsiElementFactory psiElementFactory = JavaPsiFacade.getElementFactory(project);

        PsiMethod psiMethod = psiElementFactory.createMethod(methodName, returnType);
        psiMethod.getModifierList().setModifierProperty(PsiModifier.PUBLIC,true);

        WriteCommandAction.runWriteCommandAction(project, new Runnable() {
            @Override
            public void run() {
                psiClass.add(psiMethod);
            }
        });

        return psiMethod;
    }

    static public PsiMethod createCacheMethod(PsiClass psiClass,String methodName,List<PsiParameter> parameterList,PsiType returnType) {
        PsiManager psiManager = psiClass.getContainingFile().getManager();

        LightMethodBuilder lightMethodBuilder = new LightMethodBuilder(psiManager, JavaLanguage.INSTANCE, methodName);
        lightMethodBuilder.addModifier(PsiModifier.PUBLIC);
        lightMethodBuilder.setContainingClass(psiClass);
        if (ObjectUtils.isNotEmpty(parameterList)) {
            for (PsiParameter psiParameter : parameterList) {
                lightMethodBuilder.addParameter(psiParameter.getName(), psiParameter.getType());
            }
        }
        lightMethodBuilder.setMethodReturnType(returnType);
        lightMethodBuilder.setContainingClass(psiClass);

        return lightMethodBuilder;
    }

    static public PsiType getPsiType(PsiClass psiClass,String type){
        Project project = psiClass.getProject();
        PsiElementFactory psiElementFactory = JavaPsiFacade.getElementFactory(project);
        PsiType psiType = psiElementFactory.createTypeFromText(type, null);
        return psiType;
    }
}

2.3 代码效果

代码中没有abc属性

但选择是会出现abc的属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值