Skip to content

Commit 52858c0

Browse files
committed
fix(mpp-idea): address PR review comments
1. IdeaPromptEnhancer: - Log only metadata (length) instead of user prompt content to avoid sensitive info leakage - Fix domain dictionary fallback logic to properly check both paths - Add debug logging for file loading failures - Fix regex to handle code blocks without trailing newline 2. IdeaMcpConfigDialog: - Add proper @deprecated annotation with ReplaceWith suggestion 3. IdeaBottomToolbar: - Remove unused kotlinx.coroutines.launch import 4. IdeaDevInInputArea: - Extract duplicate send logic into buildAndSendMessage helper function - Use isProcessingRef to fix stale closure issue in SwingPanel listener - Remove redundant withContext(Dispatchers.Main) + invokeLater combination
1 parent cb683ff commit 52858c0

File tree

4 files changed

+66
-42
lines changed

4 files changed

+66
-42
lines changed

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import cc.unitmesh.devins.idea.toolwindow.IdeaComposeIcons
1010
import cc.unitmesh.devins.ui.compose.theme.AutoDevColors
1111
import cc.unitmesh.llm.NamedModelConfig
1212
import com.intellij.openapi.project.Project
13-
import kotlinx.coroutines.launch
1413
import org.jetbrains.jewel.foundation.theme.JewelTheme
1514
import org.jetbrains.jewel.ui.component.*
1615
import org.jetbrains.jewel.ui.component.Icon

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaMcpConfigDialog.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ class IdeaMcpConfigDialogWrapper(
116116
* - Incremental MCP server loading
117117
*
118118
* Styled to match IdeaModelConfigDialog for consistency.
119-
*
120-
* @deprecated Use IdeaMcpConfigDialogWrapper.show() instead for proper z-index handling with SwingPanel.
121119
*/
120+
@Deprecated(
121+
message = "Use IdeaMcpConfigDialogWrapper.show() instead for proper z-index handling with SwingPanel.",
122+
replaceWith = ReplaceWith("IdeaMcpConfigDialogWrapper.show(project)"),
123+
level = DeprecationLevel.WARNING
124+
)
122125
@Composable
123126
fun IdeaMcpConfigDialog(
124127
onDismiss: () -> Unit

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaPromptEnhancer.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class IdeaPromptEnhancer(private val project: Project) {
3232
*/
3333
suspend fun enhance(input: String): String = withContext(Dispatchers.IO) {
3434
try {
35-
logger.info("Starting enhancement for input: ${input.take(50)}...")
35+
// Log only metadata to avoid leaking sensitive information
36+
logger.info("Starting enhancement for input (length: ${input.length})")
3637

3738
val dict = loadDomainDict()
3839
val readme = loadReadme()
@@ -82,11 +83,13 @@ class IdeaPromptEnhancer(private val project: Project) {
8283
return try {
8384
runReadAction {
8485
val baseDir = project.guessProjectDir() ?: return@runReadAction ""
85-
val promptsDir = baseDir.findChild(".autodev") ?: baseDir.findChild("prompts")
86-
val dictFile = promptsDir?.findChild("domain.csv")
86+
// Try .autodev/domain.csv first, then prompts/domain.csv
87+
val dictFile = baseDir.findChild(".autodev")?.findChild("domain.csv")
88+
?: baseDir.findChild("prompts")?.findChild("domain.csv")
8789
dictFile?.contentsToByteArray()?.toString(Charsets.UTF_8) ?: ""
8890
}
8991
} catch (e: Exception) {
92+
logger.debug("Failed to load domain dictionary: ${e.message}")
9093
""
9194
}
9295
}
@@ -107,6 +110,7 @@ class IdeaPromptEnhancer(private val project: Project) {
107110
if (content.length > 2000) content.take(2000) + "\n..." else content
108111
}
109112
} catch (e: Exception) {
113+
logger.debug("Failed to load README: ${e.message}")
110114
""
111115
}
112116
}
@@ -152,8 +156,8 @@ class IdeaPromptEnhancer(private val project: Project) {
152156
* Looks for content in markdown code blocks.
153157
*/
154158
private fun extractEnhancedPrompt(response: String): String? {
155-
// Try to extract from markdown code block
156-
val codeBlockRegex = Regex("```(?:\\w+)?\\s*\\n([\\s\\S]*?)\\n```")
159+
// Try to extract from markdown code block (trailing newline is optional)
160+
val codeBlockRegex = Regex("```(?:\\w+)?\\s*\\n([\\s\\S]*?)\\n?```")
157161
val match = codeBlockRegex.find(response)
158162
if (match != null) {
159163
return match.groupValues[1].trim()

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaDevInInputArea.kt

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import com.intellij.openapi.project.Project
2121
import com.intellij.openapi.util.Disposer
2222
import kotlinx.coroutines.Dispatchers
2323
import kotlinx.coroutines.launch
24-
import kotlinx.coroutines.withContext
2524
import org.jetbrains.jewel.foundation.theme.JewelTheme
2625
import java.awt.BorderLayout
2726
import java.awt.Dimension
@@ -44,6 +43,26 @@ import javax.swing.JPanel
4443
*/
4544
private val inputAreaLogger = Logger.getInstance("IdeaDevInInputArea")
4645

46+
/**
47+
* Helper function to build and send message with file references.
48+
* Extracts common logic from onSubmit and onSendClick.
49+
*/
50+
private fun buildAndSendMessage(
51+
text: String,
52+
selectedFiles: List<SelectedFileItem>,
53+
onSend: (String) -> Unit,
54+
clearInput: () -> Unit,
55+
clearFiles: () -> Unit
56+
) {
57+
if (text.isBlank()) return
58+
59+
val filesText = selectedFiles.joinToString("\n") { it.toDevInsCommand() }
60+
val fullText = if (filesText.isNotEmpty()) "$text\n$filesText" else text
61+
onSend(fullText)
62+
clearInput()
63+
clearFiles()
64+
}
65+
4766
@Composable
4867
fun IdeaDevInInputArea(
4968
project: Project,
@@ -64,6 +83,10 @@ fun IdeaDevInInputArea(
6483
var selectedFiles by remember { mutableStateOf<List<SelectedFileItem>>(emptyList()) }
6584
var isEnhancing by remember { mutableStateOf(false) }
6685

86+
// Use a ref to track current processing state for the SwingPanel listener
87+
val isProcessingRef = remember { mutableStateOf(isProcessing) }
88+
LaunchedEffect(isProcessing) { isProcessingRef.value = isProcessing }
89+
6790
val scope = rememberCoroutineScope()
6891
val borderShape = RoundedCornerShape(8.dp)
6992

@@ -119,19 +142,18 @@ fun IdeaDevInInputArea(
119142
}
120143

121144
override fun onSubmit(text: String, trigger: IdeaInputTrigger) {
122-
if (text.isNotBlank() && !isProcessing) {
123-
// Append file references to the message (use /dir: for directories, /file: for files)
124-
val filesText = selectedFiles.joinToString("\n") { it.toDevInsCommand() }
125-
val fullText = if (filesText.isNotEmpty()) {
126-
"$text\n$filesText"
127-
} else {
128-
text
129-
}
130-
onSend(fullText)
131-
clearInput()
132-
inputText = ""
133-
// Clear selected files after sending
134-
selectedFiles = emptyList()
145+
// Use ref to get current processing state
146+
if (text.isNotBlank() && !isProcessingRef.value) {
147+
buildAndSendMessage(
148+
text = text,
149+
selectedFiles = selectedFiles,
150+
onSend = onSend,
151+
clearInput = {
152+
clearInput()
153+
inputText = ""
154+
},
155+
clearFiles = { selectedFiles = emptyList() }
156+
)
135157
}
136158
}
137159

@@ -167,18 +189,16 @@ fun IdeaDevInInputArea(
167189
onSendClick = {
168190
val text = devInInput?.text?.trim() ?: inputText.trim()
169191
if (text.isNotBlank() && !isProcessing) {
170-
// Append file references to the message (use /dir: for directories, /file: for files)
171-
val filesText = selectedFiles.joinToString("\n") { it.toDevInsCommand() }
172-
val fullText = if (filesText.isNotEmpty()) {
173-
"$text\n$filesText"
174-
} else {
175-
text
176-
}
177-
onSend(fullText)
178-
devInInput?.clearInput()
179-
inputText = ""
180-
// Clear selected files after sending
181-
selectedFiles = emptyList()
192+
buildAndSendMessage(
193+
text = text,
194+
selectedFiles = selectedFiles,
195+
onSend = onSend,
196+
clearInput = {
197+
devInInput?.clearInput()
198+
inputText = ""
199+
},
200+
clearFiles = { selectedFiles = emptyList() }
201+
)
182202
}
183203
},
184204
sendEnabled = inputText.isNotBlank() && !isProcessing,
@@ -198,21 +218,19 @@ fun IdeaDevInInputArea(
198218
inputAreaLogger.info("Enhancement completed, result length: ${enhanced.length}")
199219

200220
if (enhanced != currentText && enhanced.isNotBlank()) {
201-
// Update UI on EDT
202-
withContext(Dispatchers.Main) {
203-
ApplicationManager.getApplication().invokeLater {
204-
devInInput?.replaceText(enhanced)
205-
inputText = enhanced
206-
inputAreaLogger.info("Text updated in input field")
207-
}
221+
// Update UI on EDT using invokeLater
222+
ApplicationManager.getApplication().invokeLater {
223+
devInInput?.replaceText(enhanced)
224+
inputText = enhanced
225+
inputAreaLogger.info("Text updated in input field")
208226
}
209227
} else {
210228
inputAreaLogger.info("No enhancement made (same text or empty result)")
211229
}
212230
} catch (e: Exception) {
213231
inputAreaLogger.error("Prompt enhancement failed: ${e.message}", e)
214232
} finally {
215-
withContext(Dispatchers.Main) {
233+
ApplicationManager.getApplication().invokeLater {
216234
isEnhancing = false
217235
}
218236
}

0 commit comments

Comments
 (0)