Skip to content

Commit 4fddd6d

Browse files
committed
feat(doc): add basdic prompt
1 parent f85a28d commit 4fddd6d

File tree

9 files changed

+171
-44
lines changed

9 files changed

+171
-44
lines changed

java/src/main/kotlin/cc/unitmesh/idea/promting/JavaContextPrompter.kt

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -93,25 +93,12 @@ open class JavaContextPrompter : ContextPrompter() {
9393

9494
when (action!!) {
9595
ChatActionType.EXPLAIN -> {
96-
val autoComment = customPromptConfig?.autoComment
97-
if (autoComment?.instruction?.isNotEmpty() == true) {
98-
prompt = autoComment.instruction
99-
}
10096
}
10197

10298
ChatActionType.REFACTOR -> {
103-
val refactor = customPromptConfig?.refactor
104-
if (refactor?.instruction?.isNotEmpty() == true) {
105-
prompt = refactor.instruction
106-
}
10799
}
108100

109101
ChatActionType.CODE_COMPLETE -> {
110-
val codeComplete = customPromptConfig?.autoComplete
111-
if (codeComplete?.instruction?.isNotEmpty() == true) {
112-
prompt = codeComplete.instruction
113-
}
114-
115102
when {
116103
MvcUtil.isController(fileName, lang) -> {
117104
val spec = CustomPromptConfig.load().spec["controller"]
@@ -135,12 +122,7 @@ open class JavaContextPrompter : ContextPrompter() {
135122
}
136123
}
137124

138-
ChatActionType.GENERATE_TEST -> {
139-
val writeTest = customPromptConfig?.writeTest
140-
if (writeTest?.instruction?.isNotEmpty() == true) {
141-
prompt = writeTest.instruction
142-
}
143-
}
125+
ChatActionType.GENERATE_TEST -> {}
144126

145127
ChatActionType.FIX_ISSUE -> {
146128
addFixIssueContext(selectedText)
@@ -158,6 +140,7 @@ open class JavaContextPrompter : ContextPrompter() {
158140

159141
ChatActionType.CUSTOM_COMPLETE -> {
160142
}
143+
161144
ChatActionType.CUSTOM_ACTION -> TODO()
162145
}
163146

java/src/main/kotlin/cc/unitmesh/idea/provider/JavaLivingDocumentation.kt

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ package cc.unitmesh.idea.provider
22

33
import cc.unitmesh.devti.provider.LivingDocumentation
44
import cc.unitmesh.devti.provider.LivingDocumentationType
5+
import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil
56
import com.intellij.openapi.editor.SelectionModel
6-
import com.intellij.psi.PsiClass
7-
import com.intellij.psi.PsiElement
8-
import com.intellij.psi.PsiMethod
9-
import com.intellij.psi.PsiNameIdentifierOwner
7+
import com.intellij.psi.*
108
import com.intellij.psi.util.PsiTreeUtil
9+
import com.intellij.util.IncorrectOperationException
1110

1211
class JavaLivingDocumentation : LivingDocumentation {
1312
override fun startEndString(type: LivingDocumentationType): Pair<String, String> {
@@ -19,9 +18,23 @@ class JavaLivingDocumentation : LivingDocumentation {
1918
}
2019

2120
override fun updateDoc(psiElement: PsiElement, str: String) {
22-
TODO("Not yet implemented")
21+
val project = psiElement.project
22+
val psiElementFactory = JavaPsiFacade.getElementFactory(project)
23+
val newDocComment = psiElementFactory.createDocCommentFromText(str)
24+
25+
if (psiElement is PsiDocCommentOwner) {
26+
try {
27+
psiElement.docComment?.replace(newDocComment)
28+
} catch (e: IncorrectOperationException) {
29+
val firstChild = psiElement.firstChild
30+
psiElement.addBefore(newDocComment, firstChild)
31+
}
32+
} else {
33+
throw IncorrectOperationException("Unable to update documentation")
34+
}
2335
}
2436

37+
2538
override fun findExampleDoc(psiNameIdentifierOwner: PsiNameIdentifierOwner): String {
2639
return ""
2740
}
@@ -38,11 +51,51 @@ class JavaLivingDocumentation : LivingDocumentation {
3851

3952
}
4053

54+
fun containsElement(selectionModel: SelectionModel, element: PsiElement): Boolean {
55+
return selectionModel.selectionStart <= element.textRange.startOffset && element.textRange.endOffset <= selectionModel.selectionEnd
56+
}
57+
4158
override fun findDocTargetsInSelection(
4259
psiElement: PsiElement,
4360
selectionModel: SelectionModel,
4461
): List<PsiNameIdentifierOwner> {
45-
TODO("Not yet implemented")
62+
val findCommonParent = CollectHighlightsUtil.findCommonParent(
63+
psiElement,
64+
selectionModel.selectionStart,
65+
selectionModel.selectionEnd
66+
) ?: return emptyList()
67+
68+
if (findCommonParent is PsiJavaFile) {
69+
val classAndFieldMethods = mutableListOf<PsiNameIdentifierOwner>()
70+
val classes = findCommonParent.classes
71+
for (psiClass in classes) {
72+
if (containsElement(selectionModel, psiClass)) {
73+
classAndFieldMethods.add(psiClass)
74+
}
75+
}
76+
77+
return classAndFieldMethods
78+
}
79+
80+
val target = findNearestDocumentationTarget(findCommonParent) ?: return emptyList()
81+
82+
if (target !is PsiClass || containsElement(selectionModel, target)) {
83+
return listOf(target)
84+
}
85+
86+
val methodsAndFieldsInRange = mutableListOf<PsiNameIdentifierOwner>()
87+
for (psiField in target.fields) {
88+
if (containsElement(selectionModel, psiField)) {
89+
methodsAndFieldsInRange.add(psiField)
90+
}
91+
}
92+
for (psiMethod in target.methods) {
93+
if (containsElement(selectionModel, psiMethod)) {
94+
methodsAndFieldsInRange.add(psiMethod)
95+
}
96+
}
97+
98+
return methodsAndFieldsInRange
4699
}
47100

48101
}

src/main/kotlin/cc/unitmesh/devti/context/ClassContextProvider.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package cc.unitmesh.devti.context
22

3+
import cc.unitmesh.devti.context.base.LLMQueryContextProvider
34
import cc.unitmesh.devti.context.builder.ClassContextBuilder
45
import com.intellij.lang.Language
56
import com.intellij.lang.LanguageExtension
67
import com.intellij.openapi.diagnostic.logger
78
import com.intellij.psi.PsiElement
89

9-
class ClassContextProvider(private val gatherUsages: Boolean) {
10+
class ClassContextProvider(private val gatherUsages: Boolean) : LLMQueryContextProvider<PsiElement> {
1011
private val languageExtension = LanguageExtension<ClassContextBuilder>("cc.unitmesh.classContextBuilder")
1112
private val providers: List<ClassContextBuilder>
1213

@@ -19,7 +20,7 @@ class ClassContextProvider(private val gatherUsages: Boolean) {
1920
val logger = logger<ClassContextProvider>()
2021
}
2122

22-
fun from(psiElement: PsiElement): ClassContext {
23+
override fun from(psiElement: PsiElement): ClassContext {
2324
for (provider in providers) {
2425
provider.getClassContext(psiElement, gatherUsages)?.let {
2526
return it
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package cc.unitmesh.devti.context
22

3+
import cc.unitmesh.devti.context.base.LLMQueryContextProvider
34
import cc.unitmesh.devti.context.builder.FileContextBuilder
45
import com.intellij.lang.Language
56
import com.intellij.lang.LanguageExtension
67
import com.intellij.psi.PsiFile
78

8-
class FileContextProvider {
9+
class FileContextProvider: LLMQueryContextProvider<PsiFile> {
910
private val languageExtension: LanguageExtension<FileContextBuilder> =
1011
LanguageExtension("cc.unitmesh.fileContextBuilder")
1112

@@ -16,14 +17,14 @@ class FileContextProvider {
1617
providers = registeredLanguages.mapNotNull { languageExtension.forLanguage(it) }
1718
}
1819

19-
fun from(psiFile: PsiFile): FileContext {
20+
override fun from(psiElement: PsiFile): FileContext {
2021
for (provider in providers) {
21-
val fileContext = provider.getFileContext(psiFile)
22+
val fileContext = provider.getFileContext(psiElement)
2223
if (fileContext != null) {
2324
return fileContext
2425
}
2526
}
2627

27-
return FileContext(psiFile, psiFile.name, psiFile.virtualFile?.path!!)
28+
return FileContext(psiElement, psiElement.name, psiElement.virtualFile?.path!!)
2829
}
2930
}

src/main/kotlin/cc/unitmesh/devti/context/MethodContextProvider.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package cc.unitmesh.devti.context
22

3+
import cc.unitmesh.devti.context.base.LLMQueryContextProvider
34
import cc.unitmesh.devti.context.builder.MethodContextBuilder
45
import com.intellij.lang.Language
56
import com.intellij.lang.LanguageExtension
67
import com.intellij.psi.PsiElement
78
import org.jetbrains.annotations.NotNull
89

9-
class MethodContextProvider(private val includeClassContext: Boolean, private val gatherUsages: Boolean) {
10+
class MethodContextProvider(private val includeClassContext: Boolean, private val gatherUsages: Boolean):
11+
LLMQueryContextProvider<PsiElement> {
1012
@NotNull
1113
private val languageExtension: LanguageExtension<MethodContextBuilder> =
1214
LanguageExtension("cc.unitmesh.methodContextBuilder")
@@ -20,7 +22,7 @@ class MethodContextProvider(private val includeClassContext: Boolean, private va
2022
}
2123

2224
@NotNull
23-
fun from(@NotNull psiElement: PsiElement): MethodContext {
25+
override fun from(@NotNull psiElement: PsiElement): MethodContext {
2426
val iterator = providers.iterator()
2527
while (iterator.hasNext()) {
2628
val provider = iterator.next()

src/main/kotlin/cc/unitmesh/devti/context/VariableContextProvider.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cc.unitmesh.devti.context
22

3+
import cc.unitmesh.devti.context.base.LLMQueryContextProvider
34
import cc.unitmesh.devti.context.builder.VariableContextBuilder
45
import com.intellij.lang.Language
56
import com.intellij.lang.LanguageExtension
@@ -9,7 +10,7 @@ class VariableContextProvider(
910
private val includeMethodContext: Boolean,
1011
private val includeClassContext: Boolean,
1112
private val gatherUsages: Boolean
12-
) {
13+
): LLMQueryContextProvider<PsiElement> {
1314
private val languageExtension: LanguageExtension<VariableContextBuilder> =
1415
LanguageExtension("cc.unitmesh.variableContextBuilder")
1516

@@ -20,7 +21,7 @@ class VariableContextProvider(
2021
providers = registeredLanguages.mapNotNull(languageExtension::forLanguage)
2122
}
2223

23-
fun from(psiElement: PsiElement): VariableContext {
24+
override fun from(psiElement: PsiElement): VariableContext {
2425
for (provider in providers) {
2526
val variableContext =
2627
provider.getVariableContext(psiElement, includeMethodContext, includeClassContext, gatherUsages)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package cc.unitmesh.devti.context.base;
2+
3+
import com.intellij.psi.PsiElement
4+
5+
interface LLMQueryContextProvider<T : PsiElement?> {
6+
fun from(psiElement: T): LLMQueryContext
7+
}
8+

src/main/kotlin/cc/unitmesh/devti/intentions/action/LivingDocumentationIntention.kt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.intellij.openapi.progress.ProgressManager
1010
import com.intellij.openapi.progress.Task
1111
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator
1212
import com.intellij.openapi.project.Project
13+
import com.intellij.psi.PsiElement
1314
import com.intellij.psi.PsiFile
1415
import com.intellij.psi.PsiManager
1516
import com.intellij.psi.PsiNameIdentifierOwner
@@ -39,13 +40,30 @@ class LivingDocumentationIntention : AbstractChatIntention() {
3940
if (selectedText != null) {
4041
val owners: List<PsiNameIdentifierOwner> = findSelectedElementToDocument(editor, project, selectionModel)
4142
for (identifierOwner in owners) {
42-
val task: Task.Backgroundable = LivingDocumentationTask(editor, identifierOwner)
43-
44-
ProgressManager.getInstance()
45-
.runProcessWithProgressAsynchronously(task, BackgroundableProcessIndicator(task))
43+
writeForDocument(editor, identifierOwner)
4644
}
4745
}
4846

47+
val closestToCaretNamedElement: PsiNameIdentifierOwner? = getClosestToCaretNamedElement(editor)
48+
if (closestToCaretNamedElement != null) {
49+
writeForDocument(editor, closestToCaretNamedElement)
50+
}
51+
}
52+
53+
private fun writeForDocument(editor: Editor, element: PsiNameIdentifierOwner) {
54+
val task: Task.Backgroundable = LivingDocumentationTask(editor, element)
55+
ProgressManager.getInstance()
56+
.runProcessWithProgressAsynchronously(task, BackgroundableProcessIndicator(task))
57+
}
58+
59+
private fun getClosestToCaretNamedElement(editor: Editor): PsiNameIdentifierOwner? {
60+
val element = PsiUtilBase.getElementAtCaret(editor) ?: return null
61+
return getClosestNamedElement(element)
62+
}
63+
64+
private fun getClosestNamedElement(element: PsiElement): PsiNameIdentifierOwner? {
65+
val support = LivingDocumentation.forLanguage(element.language) ?: return null
66+
return support.findNearestDocumentationTarget(element)
4967
}
5068

5169
private fun findSelectedElementToDocument(

0 commit comments

Comments
 (0)