Skip to content

Commit 75e9518

Browse files
committed
feat(devins): improve Java symbol lookup and chat rendering
- Add EDT thread handling for UI updates in chat panel - Implement comprehensive Java symbol lookup, including packages, classes, methods, and fields - Enhance SymbolInsCommand to use runReadAction for thread safety - Update JavaCustomDevInsSymbolProvider to provide more accurate and diverse symbol information
1 parent ac4607a commit 75e9518

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

core/src/main/kotlin/cc/unitmesh/devti/gui/chat/NormalChatCodingPanel.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import cc.unitmesh.devti.sketch.createActionButton
2323
import cc.unitmesh.devti.sketch.ui.code.HtmlHighlightSketch
2424
import cc.unitmesh.devti.util.whenDisposed
2525
import com.intellij.openapi.Disposable
26+
import com.intellij.openapi.application.runInEdt
2627
import com.intellij.openapi.progress.ProgressIndicator
2728
import com.intellij.openapi.progress.ProgressManager
2829
import com.intellij.openapi.progress.Task
@@ -180,7 +181,10 @@ class NormalChatCodingPanel(private val chatCodingService: ChatCodingService, va
180181
val displayText = displayPrompt.ifEmpty { message }
181182

182183
val messageView = MessageView(chatCodingService.project, message, role, displayText)
183-
myList.add(messageView)
184+
runInEdt {
185+
myList.add(messageView)
186+
}
187+
184188
scrollToBottom()
185189
progressBar.isIndeterminate = true
186190
updateUI()

exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/compiler/exec/SymbolInsCommand.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import cc.unitmesh.devti.command.InsCommand
44
import cc.unitmesh.devti.command.dataprovider.BuiltinCommand
55
import cc.unitmesh.devti.language.compiler.error.DEVINS_ERROR
66
import cc.unitmesh.devti.provider.devins.DevInsSymbolProvider
7+
import com.intellij.openapi.application.runReadAction
78
import com.intellij.openapi.project.Project
89

910
class SymbolInsCommand(val myProject: Project, val prop: String) : InsCommand {
1011
override val commandName: BuiltinCommand = BuiltinCommand.SYMBOL
1112

1213
override suspend fun execute(): String {
1314
val result = DevInsSymbolProvider.all().mapNotNull {
14-
val found = it.resolveSymbol(myProject, prop)
15+
val found = runReadAction { it.resolveSymbol(myProject, prop) }
1516
if (found.isEmpty()) return@mapNotNull null
1617
"```${it.language}\n${found.joinToString("\n")}\n```\n"
1718
}

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

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import com.intellij.ide.highlighter.JavaFileType
88
import com.intellij.lang.java.JavaLanguage
99
import com.intellij.openapi.application.runReadAction
1010
import com.intellij.openapi.project.Project
11-
import com.intellij.psi.PsiElement
12-
import com.intellij.psi.PsiManager
13-
import com.intellij.psi.PsiPackageStatement
11+
import com.intellij.psi.*
1412
import com.intellij.psi.impl.file.impl.JavaFileManagerImpl
1513
import com.intellij.psi.search.FileTypeIndex
1614
import com.intellij.psi.search.GlobalSearchScope
@@ -55,11 +53,29 @@ class JavaCustomDevInsSymbolProvider : DevInsSymbolProvider {
5553

5654
packageStatements.forEach {
5755
if (it.packageName.startsWith(text)) {
58-
val element = LookupElementBuilder.create(it.packageName).withIcon(JavaFileType.INSTANCE.icon)
56+
val element = LookupElementBuilder.create(it.packageName)
57+
.withIcon(JavaFileType.INSTANCE.icon)
58+
.withTypeText("package")
5959
lookupElements.add(element)
6060
}
6161
}
6262

63+
val psiShortNamesCache = PsiShortNamesCache.getInstance(project)
64+
val classNames = psiShortNamesCache.allClassNames
65+
66+
classNames.forEach { className ->
67+
if (className.startsWith(text) || text.isEmpty()) {
68+
val psiClasses = psiShortNamesCache.getClassesByName(className, searchScope)
69+
psiClasses.forEach { psiClass ->
70+
val qualifiedName = psiClass.qualifiedName ?: return@forEach
71+
val element = LookupElementBuilder.create(qualifiedName)
72+
.withIcon(JavaFileType.INSTANCE.icon)
73+
.withTypeText("class")
74+
lookupElements.add(element)
75+
}
76+
}
77+
}
78+
6379
return lookupElements
6480
}
6581

@@ -68,23 +84,23 @@ class JavaCustomDevInsSymbolProvider : DevInsSymbolProvider {
6884

6985
if (symbol.isEmpty()) return emptyList()
7086

71-
// className only, like `String` not Dot
7287
if (symbol.contains(".").not()) {
7388
val psiClasses = PsiShortNamesCache.getInstance(project).getClassesByName(symbol, scope)
7489
if (psiClasses.isNotEmpty()) {
75-
return psiClasses.map { it.qualifiedName!! }
90+
return psiClasses.mapNotNull { it.qualifiedName }
7691
}
7792
}
7893

79-
// for package name only, like `cc.unitmesh`
8094
JavaFileManagerImpl(project).findPackage(symbol)?.let { pkg ->
81-
return pkg.classes.map { it.qualifiedName!! }
95+
return pkg.classes.mapNotNull { it.qualifiedName }
8296
}
8397

84-
// for single class, with function name, like `cc.unitmesh.idea.provider.JavaCustomDevInsSymbolProvider`
8598
val clazz = JavaFileManagerImpl(project).findClass(symbol, scope)
8699
if (clazz != null) {
87-
return clazz.methods.map { "${clazz.qualifiedName}#${it.name}" }
100+
val classInfo = mutableListOf(clazz.qualifiedName ?: "")
101+
classInfo.addAll(clazz.methods.map { "${clazz.qualifiedName ?: ""}#${it.name}" })
102+
classInfo.addAll(clazz.fields.map { "${clazz.qualifiedName ?: ""}.${it.name}" })
103+
return classInfo
88104
}
89105

90106
// for lookup for method
@@ -139,6 +155,21 @@ class JavaCustomDevInsSymbolProvider : DevInsSymbolProvider {
139155
return lookupElementWithMethodName(project, clazzName, scope, methodName)
140156
}
141157

158+
// for lookup class field
159+
val fieldSplit = symbol.split(".")
160+
if (fieldSplit.size >= 2) {
161+
val className = fieldSplit.dropLast(1).joinToString(".")
162+
val fieldName = fieldSplit.last()
163+
164+
val psiClass = JavaFileManagerImpl(project).findClass(className, scope)
165+
if (psiClass != null) {
166+
val field = psiClass.findFieldByName(fieldName, true)
167+
if (field != null) {
168+
return listOf(field)
169+
}
170+
}
171+
}
172+
142173
// may by not our format, like <package>.<class>.<method> split last
143174
val lastDotIndex = symbol.lastIndexOf(".")
144175
if (lastDotIndex != -1) {

0 commit comments

Comments
 (0)