Skip to content

Commit ff8b0ea

Browse files
committed
feat(completion): add HobbitHole key and value completion providers #379
1 parent 0148bfd commit ff8b0ea

File tree

5 files changed

+225
-7
lines changed

5 files changed

+225
-7
lines changed

exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/completion/DevInCompletionContributor.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import com.intellij.patterns.PlatformPatterns
1212
import com.intellij.patterns.PsiElementPattern
1313
import com.intellij.psi.PsiElement
1414
import com.intellij.psi.tree.IElementType
15+
import com.phodal.shirelang.completion.provider.WhenConditionCompletionProvider
16+
import com.phodal.shirelang.completion.provider.WhenConditionFunctionCompletionProvider
1517

1618
class DevInCompletionContributor : CompletionContributor() {
1719
init {
@@ -26,13 +28,11 @@ class DevInCompletionContributor : CompletionContributor() {
2628
extend(CompletionType.BASIC, identifierAfter(DevInTypes.VARIABLE_START), AgentToolOverviewCompletion())
2729
extend(CompletionType.BASIC, identifierAfter(DevInTypes.COMMAND_START), BuiltinCommandCompletion())
2830

29-
// extend(CompletionType.BASIC, hobbitHoleKey(), HobbitHoleKeyCompletion())
30-
// extend(CompletionType.BASIC, hobbitHolePattern(), HobbitHoleValueCompletion())
31-
//
32-
// extend(CompletionType.BASIC, identifierAfter(DevInTypes.PIPE), PostProcessorCompletion())
33-
//
34-
// extend(CompletionType.BASIC, whenConditionPattern(), WhenConditionCompletionProvider())
35-
// extend(CompletionType.BASIC, whenConditionFuncPattern(), WhenConditionFunctionCompletionProvider())
31+
extend(CompletionType.BASIC, hobbitHoleKey(), HobbitHoleKeyCompletion())
32+
extend(CompletionType.BASIC, hobbitHolePattern(), HobbitHoleValueCompletion())
33+
extend(CompletionType.BASIC, identifierAfter(DevInTypes.PIPE), PostProcessorCompletion())
34+
extend(CompletionType.BASIC, whenConditionPattern(), WhenConditionCompletionProvider())
35+
extend(CompletionType.BASIC, whenConditionFuncPattern(), WhenConditionFunctionCompletionProvider())
3636

3737
// command completion
3838
extend(
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package cc.unitmesh.devti.language.completion
2+
3+
import cc.unitmesh.devti.AutoDevIcons
4+
import cc.unitmesh.devti.language.ast.HobbitHole
5+
import com.intellij.codeInsight.completion.CompletionParameters
6+
import com.intellij.codeInsight.completion.CompletionProvider
7+
import com.intellij.codeInsight.completion.CompletionResultSet
8+
import com.intellij.codeInsight.completion.PrioritizedLookupElement
9+
import com.intellij.codeInsight.lookup.LookupElementBuilder
10+
import com.intellij.util.ProcessingContext
11+
12+
class HobbitHoleKeyCompletion : CompletionProvider<CompletionParameters>() {
13+
override fun addCompletions(
14+
parameters: CompletionParameters,
15+
context: ProcessingContext,
16+
result: CompletionResultSet,
17+
) {
18+
HobbitHole.keys().forEach {
19+
val element = LookupElementBuilder.create(it.key)
20+
.withIcon(AutoDevIcons.AI_COPILOT)
21+
.withTypeText(it.value, true)
22+
23+
result.addElement(PrioritizedLookupElement.withPriority(element, 0.0))
24+
}
25+
}
26+
27+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package cc.unitmesh.devti.language.completion
2+
3+
import cc.unitmesh.devti.AutoDevIcons
4+
import cc.unitmesh.devti.custom.team.InteractionType
5+
import cc.unitmesh.devti.devins.ShireActionLocation
6+
import cc.unitmesh.devti.devins.post.PostProcessor
7+
import cc.unitmesh.devti.language.ast.HobbitHole
8+
import cc.unitmesh.devti.language.middleware.select.SelectElementStrategy
9+
import com.intellij.codeInsight.completion.CompletionParameters
10+
import com.intellij.codeInsight.completion.CompletionProvider
11+
import com.intellij.codeInsight.completion.CompletionResultSet
12+
import com.intellij.codeInsight.completion.InsertionContext
13+
import com.intellij.codeInsight.lookup.LookupElement
14+
import com.intellij.codeInsight.lookup.LookupElementBuilder
15+
import com.intellij.psi.util.PsiTreeUtil
16+
import com.intellij.util.ProcessingContext
17+
18+
class HobbitHoleValueCompletion : CompletionProvider<CompletionParameters>() {
19+
private val HOBBIT = "hobbit"
20+
21+
override fun addCompletions(
22+
parameters: CompletionParameters,
23+
context: ProcessingContext,
24+
result: CompletionResultSet,
25+
) {
26+
val position = parameters.originalPosition ?: parameters.position
27+
val psiElement = PsiTreeUtil.prevVisibleLeaf(position)?.let {
28+
PsiTreeUtil.prevLeaf(it, true)
29+
} ?: return
30+
31+
when (psiElement.text) {
32+
HOBBIT -> {
33+
hobbitHeroes(result)
34+
}
35+
36+
HobbitHole.ACTION_LOCATION -> {
37+
ShireActionLocation.all().forEach {
38+
result.addElement(
39+
LookupElementBuilder
40+
.create(it.location)
41+
.withIcon(AutoDevIcons.AI_COPILOT)
42+
.withInsertHandler { context, _ ->
43+
context.document.insertString(context.startOffset, " ")
44+
}
45+
.withTypeText(it.description, true)
46+
)
47+
}
48+
}
49+
50+
HobbitHole.INTERACTION -> {
51+
InteractionType.entries.forEach {
52+
result.addElement(
53+
LookupElementBuilder
54+
.create(it.name)
55+
.withIcon(AutoDevIcons.AI_COPILOT)
56+
.withInsertHandler { context, _ ->
57+
context.document.insertString(context.startOffset, " ")
58+
}
59+
.withTypeText(it.description, true)
60+
)
61+
}
62+
}
63+
64+
HobbitHole.STRATEGY_SELECTION -> {
65+
SelectElementStrategy.all().forEach {
66+
result.addElement(
67+
LookupElementBuilder
68+
.create(it)
69+
.withIcon(AutoDevIcons.AI_COPILOT)
70+
.withInsertHandler { context, _ ->
71+
context.document.insertString(context.startOffset, " ")
72+
}
73+
)
74+
}
75+
}
76+
77+
HobbitHole.ON_STREAMING_END -> {
78+
PostProcessor.allNames().forEach {
79+
result.addElement(
80+
LookupElementBuilder
81+
.create(it)
82+
.withIcon(AutoDevIcons.AI_COPILOT)
83+
.withInsertHandler { context: InsertionContext, item: LookupElement ->
84+
val offset = context.editor.caretModel.offset
85+
val startOffset = offset - item.lookupString.length
86+
context.document.deleteString(startOffset, offset)
87+
// insert value inside `{ }`, for example, if user select $demo, the insert will be `{ $demo }`
88+
val value = " { $it }"
89+
context.document.insertString(context.startOffset, value)
90+
91+
context.editor.caretModel.moveToOffset(startOffset + value.length - 2)
92+
}
93+
)
94+
}
95+
}
96+
}
97+
}
98+
99+
private fun hobbitHeroes(result: CompletionResultSet) {
100+
listOf("Frodo", "Sam", "Merry", "Pippin").forEach {
101+
result.addElement(LookupElementBuilder.create(it))
102+
}
103+
}
104+
105+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package cc.unitmesh.devti.language.completion
2+
3+
import cc.unitmesh.devti.AutoDevIcons
4+
import cc.unitmesh.devti.devins.post.PostProcessor
5+
import com.intellij.codeInsight.completion.CompletionParameters
6+
import com.intellij.codeInsight.completion.CompletionProvider
7+
import com.intellij.codeInsight.completion.CompletionResultSet
8+
import com.intellij.codeInsight.completion.InsertionContext
9+
import com.intellij.codeInsight.lookup.LookupElement
10+
import com.intellij.codeInsight.lookup.LookupElementBuilder
11+
import com.intellij.util.ProcessingContext
12+
13+
class PostProcessorCompletion : CompletionProvider<CompletionParameters>() {
14+
override fun addCompletions(
15+
parameters: CompletionParameters,
16+
context: ProcessingContext,
17+
result: CompletionResultSet,
18+
) {
19+
PostProcessor.allNames().forEach {
20+
result.addElement(
21+
LookupElementBuilder
22+
.create(it)
23+
.withIcon(AutoDevIcons.AI_COPILOT)
24+
.withInsertHandler { context: InsertionContext, item: LookupElement ->
25+
26+
}
27+
)
28+
}
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.phodal.shirelang.completion.provider
2+
3+
import cc.unitmesh.devti.AutoDevIcons
4+
import cc.unitmesh.devti.devins.variable.ConditionPsiVariable
5+
import cc.unitmesh.devti.language.ast.ExpressionBuiltInMethod
6+
import com.intellij.codeInsight.completion.CompletionParameters
7+
import com.intellij.codeInsight.completion.CompletionProvider
8+
import com.intellij.codeInsight.completion.CompletionResultSet
9+
import com.intellij.codeInsight.completion.PrioritizedLookupElement
10+
import com.intellij.codeInsight.lookup.LookupElementBuilder
11+
import com.intellij.util.ProcessingContext
12+
13+
class WhenConditionCompletionProvider : CompletionProvider<CompletionParameters>() {
14+
override fun addCompletions(
15+
parameters: CompletionParameters,
16+
context: ProcessingContext,
17+
result: CompletionResultSet,
18+
) {
19+
ConditionPsiVariable.values().forEach {
20+
val withTypeText =
21+
PrioritizedLookupElement.withPriority(
22+
LookupElementBuilder
23+
.create(it.name)
24+
.withIcon(AutoDevIcons.AI_COPILOT)
25+
.withTypeText(it.description, true),
26+
199.0
27+
)
28+
29+
result.addElement(withTypeText)
30+
}
31+
}
32+
}
33+
34+
class WhenConditionFunctionCompletionProvider : CompletionProvider<CompletionParameters>() {
35+
override fun addCompletions(
36+
parameters: CompletionParameters,
37+
context: ProcessingContext,
38+
result: CompletionResultSet,
39+
) {
40+
ExpressionBuiltInMethod.completionProvider().forEach {
41+
val elementBuilder = LookupElementBuilder.create(it.methodName)
42+
.withTypeText(it.description, true)
43+
.withInsertHandler { context, _ ->
44+
context.document.insertString(context.tailOffset, it.postInsertString)
45+
context.editor.caretModel.moveCaretRelatively(it.moveCaret, 0, false, false, false)
46+
}
47+
48+
val withTypeText =
49+
PrioritizedLookupElement.withPriority(
50+
elementBuilder, 99.0
51+
)
52+
53+
result.addElement(withTypeText)
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)