Skip to content

Commit f08f12a

Browse files
authored
refactor: Add the right-click actions to the dynamic group and check for the psi-element to determine its visibility (#232)
1 parent 22cd295 commit f08f12a

File tree

16 files changed

+94
-32
lines changed

16 files changed

+94
-32
lines changed

src/222/main/kotlin/cc/unitmesh/devti/intentions/IntentionHelperUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import com.intellij.psi.PsiFile
1616

1717
object IntentionHelperUtil {
1818
val EP_NAME: ExtensionPointName<IntentionActionBean> = ExtensionPointName("cc.unitmesh.autoDevIntention")
19-
fun getAiAssistantIntentions(project: Project, editor: Editor, file: PsiFile): List<IntentionAction> {
19+
fun getAiAssistantIntentions(project: Project, editor: Editor?, file: PsiFile): List<IntentionAction> {
2020
val extensionList = EP_NAME.extensionList
2121

2222
val builtinIntentions = extensionList

src/222/main/resources/META-INF/autodev-core.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@
238238
</group>
239239

240240
<!-- For right click -->
241-
<!-- TODO: refactor to dynamic group: https://plugins.jetbrains.com/docs/intellij/grouping-action.html#adding-child-actions-to-the-dynamic-group -->
242-
<group id="org.intellij.sdk.action.GroupedActions" popup="true" text="AutoDev Chat" description="AutoDev chat">
241+
<group id="autodev.groups.AutoChatDynamicActionGroup" popup="true" description="AutoDev chat"
242+
class="cc.unitmesh.devti.actions.groups.AutoChatDynamicActionGroup">
243243
<action id="cc.unitmesh.devti.actions.chat.ExplainThisAction"
244244
class="cc.unitmesh.devti.actions.chat.ExplainThisAction"
245245
description="Ask AI about this code">

src/233/main/kotlin/cc/unitmesh/devti/intentions/IntentionHelperUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import com.intellij.psi.PsiFile
1616

1717
object IntentionHelperUtil {
1818
val EP_NAME: ExtensionPointName<IntentionActionBean> = ExtensionPointName("cc.unitmesh.autoDevIntention")
19-
fun getAiAssistantIntentions(project: Project, editor: Editor, file: PsiFile): List<IntentionAction> {
19+
fun getAiAssistantIntentions(project: Project, editor: Editor?, file: PsiFile): List<IntentionAction> {
2020
val extensionList = EP_NAME.extensionList
2121

2222
val builtinIntentions = extensionList

src/233/main/resources/META-INF/autodev-core.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@
251251
</group>
252252

253253
<!-- For right click -->
254-
<!-- TODO: refactor to dynamic group: https://plugins.jetbrains.com/docs/intellij/grouping-action.html#adding-child-actions-to-the-dynamic-group -->
255-
<group id="org.intellij.sdk.action.GroupedActions" popup="true" text="AutoDev Chat" description="AutoDev chat">
254+
<group id="autodev.groups.AutoChatDynamicActionGroup" popup="true" description="AutoDev chat"
255+
class="cc.unitmesh.devti.actions.groups.AutoChatDynamicActionGroup">
256256
<action id="cc.unitmesh.devti.actions.chat.ExplainThisAction"
257257
class="cc.unitmesh.devti.actions.chat.ExplainThisAction"
258258
description="Ask AI about this code">

src/main/kotlin/cc/unitmesh/devti/actions/chat/ChatWithThisAction.kt

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

3-
import cc.unitmesh.devti.actions.chat.base.ChatBaseAction
3+
import cc.unitmesh.devti.actions.chat.base.ChatCheckForUpdateAction
44
import cc.unitmesh.devti.gui.chat.ChatActionType
55
import cc.unitmesh.devti.gui.sendToChatWindow
66
import cc.unitmesh.devti.settings.LanguageChangedCallback.presentationText
77
import com.intellij.openapi.actionSystem.AnActionEvent
88
import com.intellij.openapi.actionSystem.CommonDataKeys
99
import com.intellij.temporary.getElementToAction
1010

11-
class ChatWithThisAction : ChatBaseAction() {
11+
class ChatWithThisAction : ChatCheckForUpdateAction() {
1212

1313
init{
1414
presentationText("settings.autodev.rightClick.chat", templatePresentation)

src/main/kotlin/cc/unitmesh/devti/actions/chat/ExplainThisAction.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package cc.unitmesh.devti.actions.chat
22

3-
import cc.unitmesh.devti.actions.chat.base.ChatBaseAction
3+
import cc.unitmesh.devti.actions.chat.base.ChatCheckForUpdateAction
44
import cc.unitmesh.devti.gui.chat.ChatActionType
55
import cc.unitmesh.devti.settings.LanguageChangedCallback.presentationText
66

7-
class ExplainThisAction() : ChatBaseAction() {
7+
class ExplainThisAction() : ChatCheckForUpdateAction() {
88
init{
99
presentationText("settings.autodev.rightClick.explain", templatePresentation)
1010
}

src/main/kotlin/cc/unitmesh/devti/actions/chat/GenerateApiTestAction.kt

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

3-
import cc.unitmesh.devti.actions.chat.base.ChatBaseAction
3+
import cc.unitmesh.devti.actions.chat.base.ChatCheckForUpdateAction
44
import cc.unitmesh.devti.gui.chat.ChatActionType
55
import cc.unitmesh.devti.settings.LanguageChangedCallback.presentationText
66
import com.intellij.openapi.editor.Editor
77
import com.intellij.openapi.project.Project
88
import com.intellij.psi.PsiElement
99

10-
class GenerateApiTestAction : ChatBaseAction() {
10+
class GenerateApiTestAction : ChatCheckForUpdateAction() {
1111
init {
1212
presentationText("settings.autodev.rightClick.genApiTest", templatePresentation)
1313
}

src/main/kotlin/cc/unitmesh/devti/actions/chat/RefactorThisAction.kt

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,29 @@
11
package cc.unitmesh.devti.actions.chat
22

33
import cc.unitmesh.devti.AutoDevBundle
4-
import cc.unitmesh.devti.actions.chat.base.ChatBaseAction
4+
import cc.unitmesh.devti.actions.chat.base.ChatCheckForUpdateAction
55
import cc.unitmesh.devti.actions.chat.base.collectProblems
66
import cc.unitmesh.devti.actions.chat.base.commentPrefix
77
import cc.unitmesh.devti.gui.chat.ChatActionType
88
import cc.unitmesh.devti.gui.chat.ChatCodingPanel
99
import cc.unitmesh.devti.provider.RefactoringTool
1010
import cc.unitmesh.devti.settings.LanguageChangedCallback.presentationText
11-
import com.intellij.openapi.actionSystem.ActionUpdateThread
1211
import com.intellij.openapi.actionSystem.AnActionEvent
1312
import com.intellij.openapi.actionSystem.CommonDataKeys
1413
import com.intellij.openapi.editor.Editor
1514
import com.intellij.openapi.project.Project
1615
import com.intellij.psi.PsiElement
1716

18-
open class RefactorThisAction : ChatBaseAction() {
17+
open class RefactorThisAction : ChatCheckForUpdateAction() {
1918
init {
2019
presentationText("settings.autodev.rightClick.refactor", templatePresentation)
2120
}
2221

23-
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
2422
override fun getActionType(): ChatActionType = ChatActionType.REFACTOR
2523
override fun update(e: AnActionEvent) {
26-
val editor = e.getData(CommonDataKeys.EDITOR)
2724
val file = e.getData(CommonDataKeys.PSI_FILE)
28-
val project = e.getData(CommonDataKeys.PROJECT)
29-
30-
if (editor == null || file == null || project == null) {
31-
e.presentation.isEnabled = false
32-
return
33-
}
34-
35-
if (file.isWritable) {
36-
e.presentation.isEnabled = true
25+
if (file != null && file.isWritable) {
26+
super.update(e)
3727
return
3828
}
3929

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package cc.unitmesh.devti.actions.chat.base
2+
3+
import com.intellij.openapi.actionSystem.ActionUpdateThread
4+
import com.intellij.openapi.actionSystem.AnActionEvent
5+
import com.intellij.openapi.actionSystem.CommonDataKeys
6+
import com.intellij.psi.PsiWhiteSpace
7+
import com.intellij.temporary.getElementToAction
8+
9+
/**
10+
* This abstract class can check for the psi-element
11+
* when updating the presentation of the action in the user interface.
12+
*
13+
* For example, when the psi-element of an action is [PsiWhiteSpace],
14+
* an unexpected prompt is generated and should not be processed.
15+
* To avoid such prompts, the action should be disabled.
16+
*
17+
* @author lk
18+
*/
19+
abstract class ChatCheckForUpdateAction : ChatBaseAction() {
20+
21+
override fun getActionUpdateThread() = ActionUpdateThread.BGT
22+
23+
override fun update(e: AnActionEvent) {
24+
val editor = e.getData(CommonDataKeys.EDITOR)
25+
val project = e.getData(CommonDataKeys.PROJECT)
26+
e.presentation.isEnabled = getElementToAction(project, editor)?.text?.isNotBlank() ?: false
27+
}
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package cc.unitmesh.devti.actions.groups
2+
3+
import cc.unitmesh.devti.settings.LanguageChangedCallback
4+
import com.intellij.openapi.actionSystem.ActionGroupUtil
5+
import com.intellij.openapi.actionSystem.ActionUpdateThread
6+
import com.intellij.openapi.actionSystem.AnActionEvent
7+
import com.intellij.openapi.actionSystem.DefaultActionGroup
8+
import com.intellij.openapi.project.DumbAware
9+
10+
/**
11+
* Add the right-click actions to the dynamic group.
12+
*
13+
* This group hides itself on the editorPopupMenu
14+
* when each child are disabled or invisible.
15+
*
16+
* @author lk
17+
*/
18+
class AutoChatDynamicActionGroup : DefaultActionGroup(), DumbAware {
19+
20+
init {
21+
LanguageChangedCallback.presentationText("autodev.chat",
22+
templatePresentation.also { it.isHideGroupIfEmpty = true })
23+
}
24+
25+
override fun getActionUpdateThread() = ActionUpdateThread.BGT
26+
27+
override fun update(e: AnActionEvent) {
28+
e.presentation.isEnabledAndVisible = !ActionGroupUtil.isGroupEmpty(this, e)
29+
}
30+
}
31+

src/main/kotlin/cc/unitmesh/devti/actions/quick/QuickAssistantAction.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ open class QuickAssistantAction : AnAction() {
3737
presentationText("settings.autodev.others.quickAssistant", templatePresentation)
3838
}
3939

40+
override fun getActionUpdateThread() = ActionUpdateThread.BGT
41+
42+
override fun update(e: AnActionEvent) {
43+
e.presentation.isEnabled = e.getData(CommonDataKeys.PSI_FILE)?.isWritable ?: false
44+
}
45+
46+
4047
override fun actionPerformed(e: AnActionEvent) {
4148
val dataContext = e.dataContext
4249
val editor = dataContext.getData(CommonDataKeys.EDITOR) ?: return

src/main/kotlin/cc/unitmesh/devti/intentions/AutoDevIntentionHelper.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class AutoDevIntentionHelper : IntentionAction, Iconable {
2222

2323
val instance = InjectedLanguageManager.getInstance(project)
2424
return instance.getTopLevelFile(file)?.virtualFile != null
25+
&& IntentionHelperUtil.getAiAssistantIntentions(project, editor, file).isNotEmpty()
2526
}
2627

2728
override fun invoke(project: Project, editor: Editor, file: PsiFile) {

src/main/kotlin/cc/unitmesh/devti/intentions/IntentionsActionGroup.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ import com.intellij.openapi.project.DumbAware
1111
import com.intellij.openapi.project.DumbAwareAction
1212
import com.intellij.openapi.project.Project
1313
import com.intellij.psi.PsiFile
14+
import java.util.function.Supplier
1415

15-
class IntentionsActionGroup : ActionGroup(AutoDevBundle.message("intentions.assistant.name"), true), DumbAware {
16+
class IntentionsActionGroup : ActionGroup(Supplier { AutoDevBundle.message("intentions.assistant.name") }, true), DumbAware {
1617
override fun getChildren(e: AnActionEvent?): Array<AnAction> {
1718
val project: Project = e?.project ?: return emptyArray()
1819
val editor: Editor = e.getData(CommonDataKeys.EDITOR) ?: return emptyArray()

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class AutoTestThisIntention : ChatBaseIntention() {
2121
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?): Boolean {
2222
val psiElement = file?.originalElement ?: return false
2323
val service = AutoTestService.context(psiElement)
24-
return service != null
24+
return service != null && getElementToAction(project, editor)?.text?.isNotBlank() ?: false
2525
}
2626

2727
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import cc.unitmesh.devti.provider.LivingDocumentation
77
import com.intellij.openapi.editor.Editor
88
import com.intellij.openapi.project.Project
99
import com.intellij.psi.PsiFile
10+
import com.intellij.psi.util.PsiUtilBase
1011

1112
class DefaultDocumentationBaseIntention: BasedDocumentationBaseIntention() {
1213
override val config: CustomDocumentationConfig = CustomDocumentationConfig.default()
@@ -16,9 +17,12 @@ class DefaultDocumentationBaseIntention: BasedDocumentationBaseIntention() {
1617
override fun getFamilyName(): String = AutoDevBundle.message("intentions.living.documentation.family.name")
1718

1819
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?): Boolean {
19-
if (editor == null || file == null) return false
20+
if (editor == null || file == null || !file.isWritable) return false
2021

21-
val livingDocumentation = LivingDocumentation.forLanguage(file.language)
22-
return livingDocumentation != null
22+
return LivingDocumentation.forLanguage(file.language)?.let {
23+
editor.selectionModel.selectedText != null || PsiUtilBase.getElementAtCaret(editor)?.run {
24+
it.findNearestDocumentationTarget(this) != null
25+
} ?: false
26+
} ?: false
2327
}
2428
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class NewChatWithCodeBaseIntention : ChatBaseIntention() {
1717
override fun getFamilyName(): String = AutoDevBundle.message("intentions.chat.new.family.name")
1818

1919
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?): Boolean {
20-
if (editor == null || file == null) return false
20+
if (editor == null || file == null || getElementToAction(project, editor)?.text?.isBlank() ?: true) return false
2121

2222
this.title = computeTitle(project, file, getCurrentSelectionAsRange(editor))
2323
return true

0 commit comments

Comments
 (0)