文章目录

  • 前言
  • 一、Quick Fix是什么?
  • 二、开发quick fix 通常包含两部分
    • 1. Annotator
    • 2.quick fix
    • 3. FixAnnotationEnum
    • 4、注册插件
  • 三、演示
  • 总结

前言

以下代码为开发idea quick fix功能插件演示代码,该代码实现的功能是:对于标注有SpingMVC中的 GetMappingPostMappingPatchMappingPutMappingDeleteMappingRequestMapping等注解等方法,若没有同时标注LevenApi注解,则在方法名上会出现警告,提示开发者加上LevenApi注解,此时使用quick fix的功能即可在方法上生成LevenApi注解。


一、Quick Fix是什么?

quick fix就是快速修复的意思,在idea编辑代码的时候,当我们输入一些违法或者是不安全(或是不推荐)的代码时,idea会自动帮我们检测出来,并使用红色或黄色波浪线提示我们修改代码。对于有些非法或者是不推荐的代码,idea能够推测出正确或者是被推荐的代码时,就会给我们提供一个快速修复的功能,这个功能就是quick fix。
而前面的检测行为则是由Annotator功能完成的,因此quick fix通常是跟着Annotator出现的,而有Annotator却不一定有quick fix(就是没有推荐修改的情况)。



以上图片演示就是常见的quick fix场景——导入类。红色方块就是Annotator,提示“无法解析BigDecimal”;橙色框则是quick fix,通过点击Import class或者使用快捷键(Windows是alt + enter,Mac是option + enter)快速导入BigDecimal类。


二、开发quick fix 通常包含两部分

1. Annotator

筛选出需要quick fix的代码段:校验标注有SpringMVC mapping相关注解的方法是否同时标注有@LevenApi注解,如果没有则在这个方法名上添加Annotator,提示需要加上@LevenApi注解

