mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-completion] IDEA-359174 command completion
- add new actions: getter/setter/find usages, introduce variable - fix set of actions GitOrigin-RevId: 9f733d5b38cb8333c3c83e1a0f3d8ea43d7bcbb1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5238e08e3f
commit
94efe9cb4d
@@ -134,6 +134,8 @@ create.write.only.property.from.usage.full.text=Create write-only property ''{0}
|
||||
create.getter=Create Getter
|
||||
# suppress inspection "UnusedProperty"
|
||||
create.setter=Create Setter
|
||||
# suppress inspection "UnusedProperty"
|
||||
create.getter.setter=Create Getter/Setter
|
||||
create.annotation.family=Add annotation to declaration
|
||||
create.annotation.text=Annotate as @{0}
|
||||
defer.final.assignment.with.temp.family=Defer final assignment with temp
|
||||
|
||||
@@ -1505,6 +1505,12 @@
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.RecentFilesCompletionCommand" />
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.ProjectViewCompletionCommand" />
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.CommentCompletionCommand" />
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.IntroduceVariableCommand" />
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.ShowUsagesActionCompletionCommand" />
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.GenerateGetterSetterHandleCompletionCommand" />
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.GenerateSetterHandleCompletionCommand" />
|
||||
<codeInsight.completion.command implementation="com.intellij.codeInsight.completion.commands.impl.GenerateGetterHandleCompletionCommand" />
|
||||
|
||||
|
||||
<weigher implementationClass="com.intellij.codeInsight.completion.LoggerWeigher" key="completion" id="logger"/>
|
||||
|
||||
|
||||
+32
@@ -1,9 +1,15 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.api
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtil
|
||||
import com.intellij.modcommand.ModHighlight.HighlightInfo
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys
|
||||
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.IndexNotReadyException
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
@@ -41,4 +47,30 @@ abstract class OldCompletionCommand : CompletionCommand() {
|
||||
override fun execute(offset: Int, psiFile: PsiFile) {
|
||||
execute(offset, psiFile, null)
|
||||
}
|
||||
|
||||
|
||||
internal fun dataContext(
|
||||
psiFile: PsiFile,
|
||||
editor: Editor,
|
||||
context: PsiElement?,
|
||||
): DataContext {
|
||||
val dataContext = SimpleDataContext.builder()
|
||||
.add(CommonDataKeys.PROJECT, psiFile.project)
|
||||
.add(CommonDataKeys.EDITOR, editor)
|
||||
.add(CommonDataKeys.PSI_ELEMENT, context)
|
||||
.add(CommonDataKeys.PSI_FILE, psiFile)
|
||||
.add(LangDataKeys.CONTEXT_LANGUAGES, arrayOf(psiFile.language))
|
||||
.build()
|
||||
return dataContext
|
||||
}
|
||||
|
||||
internal fun getTargetContext(offset: Int, editor: Editor): PsiElement? {
|
||||
try {
|
||||
val util = TargetElementUtil.getInstance()
|
||||
return util.findTargetElement(editor, util.getReferenceSearchFlags(), offset)
|
||||
}
|
||||
catch (e: IndexNotReadyException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -114,7 +114,8 @@ class CommandCompletionService(
|
||||
if (highlightInfoContainer == null || actionContainers == null) return null
|
||||
if (document.immutableCharSequence.hashCode() != highlightInfoContainer.hashcode) return null
|
||||
if (highlightInfoContainer.offset != offset) return null
|
||||
val actionContainer = actionContainers.firstOrNull { it.hashcode == highlightInfoContainer.hashcode } ?: return null
|
||||
val actionContainer = actionContainers.firstOrNull { it.hashcode == highlightInfoContainer.hashcode && it.offset == offset }
|
||||
?: return null
|
||||
val allActions = mutableListOf<IntentionActionWithTextCaching>()
|
||||
allActions.addAll(actionContainer.highlighters.allActions)
|
||||
val revertMap: MutableMap<IntentionAction, RangeHighlighterEx> = mutableMapOf()
|
||||
|
||||
+2
-22
@@ -1,16 +1,12 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtil
|
||||
import com.intellij.codeInsight.completion.commands.api.OldCompletionCommand
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.IndexNotReadyException
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.annotations.Nls
|
||||
@@ -29,13 +25,7 @@ abstract class AbstractActionCompletionCommand(
|
||||
val action = action ?: return false
|
||||
if (editor == null) return false
|
||||
val context = getTargetContext(offset, editor)
|
||||
val dataContext = SimpleDataContext.builder()
|
||||
.add(CommonDataKeys.PROJECT, psiFile.project)
|
||||
.add(CommonDataKeys.EDITOR, editor)
|
||||
.add(CommonDataKeys.PSI_ELEMENT, context)
|
||||
.add(CommonDataKeys.PSI_FILE, psiFile)
|
||||
.add(LangDataKeys.CONTEXT_LANGUAGES, arrayOf(psiFile.language))
|
||||
.build()
|
||||
val dataContext = dataContext(psiFile, editor, context)
|
||||
val presentation: Presentation = action.templatePresentation.clone()
|
||||
val event = AnActionEvent.createEvent(action, dataContext, presentation, ActionPlaces.ACTION_PLACE_QUICK_LIST_POPUP_ACTION, ActionUiKind.NONE, null)
|
||||
|
||||
@@ -44,16 +34,6 @@ abstract class AbstractActionCompletionCommand(
|
||||
return event.presentation.isEnabled && event.presentation.isVisible
|
||||
}
|
||||
|
||||
private fun getTargetContext(offset: Int, editor: Editor): PsiElement? {
|
||||
try {
|
||||
val util = TargetElementUtil.getInstance()
|
||||
return util.findTargetElement(editor, util.getReferenceSearchFlags(), offset)
|
||||
}
|
||||
catch (e: IndexNotReadyException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
override fun execute(offset: Int, psiFile: PsiFile, editor: Editor?) {
|
||||
val action = action ?: return
|
||||
if (editor == null) return
|
||||
@@ -61,7 +41,7 @@ abstract class AbstractActionCompletionCommand(
|
||||
val presentation: Presentation = action.templatePresentation.clone()
|
||||
val event = AnActionEvent.createEvent(action, dataContext, presentation, ActionPlaces.ACTION_PLACE_QUICK_LIST_POPUP_ACTION, ActionUiKind.NONE, null)
|
||||
if (ActionUtil.lastUpdateAndCheckDumb(action, event, false)) {
|
||||
ActionUtil.performActionDumbAwareWithCallbacks(action, event);
|
||||
ActionUtil.performActionDumbAwareWithCallbacks(action, event)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.codeInsight.completion.commands.api.OldCompletionCommand
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory
|
||||
import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler
|
||||
import com.intellij.modcommand.ActionContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import javax.swing.Icon
|
||||
|
||||
|
||||
class GenerateGetterSetterHandleCompletionCommand :
|
||||
BaseGenerateGetterSetterHandleCompletionCommand(true, true, "Create Getter/Setter",
|
||||
QuickFixBundle.message("create.getter.setter"))
|
||||
|
||||
class GenerateSetterHandleCompletionCommand :
|
||||
BaseGenerateGetterSetterHandleCompletionCommand(false, true, "Create Setter",
|
||||
QuickFixBundle.message("create.setter"))
|
||||
|
||||
class GenerateGetterHandleCompletionCommand :
|
||||
BaseGenerateGetterSetterHandleCompletionCommand(true, false, "Create Getter",
|
||||
QuickFixBundle.message("create.getter"))
|
||||
|
||||
abstract class BaseGenerateGetterSetterHandleCompletionCommand(
|
||||
val generateGetter: Boolean,
|
||||
val generateSetter: Boolean,
|
||||
override val name: String,
|
||||
override val i18nName: String,
|
||||
) : OldCompletionCommand() {
|
||||
|
||||
override val icon: Icon? = null
|
||||
|
||||
override fun isApplicable(offset: Int, psiFile: PsiFile, editor: Editor?): Boolean {
|
||||
val element = getContext(offset, psiFile) ?: return false
|
||||
val field = PsiTreeUtil.getParentOfType(element, PsiField::class.java) ?: return false
|
||||
val action = QuickFixFactory.getInstance().createCreateGetterOrSetterFix(generateGetter, generateSetter, field)
|
||||
val context = ActionContext.from(editor, psiFile).withElement(field)
|
||||
return action.asModCommandAction()?.getPresentation(context) != null
|
||||
}
|
||||
|
||||
override fun execute(offset: Int, psiFile: PsiFile, editor: Editor?) {
|
||||
val element = getContext(offset, psiFile) ?: return
|
||||
val field = PsiTreeUtil.getParentOfType(element, PsiField::class.java) ?: return
|
||||
val action = QuickFixFactory.getInstance().createCreateGetterOrSetterFix(generateGetter, generateSetter, field)
|
||||
if (editor == null) return
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
ShowIntentionActionsHandler.chooseActionAndInvoke(psiFile, editor, action, action.text)
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,8 +1,8 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.codeInsight.completion.commands.api.CompletionCommand
|
||||
import com.intellij.codeInsight.completion.commands.api.CommandProvider
|
||||
import com.intellij.codeInsight.completion.commands.api.CompletionCommand
|
||||
import com.intellij.codeInsight.generation.actions.BaseGenerateAction
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
|
||||
@@ -39,6 +39,7 @@ class GenerateCommandProvider : CommandProvider {
|
||||
}
|
||||
}
|
||||
return generateActions.map { GenerateCompletionCommand(it) }
|
||||
.filter { it.isApplicable(offset, psiFile, editor) }
|
||||
}
|
||||
|
||||
override fun getId(): String {
|
||||
|
||||
+4
@@ -2,6 +2,7 @@
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.codeInsight.completion.commands.api.OldCompletionCommand
|
||||
import com.intellij.codeInsight.completion.commands.impl.AbstractActionCompletionCommand.Companion.isApplicableToProject
|
||||
import com.intellij.codeInsight.generation.actions.BaseGenerateAction
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.java.JavaBundle
|
||||
@@ -25,6 +26,9 @@ class GenerateCompletionCommand(private val action: BaseGenerateAction) : OldCom
|
||||
get() = null
|
||||
|
||||
override fun isApplicable(offset: Int, psiFile: PsiFile, editor: Editor?): Boolean {
|
||||
if (!isApplicableToProject(offset, psiFile)) {
|
||||
return false
|
||||
}
|
||||
val context = psiFile.findElementAt(offset) ?: return false
|
||||
if (editor == null) return false
|
||||
val dataContext = SimpleDataContext.builder()
|
||||
|
||||
+10
-30
@@ -1,50 +1,30 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.codeInsight.completion.commands.api.CompletionCommand
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.util.EditSourceUtil
|
||||
import com.intellij.idea.ActionsBundle
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiIdentifier
|
||||
import com.intellij.psi.PsiJavaCodeReferenceElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.annotations.Nls
|
||||
import javax.swing.Icon
|
||||
|
||||
class GoToDeclarationCompletionCommand : CompletionCommand() {
|
||||
override val name: String
|
||||
get() = "Go to Declaration"
|
||||
class GoToDeclarationCompletionCommand : AbstractActionCompletionCommand("GotoDeclarationOnly",
|
||||
"Go to Declaration",
|
||||
ActionsBundle.message("action.GotoDeclarationOnly.text"),
|
||||
null) {
|
||||
override fun isApplicable(offset: Int, psiFile: PsiFile, editor: Editor?): Boolean {
|
||||
return super.isApplicable(offset, psiFile, editor) && hasToShow(offset, psiFile)
|
||||
}
|
||||
|
||||
override val i18nName: @Nls String
|
||||
get() = ActionsBundle.message("action.GotoDeclaration.text")
|
||||
|
||||
override val icon: Icon
|
||||
get() = AllIcons.Ide.ExternalLinkArrowWhite // Use the appropriate icon
|
||||
|
||||
override fun isApplicable(offset: Int, psiFile: PsiFile): Boolean {
|
||||
private fun hasToShow(offset: Int, psiFile: PsiFile): Boolean {
|
||||
val context = (getContext(offset, psiFile)) ?: return false
|
||||
return canNavigateToDeclaration(context)
|
||||
}
|
||||
|
||||
override fun execute(offset: Int, psiFile: PsiFile) {
|
||||
val element = getContext(offset, psiFile) ?: return
|
||||
if (element !is PsiIdentifier) {
|
||||
return
|
||||
}
|
||||
val javaRef = PsiTreeUtil.getParentOfType(element, PsiJavaCodeReferenceElement::class.java)
|
||||
|
||||
val psiElement = javaRef?.resolve()
|
||||
if (psiElement != null) {
|
||||
EditSourceUtil.navigateToPsiElement(psiElement)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun canNavigateToDeclaration(context: PsiElement): Boolean {
|
||||
if (context !is PsiIdentifier) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
val javaRef = PsiTreeUtil.getParentOfType(context, PsiJavaCodeReferenceElement::class.java)
|
||||
val psiElement = javaRef?.resolve()
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.codeInsight.completion.commands.api.OldCompletionCommand
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.lang.ContextAwareActionHandler
|
||||
import com.intellij.openapi.actionSystem.ActionPlaces
|
||||
import com.intellij.openapi.actionSystem.ActionUiKind
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.Presentation
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.refactoring.JavaRefactoringActionHandlerFactory
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.actions.IntroduceVariableAction
|
||||
import org.jetbrains.annotations.Nls
|
||||
import javax.swing.Icon
|
||||
|
||||
class IntroduceVariableCommand : OldCompletionCommand() {
|
||||
override val name: String
|
||||
get() = "Introduce variable"
|
||||
|
||||
override val i18nName: @Nls String
|
||||
get() = RefactoringBundle.message("introduce.variable.title")
|
||||
|
||||
override val icon: Icon
|
||||
get() = AllIcons.Nodes.Variable
|
||||
|
||||
override fun isApplicable(offset: Int, psiFile: PsiFile, editor: Editor?): Boolean {
|
||||
if (editor == null) return false
|
||||
val factory = JavaRefactoringActionHandlerFactory.getInstance()
|
||||
val variableHandler = factory.createIntroduceVariableHandler()
|
||||
if (variableHandler is ContextAwareActionHandler) {
|
||||
return variableHandler.isAvailableForQuickList(editor, psiFile, dataContext(psiFile, editor, getTargetContext(offset, editor)))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun execute(offset: Int, psiFile: PsiFile, editor: Editor?) {
|
||||
val action = IntroduceVariableAction()
|
||||
if (editor == null) return
|
||||
val context = getTargetContext(offset, editor)
|
||||
val dataContext = dataContext(psiFile, editor, context)
|
||||
val presentation: Presentation = action.templatePresentation.clone()
|
||||
val event = AnActionEvent.createEvent(action, dataContext, presentation, ActionPlaces.ACTION_PLACE_QUICK_LIST_POPUP_ACTION, ActionUiKind.NONE, null)
|
||||
action.update(event)
|
||||
ActionUtil.performActionDumbAwareWithCallbacks(action, event)
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.find.actions.ShowUsagesAction
|
||||
import com.intellij.idea.ActionsBundle
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
|
||||
class ShowUsagesActionCompletionCommand : AbstractActionCompletionCommand(ShowUsagesAction.ID,
|
||||
"Show usages",
|
||||
ActionsBundle.message("action.ShowUsages.text"),
|
||||
null) {
|
||||
override fun isApplicable(offset: Int, psiFile: PsiFile, editor: Editor?): Boolean {
|
||||
return super.isApplicable(offset, psiFile, editor) && hasToShow(getContext(offset, psiFile))
|
||||
}
|
||||
|
||||
private fun hasToShow(element: PsiElement?): Boolean {
|
||||
if (element == null) return false
|
||||
val namedIdentifierParent = PsiTreeUtil.getParentOfType(element, PsiNameIdentifierOwner::class.java)
|
||||
return namedIdentifierParent?.nameIdentifier == element &&
|
||||
(namedIdentifierParent is PsiVariable || namedIdentifierParent is PsiMethod || namedIdentifierParent is PsiMember)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user