使用IntelliJ IDEA想必大家都有使用过代码自动补全功能,如输入ab,会自动触发补全,提供相应的补全建议列表。作为有追求的程序员,有没有想过这样的功能是如何实现的?本节将详细介绍如何实现一个类似的代码自动补全插件。
在IntelliJ IDEA插件开发中,CompletionContributor是一个关键的API,它允许开发者为特定语言的代码编辑器添加代码补全功能。本节将详细介绍如何使用CompletionContributor实现代码补全功能,并提供完整的示例代码和解释,理解如何使用该API来创建一个简单的代码补全插件。
一.环境准备
为了确保项目的兼容性,本章节使用以下版本:
IntelliJ IDEA: 2020.1.4
JDK: 1.8
Gradle: 6.1
如果不知道如何搭建IntelliJ IDEA插件开发环境,请阅读【IntelliJ IDEA插件开发-开发环境搭建】章节内容。
二.CompletionContributor介绍
CompletionContributor 是一个IntelliJ IDEA插件API的类,它允许开发者定义代码补全的行为。通过继承CompletionContributor,可以设置触发补全的条件和提供相应的补全建议。这些补全建议会在编辑器中显示,帮助开发者快速编写代码。
代码补全的两种主要类型:
Basic Completion:标准的代码补全,一般会在用户输入时自动显示选项。
Smart Completion:根据上下文提供更为智能的代码补全。
本篇将实现一个基本的代码补全功能。
三.新建项目
首先,在IntelliJ IDEA中创建一个新的插件项目,并进行基础设置。
创建插件项目:打开IntelliJ IDEA,选择Create New Project。
填写项目基本信息:这里随意命名。
修改org.jetbrains.intellij插件版本:如果默认生成的build.gradle文件中Gradle版本和org.jetbrains.intellij插件版本不兼容导致Build窗口输出报错,打开build.gradle文件将org.jetbrains.intellij版本改为0.7.3即解决。Gradle版本和org.jetbrains.intellij插件兼容版本,请至gradle-intellij-plugin插件的releases页面查看。
四.编写插件代码
在这个步骤中,将编写CompletionContributor子类来定义补全的逻辑。
步骤 1:创建CompletionContributor子类
在src/main/java下创建MyCompletionContributor.java文件,并让它继承CompletionContributor。
代码解读:
CompletionType.BASIC:指定为基本补全类型。
PlatformPatterns.psiElement():匹配所有的PsiElement(表示源代码中的元素),即允许插件在所有位置触发补全。
addCompletions 方法:定义补全的内容。resultSet.addElement用于添加选项。在这里,我们简单地添加了两个字符串 "HelloWorld" 和 "HelloPlugin" 作为补全建议。
步骤 2:注册CompletionContributor
在plugin.xml中注册MyCompletionContributor类。
language="JAVA"表示我们的补全功能将应用于Java语言。
五.测试插件
运行插件:在IntelliJ IDEA中选择 Run > Run 'Plugin'。
打开测试项目:在弹出的新窗口中打开或新建一个项目。
测试补全:在Java文件中输入任意字符,例如"H"或者"Hell",你会看到"HelloWorld"和"HelloPlugin" 出现在候选项列表中,通过上下键可选择,回车自动选中并替换
六.动态补全
目前实现了一个简单的代码补全,接下来进行一些改进,实现可根据上下文进行动态补全。大家都用过IntelliJ IDEA中的属性自动提示补全功能,如下图。
接下来将实现一个类似的功能,根据定义的属性实现动态补全,代码调整如下:
如果你使用以上代码你会发现它编译报错,找不到PsiVariable和PsiTreeUtil,这是因为它需要用到IntelliJ Platform Plugin SDK进行编译,点击菜单栏的 File -> Project Structure -> Project Settings -> Project -> Project SDK ,选择IntelliJ Platform Plugin SDK版本。如果未设置过IntelliJ Platform Plugin SDK,请阅读【IntelliJ IDEA插件开发-开发环境搭建】章节内容。
设置完IntelliJ Platform Plugin SDK后,此时编译不会报错了,但如果想跑起来需要在plugin.xml中添加对 com.intellij.modules.java 的依赖,这是因为PsiVariable是Java相关的类,同时还需要在build.gradle文件中增加Java插件依赖,确保项目在构建时包含Java插件所需的依赖项, build.gradle完整代码如下:
plugin.xml代码如下:
接下来运行插件:选择Run > Run 'Plugin',代码运行效果如下:
如果你想实现右侧的文字“我是动态生成的”换成对应变量的数据类型,可以使用variable.getType().getPresentableText()替换,通过PsiVariable获取类型,具体代码如下:
LookupElementBuilder 是IntelliJ IDEA插件开发API中的一个核心类,用于构建代码补全建议的展示。以下是 LookupElementBuilder 类中一些常用且实用的方法:
create(String lookupString)
这是静态方法,用于生成包含补全字符串的基础 LookupElementBuilder 对象。
示例:LookupElementBuilder.create("myCompletionItem")
withTypeText(String typeText)
在补全建议右侧显示类型信息或描述性文本,通常用来标注该项的类型或来源。
示例:withTypeText("int") 会在补全项右侧显示“int”文本。
withIcon(Icon icon)
为补全项添加图标。通常用于在补全项左侧添加图标,比如类、方法或变量的图标。
示例:withIcon(AllIcons.Nodes.Method)。
withTailText(String tailText, boolean grayed)
在补全项后添加附加文本,例如参数或其他信息。grayed 参数表示文本是否显示为灰色。
示例:withTailText("(param1, param2)", true) 在补全项后以灰色显示 (param1, param2)。
bold()
让补全项的显示文本加粗。适合用于推荐性较高或特别重要的选项。
示例:bold()。
withInsertHandler(InsertHandler<? super LookupElement> handler)
定义插入操作的处理逻辑,例如在选择补全项后添加括号、光标移动等操作。
示例:withInsertHandler((context, item) -> { /* 插入处理逻辑 */ })。
withPresentableText(String presentableText)
自定义补全项的显示文本,不改变实际插入的内容。适合用在用户看到的内容和实际插入内容不同的场景。
示例:withPresentableText("displayedText")。
withAutoCompletionPolicy(AutoCompletionPolicy policy)
控制自动补全策略。可以设置为 AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE,使该项在自动补全时直接插入。
示例:withAutoCompletionPolicy(AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE)。
withPriority(double priority)
设置补全项的优先级,优先级越高的项将显示在补全列表的顶部。
示例:withPriority(10.0)。
withCaseSensitivity(boolean caseSensitive)
设置补全项是否区分大小写。适用于特定语言或环境要求区分大小写的情况。
示例:withCaseSensitivity(false)。
这些方法可以配合使用,使补全建议更符合用户预期并提升用户体验。
本节实现了一个基础的代码补全功能,并展示了如何使用CompletionContributor来扩展和定制补全行为。完成插件开发后,你可以进一步扩展补全功能,实现更复杂的逻辑,满足实际项目需求。