package run.leven.fix;import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;/*** Create By  leven [2021/12/21 9:34 下午]*/
public class LevenApiAnnotator implements Annotator {private static final Set<String> MAPPING_NAME_SET;static {MAPPING_NAME_SET = new HashSet<>(Arrays.asList(FixAnnotationEnum.PatchMapping.getQualifiedName(),FixAnnotationEnum.PutMapping.getQualifiedName(),FixAnnotationEnum.PostMapping.getQualifiedName(),FixAnnotationEnum.GetMapping.getQualifiedName(),FixAnnotationEnum.RequestMapping.getQualifiedName(),FixAnnotationEnum.DeleteMapping.getQualifiedName()));}@Overridepublic void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {final Project project = element.getProject();// 项目或者引入的依赖包含LevenApi时才处理if (JavaPsiFacade.getInstance(project).findClass(FixAnnotationEnum.LevenApi.getQualifiedName(), GlobalSearchScope.allScope(project)) == null){return;}// 仅对Java方法处理if (!(element instanceof PsiMethod)){return;}// 仅对Java文件处理if (!(element.getContainingFile() instanceof PsiJavaFile)){return;}final PsiMethod psiMethod = (PsiMethod) element;final PsiAnnotation[] methodAnnotations = psiMethod.getAnnotations();PsiAnnotation mappingAnnotation = null;PsiAnnotation levenApiAnnotation = null;for (PsiAnnotation methodAnnotation : methodAnnotations) {if (MAPPING_NAME_SET.contains(methodAnnotation.getQualifiedName())){mappingAnnotation = methodAnnotation;}else if (FixAnnotationEnum.LevenApi.getQualifiedName().equals(methodAnnotation.getQualifiedName())){levenApiAnnotation = methodAnnotation;}}// 方法上标注了spring mvc相关的mapping注解时,如果同时不存在@LevenApi注解,则quick fix生效if (mappingAnnotation != null && levenApiAnnotation == null && psiMethod.getNameIdentifier() != null){holder.newAnnotation(HighlightSeverity.WARNING, "添加@LevenApi注解").range(psiMethod.getNameIdentifier()).highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).withFix(new LevenApiQuickFix(psiMethod)).create();}}
}

2.quick fix

quick fix处理:在方法上创建@LevenApi注解

package run.leven.fix;import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.codeInspection.util.IntentionFamilyName;
import com.intellij.codeInspection.util.IntentionName;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;/*** Create By  leven [2021/12/21 10:30 下午]*/
public class LevenApiQuickFix extends BaseIntentionAction {private final PsiMethod psiMethod;public LevenApiQuickFix(PsiMethod psiMethod) {this.psiMethod = psiMethod;}@Overridepublic @IntentionName @NotNull String getText() {return "Create @LevenApi";}@Overridepublic @NotNull @IntentionFamilyName String getFamilyName() {return "Create @LevenApi";}@Overridepublic boolean isAvailable(@NotNull Project project, Editor editor, PsiFile psiFile) {return true;}@Overridepublic void invoke(@NotNull Project project, Editor editor, PsiFile psiFile) throws IncorrectOperationException {// GlobalSearchScope.projectScope(project) 为allScopefinal PsiClass levenApiClass = JavaPsiFacade.getInstance(project).findClass(FixAnnotationEnum.LevenApi.getQualifiedName(), GlobalSearchScope.projectScope(project));if (levenApiClass != null){ApplicationManager.getApplication().invokeLater(() -> WriteCommandAction.runWriteCommandAction(project, () ->{final PsiClass containingClass = psiMethod.getContainingClass();if (containingClass == null){return;}final PsiImportList importList = ((PsiJavaFile) containingClass.getContainingFile()).getImportList();if (importList == null){return;}importLevenApiClass(project, levenApiClass, importList);psiMethod.getModifierList().addAnnotation("LevenApi(name = \"" + psiMethod.getName() + "\")");}));}}private void importLevenApiClass(@NotNull Project project, PsiClass levenApiClass, PsiImportList importList) {boolean notExistLevenApiImportStatement = true;for (PsiImportStatement importStatement : importList.getImportStatements()) {if (FixAnnotationEnum.LevenApi.getQualifiedName().equals(importStatement.getQualifiedName())){notExistLevenApiImportStatement = false;}}if (notExistLevenApiImportStatement){final PsiImportStatement levenApiImportStatement = JavaPsiFacade.getElementFactory(project).createImportStatement(levenApiClass);importList.add(levenApiImportStatement);}}
}

3. FixAnnotationEnum

package run.leven.fix;/*** Create By  leven [2021/12/21 9:37 下午]*/
public enum FixAnnotationEnum {GetMapping("GetMapping", "org.springframework.web.bind.annotation.GetMapping"),PostMapping("PostMapping", "org.springframework.web.bind.annotation.PostMapping"),PutMapping("PutMapping", "org.springframework.web.bind.annotation.PutMapping"),PatchMapping("PatchMapping", "org.springframework.web.bind.annotation.PatchMapping"),RequestMapping("RequestMapping", "org.springframework.web.bind.annotation.RequestMapping"),DeleteMapping("DeleteMapping", "org.springframework.web.bind.annotation.DeleteMapping"),LevenApi("LevenApi", "run.leven.fix.LevenApi");FixAnnotationEnum(String shortName, String qualifiedName) {this.shortName = shortName;this.qualifiedName = qualifiedName;}private String shortName;private String qualifiedName;public String getShortName() {return shortName;}public String getQualifiedName() {return qualifiedName;}
}

4、注册插件

在plugin.xml文件的extensions标签下添加如下annotator标签。这里的language属性指的是自己的定义Annotator对什么语言生效,如果想对xml文件生效,则可以把language="JAVA"修改为language="XML"

    <extensions defaultExtensionNs="com.intellij"><annotator language="JAVA" implementationClass="run.leven.fix.LevenApiAnnotator"/></extensions>

三、演示

如上图,加有@GetMapping注解的方法上没有@LevenApi注解,此时方法名上有红色波浪线,且提示“添加@LevenApi注解”。当点击“Create @LevenApi”时,会在这个方法上生成@LevenApi(value = "hello"),如下图:


总结

【IDEA插件开发】Quick Fix 快速修复插件开发相关推荐

  1. 捷径和妙方quick fix and silver bullet

    3月24日美国总统奥巴马在白宫的新闻发布会上发表讲话时表示,政府已制定综合经济战略,美国将开始看到进展的迹象,但需要时间和耐心.在回应3.55万亿美元预算遭国会质疑时,奥巴马表示该预算与美国经济复苏是 ...

