代码补全、检查与 Quick Fix¶
编辑器功能是插件最常见的价值入口。本章覆盖三类常用能力:代码补全、代码检查、Quick Fix。
代码补全¶
IntelliJ Platform 中常见补全有两种实现方式。
| 方式 | 适合场景 | 入口 |
|---|---|---|
| Reference Completion | 基于引用解析的基础补全 | PsiReference.getVariants() |
| Contributor Completion | 更可控的补全、关键词补全、类型匹配补全 | CompletionContributor |
CompletionContributor 示例¶
class MyCompletionContributor : CompletionContributor() {
init {
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement().withLanguage(JavaLanguage.INSTANCE),
object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addElement(
LookupElementBuilder.create("myKeyword")
.withTypeText("example")
.bold()
)
}
}
)
}
}
注册:
<extensions defaultExtensionNs="com.intellij">
<completion.contributor
language="JAVA"
implementationClass="com.example.MyCompletionContributor"/>
</extensions>
补全建议:
- 不依赖索引的补全可以标记为 Dumb Aware。
- 显示项使用
LookupElementBuilder,可以设置图标、尾部文本、类型文本和插入处理器。 - 模式匹配针对光标附近的叶子 PSI Element;匹配父节点时使用
withParent()或withSuperParent()。
代码检查¶
代码检查用于静态分析,不实际执行用户代码。局部检查通常一次处理一个文件,并可在用户编辑时实时运行。
最小组成:
LocalInspectionTool或特定语言的基类。- PSI Visitor,用于遍历目标语法节点。
ProblemsHolder,用于登记问题。- 可选
LocalQuickFix,用于修复问题。 inspectionDescriptions/<ShortName>.html,用于设置页展示说明。
LocalInspectionTool 示例¶
class MyStringComparisonInspection : LocalInspectionTool() {
override fun buildVisitor(
holder: ProblemsHolder,
isOnTheFly: Boolean
): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitBinaryExpression(expression: PsiBinaryExpression) {
val op = expression.operationTokenType
if (op == JavaTokenType.EQEQ || op == JavaTokenType.NE) {
holder.registerProblem(
expression.operationSign,
"String comparison should use equals()",
ReplaceWithEqualsQuickFix()
)
}
}
}
}
}
注册:
<extensions defaultExtensionNs="com.intellij">
<localInspection
language="JAVA"
shortName="MyStringComparison"
displayName="String comparison uses =="
groupName="Probable bugs"
enabledByDefault="true"
level="WARNING"
implementationClass="com.example.MyStringComparisonInspection"/>
</extensions>
Quick Fix¶
Quick Fix 应尽量小而确定。它接收问题位置,在 Write Command 中修改 PSI。
class ReplaceWithEqualsQuickFix : LocalQuickFix {
override fun getFamilyName(): String = "Replace with equals()"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.psiElement ?: return
WriteCommandAction.runWriteCommandAction(project) {
// create replacement PSI and replace the old expression
}
}
}
检查描述文件¶
路径约定:
src/main/resources/inspectionDescriptions/MyStringComparison.html
HTML 内容应解释:
- 检查发现什么问题。
- 为什么这是问题。
- Quick Fix 会做什么。
- 哪些情况可能误报。