  2. java怎么设置快速修复键_Java开发环境之------MyEclipse快捷键和排除错误第一选择ctrl+1(***重点***:ctrl+1,快速修复---有点像vs中的快速using...

    [摘要:1,MyEclipse快速键设置装备摆设方式 2,经常使用快速键 : (1),alt+/ //内容提醒, 近似于vs中的ctrl+j ,即单词提醒,输进单词的前几个字母,然后提醒大概的单词. ...

  3. 数仓备机DN重建:快速修复你的数仓DN单点故障

    摘要:大规模分布式系统中的故障无法避免.当DN发生单点故障时,恢复手段有哪些,又是如何恢复的,本节重点介绍操作gs_ctl build是如何修复DN单点故障的. 本文分享自华为云社区<华为云数仓 ...

  4. 苹果充电线android头断了,【黑科技数据线!断了都能用!】 苹果安卓数据线 快速修复永不断线...

    原标题:[黑科技数据线!断了都能用!] 苹果安卓数据线 快速修复永不断线 这个世界上最爽的事情是什么呢? 是躺在床上玩手机 那么最痛苦的事情是什么呢 玩到手机没电的时候数据线坏了! 这说到数据线有什么 ...

  5. 快速修复 bug 的技巧?初学者的痛点,教你一招搞定!

    前言 写 bug 和改 bug 是每个程序员都绕不过的话题,在编写代码的过程中,相信大家肯定遇到过这种情况:代码编译通过,没有语法错误,但是运行结果却报错或和预期不同,反复检查了很多遍,仍然无法修复错 ...

  6. mysql的check出错_如何利用myisamchk和mysqlcheck快速修复损坏的MySQL数据库

    如何利用myisamchk和mysqlcheck快速修复损坏的MySQL数据库 由于服务器的数据库硬盘空间满了,由于大量写入数据失败导致了出现"Duplicate entry '' for ...

  7. 彻底关闭win10更新自动更新 卸载win10自带杀毒软件 新增联想软件 lenovo quick fix

    联想 lenovo quick fix 下载地址 https://box.lenovo.com/l/t5dQKH 1.开始 运行 输入services.msc. 2.找到windows update, ...

  8. 快速修复IE浏览器方案

    快速修复浏览器方案(请活学活用以下方法--根据具体情况决定做哪些) 1.打开浏览器,点"工具"→"管理加载项"那里禁用所有可疑插件,或者你能准确知道没问题的保留 ...

  9. HD Tune结合硬盘再生器HDDREG快速修复硬盘错误

    最近用HD Tune检查硬盘状态,结果显示(C5) 当前待映射扇区数显示黄色的警告状态 赶紧对硬盘做了备份,果然出现了某几个文件损坏读取失败的情况. 网上查了资料,发现HDDREG可以修复硬盘,但实际 ...

最新文章

  1. 论文小综 | 知识图谱中的复杂查询问答
  2. 莫比乌斯带catia建模_独家教程 | 循环曲面“莫比乌斯”,康石石教你Rhino“3步”快速打造...
  3. 【高并发】JUC中原子类介绍
  4. 拿什么来拯救你,电视!
  5. 自定义办法设置 localStorage 过期时间
  6. 数据库原理与应用 基于SQL Server 2005pdf
  7. 关于ipcam的UPnP或NAT的知识
  8. golang xorm cmd xorm工具使用 reverse 反转一个数据库结构,生成代码
  9. 地图 显示 动态轨迹_野外探路必备神器——奥维互动地图浏览器
  10. 9种常见的反爬虫策略思路
  11. 论文解读:MOEA/D-TPN
  12. Mysql性能优化:什么是索引下推?
  13. 19 枚举类型 Enumerated
  14. 【阿里巴巴/腾旭】mysql面试题汇总
  15. 深度学习之epoch
  16. C语言-第8章-基本数据类型-v2
  17. WiFi_combo模组功耗数据
  18. pycocotools报错 if type(resFile) == str or type(resFile) == unicode: NameError: name ‘unicode‘ is
  19. Python的IDEL增加清屏功能
  20. 转ios icon及默认图片等

热门文章

  1. 搭建私人影院-超详细教程
  2. as打包报 MissingTranslation 的解决办法
  3. SurfaceFlinger系列<一>
  4. JXL 对excle 操作(单元格合并,列宽,格式等)《二》
  5. 美团和饿了么再起战火,前者补贴更高,市场份额将进一步集中
  6. Android ComponentName 学习
  7. 重装WinXP系统之前 病毒库的备份方法
  8. PHP sm2 国密扩展
  9. 我的游戏学习日志47——游戏交互设计(3)
  10. React-Native清除缓存汇总