From 04cc5e5f91e29b6ed15eb206d5ea5b9a9e2284e9 Mon Sep 17 00:00:00 2001 From: Louis Vignier Date: Thu, 13 Jun 2024 19:32:15 +0200 Subject: [PATCH] [refactoring] Add ChangeSignatureCodeVisionProvider #IJPL-10790 Fixed GitOrigin-RevId: f1d1b8e6b2df595520edfdcab71a2e5558772ac3 --- .../JavaRefactoringCodeVisionSupport.java | 5 + platform/lang-impl/api-dump-unreviewed.txt | 22 ++++ .../settings/PlatformCodeVisionIds.kt | 1 + .../hints/InlayProviderUsageCollector.kt | 2 +- .../codeVision/CodeVisionFusCollector.kt | 4 +- .../RefactoringCodeVisionSupport.java | 6 + .../ChangeSignatureCodeVisionProvider.kt | 109 ++++++++++++++++++ ...ggestedRefactoringAvailabilityIndicator.kt | 5 +- .../src/META-INF/PlatformExtensions.xml | 1 + .../messages/RefactoringBundle.properties | 2 + 10 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureCodeVisionProvider.kt diff --git a/java/java-impl/src/com/intellij/refactoring/rename/JavaRefactoringCodeVisionSupport.java b/java/java-impl/src/com/intellij/refactoring/rename/JavaRefactoringCodeVisionSupport.java index 4e8bf9abc1e0..0e842fb23935 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/JavaRefactoringCodeVisionSupport.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/JavaRefactoringCodeVisionSupport.java @@ -11,4 +11,9 @@ public class JavaRefactoringCodeVisionSupport extends RefactoringCodeVisionSuppo public boolean supportsRename(@NotNull FileType fileType) { return fileType == JavaFileType.INSTANCE; } + + @Override + public boolean supportsChangeSignature(@NotNull FileType fileType) { + return fileType == JavaFileType.INSTANCE; + } } diff --git a/platform/lang-impl/api-dump-unreviewed.txt b/platform/lang-impl/api-dump-unreviewed.txt index 157cb597c11c..8cb4beb4d550 100644 --- a/platform/lang-impl/api-dump-unreviewed.txt +++ b/platform/lang-impl/api-dump-unreviewed.txt @@ -3064,6 +3064,7 @@ f:com.intellij.codeInsight.codeVision.settings.CodeVisionSettingsPreviewLanguage - setPluginDescriptor(com.intellij.openapi.extensions.PluginDescriptor):V e:com.intellij.codeInsight.codeVision.settings.PlatformCodeVisionIds - java.lang.Enum +- sf:CHANGE_SIGNATURE:com.intellij.codeInsight.codeVision.settings.PlatformCodeVisionIds - sf:INHERITORS:com.intellij.codeInsight.codeVision.settings.PlatformCodeVisionIds - sf:PROBLEMS:com.intellij.codeInsight.codeVision.settings.PlatformCodeVisionIds - sf:RENAME:com.intellij.codeInsight.codeVision.settings.PlatformCodeVisionIds @@ -24897,7 +24898,9 @@ f:com.intellij.refactoring.IntroduceTargetChooser a:com.intellij.refactoring.RefactoringCodeVisionSupport - sf:EP_NAME:com.intellij.openapi.extensions.ExtensionPointName - ():V +- s:isChangeSignatureCodeVisionEnabled(com.intellij.openapi.fileTypes.FileType):Z - s:isRenameCodeVisionEnabled(com.intellij.openapi.fileTypes.FileType):Z +- a:supportsChangeSignature(com.intellij.openapi.fileTypes.FileType):Z - a:supportsRename(com.intellij.openapi.fileTypes.FileType):Z a:com.intellij.refactoring.RefactoringImpl - com.intellij.refactoring.Refactoring @@ -25100,6 +25103,25 @@ a:com.intellij.refactoring.changeSignature.CallerChooserBase - p:getSelectedNodes():java.util.Set - p:getTopMember():com.intellij.psi.PsiElement - getTree():com.intellij.ui.treeStructure.Tree +f:com.intellij.refactoring.changeSignature.ChangeSignatureCodeVisionProvider +- com.intellij.codeInsight.codeVision.CodeVisionProvider +- sf:Companion:com.intellij.refactoring.changeSignature.ChangeSignatureCodeVisionProvider$Companion +- ():V +- computeCodeVision(com.intellij.openapi.editor.Editor,kotlin.Unit):com.intellij.codeInsight.codeVision.CodeVisionState +- getDefaultAnchor():com.intellij.codeInsight.codeVision.CodeVisionAnchorKind +- getGroupId():java.lang.String +- getId():java.lang.String +- getName():java.lang.String +- getRelativeOrderings():java.util.List +- isAvailableFor(com.intellij.openapi.project.Project):Z +- precomputeOnUiThread(com.intellij.openapi.editor.Editor):V +f:com.intellij.refactoring.changeSignature.ChangeSignatureCodeVisionProvider$ChangeSignatureCodeVisionEntry +- com.intellij.codeInsight.codeVision.ui.model.TextCodeVisionEntry +- com.intellij.codeInsight.codeVision.ui.model.CodeVisionPredefinedActionEntry +- (com.intellij.openapi.project.Project,java.lang.String,java.lang.String,java.lang.String):V +- f:getProject():com.intellij.openapi.project.Project +- onClick(com.intellij.openapi.editor.Editor):V +f:com.intellij.refactoring.changeSignature.ChangeSignatureCodeVisionProvider$Companion a:com.intellij.refactoring.changeSignature.ChangeSignatureDialogBase - com.intellij.refactoring.ui.RefactoringDialog - psf:EXIT_SILENTLY:java.lang.String diff --git a/platform/lang-impl/src/com/intellij/codeInsight/codeVision/settings/PlatformCodeVisionIds.kt b/platform/lang-impl/src/com/intellij/codeInsight/codeVision/settings/PlatformCodeVisionIds.kt index 86f13da9140b..6d951f221802 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/codeVision/settings/PlatformCodeVisionIds.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/codeVision/settings/PlatformCodeVisionIds.kt @@ -6,4 +6,5 @@ enum class PlatformCodeVisionIds(val key: String) { INHERITORS("inheritors"), PROBLEMS("problems"), RENAME("rename"), + CHANGE_SIGNATURE("change.signature"), } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hints/InlayProviderUsageCollector.kt b/platform/lang-impl/src/com/intellij/codeInsight/hints/InlayProviderUsageCollector.kt index 09d6b0ae9f82..0916af54da77 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hints/InlayProviderUsageCollector.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/hints/InlayProviderUsageCollector.kt @@ -19,7 +19,7 @@ import com.intellij.openapi.project.Project private val LOG = logger() class InlayProviderUsageCollector : ProjectUsagesCollector() { - private val INLAY_CONFIGURATION_GROUP = EventLogGroup("inlay.configuration", 32) + private val INLAY_CONFIGURATION_GROUP = EventLogGroup("inlay.configuration", 33) private val GLOBAL_SETTINGS_EVENT = INLAY_CONFIGURATION_GROUP.registerEvent( "global.inlays.settings", diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hints/codeVision/CodeVisionFusCollector.kt b/platform/lang-impl/src/com/intellij/codeInsight/hints/codeVision/CodeVisionFusCollector.kt index dac71d290304..1c12213927d6 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hints/codeVision/CodeVisionFusCollector.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/hints/codeVision/CodeVisionFusCollector.kt @@ -13,7 +13,7 @@ import org.jetbrains.annotations.ApiStatus.Internal @Internal object CodeVisionFusCollector : CounterUsagesCollector() { - private val GROUP = EventLogGroup("daemon.code.vision", 4) + private val GROUP = EventLogGroup("daemon.code.vision", 5) override fun getGroup(): EventLogGroup = GROUP @@ -39,7 +39,7 @@ object CodeVisionFusCollector : CounterUsagesCollector() { EventFields.Language, EventFields.Size) - enum class Refactorings { Rename, } + enum class Refactorings { Rename, ChangeSignature } private val REFACTORING_PERFORMED: EventId1 = GROUP.registerEvent("refactoring.performed", EventFields.String("refactoring", Refactorings.entries.map { it.name })) diff --git a/platform/lang-impl/src/com/intellij/refactoring/RefactoringCodeVisionSupport.java b/platform/lang-impl/src/com/intellij/refactoring/RefactoringCodeVisionSupport.java index 00541a50d422..9f7dee6c9096 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/RefactoringCodeVisionSupport.java +++ b/platform/lang-impl/src/com/intellij/refactoring/RefactoringCodeVisionSupport.java @@ -20,7 +20,13 @@ public abstract class RefactoringCodeVisionSupport { */ public abstract boolean supportsRename(@NotNull FileType fileType); + public abstract boolean supportsChangeSignature(@NotNull FileType fileType); + public static boolean isRenameCodeVisionEnabled(@NotNull FileType fileType) { return ContainerUtil.exists(EP_NAME.getExtensionList(), extension -> extension.supportsRename(fileType)); } + + public static boolean isChangeSignatureCodeVisionEnabled(@NotNull FileType fileType) { + return ContainerUtil.exists(EP_NAME.getExtensionList(), extension -> extension.supportsChangeSignature(fileType)); + } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureCodeVisionProvider.kt b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureCodeVisionProvider.kt new file mode 100644 index 000000000000..34766b88e532 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureCodeVisionProvider.kt @@ -0,0 +1,109 @@ +// 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.refactoring.changeSignature + +import com.intellij.codeInsight.codeVision.* +import com.intellij.codeInsight.codeVision.settings.PlatformCodeVisionIds +import com.intellij.codeInsight.codeVision.ui.model.CodeVisionPredefinedActionEntry +import com.intellij.codeInsight.codeVision.ui.model.TextCodeVisionEntry +import com.intellij.codeInsight.hints.InlayHintsUtils +import com.intellij.codeInsight.hints.codeVision.CodeVisionFusCollector +import com.intellij.core.CoreFileTypeRegistry +import com.intellij.icons.AllIcons +import com.intellij.openapi.actionSystem.ActionPlaces +import com.intellij.openapi.command.CommandProcessor +import com.intellij.openapi.command.UndoConfirmationPolicy +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.NlsContexts +import com.intellij.openapi.vfs.findPsiFile +import com.intellij.refactoring.RefactoringBundle +import com.intellij.refactoring.RefactoringCodeVisionSupport +import com.intellij.refactoring.suggested.REFACTORING_DATA_KEY +import com.intellij.refactoring.suggested.SuggestedChangeSignatureData +import com.intellij.refactoring.suggested.performSuggestedRefactoring +import com.intellij.util.concurrency.annotations.RequiresReadLock +import org.jetbrains.annotations.Nls + +class ChangeSignatureCodeVisionProvider : CodeVisionProvider { + companion object { + internal const val ID: String = "Change signature" + } + + override fun precomputeOnUiThread(editor: Editor) {} + + class ChangeSignatureCodeVisionEntry( + val project: Project, + @Nls text: String, + @NlsContexts.Tooltip tooltip: String, + providerId: String, + ) : TextCodeVisionEntry(text, providerId, AllIcons.Actions.SuggestedRefactoringBulb, tooltip, tooltip, listOf()), CodeVisionPredefinedActionEntry { + override fun onClick(editor: Editor) { + CodeVisionFusCollector.refactoringPerformed(CodeVisionFusCollector.Refactorings.ChangeSignature) + val mouseEvent = this.getUserData(codeVisionEntryMouseEventKey) + CommandProcessor.getInstance().executeCommand(project, { + performSuggestedRefactoring(project, + editor, + null, + mouseEvent?.point, + false, + ActionPlaces.EDITOR_INLAY) + }, RefactoringBundle.message("change.signature.code.vision.name"), null, UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION, true) + } + } + + override fun computeCodeVision(editor: Editor, uiData: Unit): CodeVisionState { + val project = editor.project ?: return CodeVisionState.READY_EMPTY + + return InlayHintsUtils.computeCodeVisionUnderReadAction { + return@computeCodeVisionUnderReadAction when { + project.isDisposed || editor.isDisposed -> CodeVisionState.READY_EMPTY + else -> getCodeVisionState(editor, project) + } + } + } + + @RequiresReadLock + private fun getCodeVisionState(editor: Editor, project: Project): CodeVisionState { + val file = editor.virtualFile?.findPsiFile(project) + + if (file != null && !RefactoringCodeVisionSupport.isChangeSignatureCodeVisionEnabled(file.fileType)) { + return CodeVisionState.READY_EMPTY + } + + val refactoring = file?.getUserData(REFACTORING_DATA_KEY) + ?: editor.getUserData(REFACTORING_DATA_KEY) + ?: return CodeVisionState.READY_EMPTY + + if (refactoring is SuggestedChangeSignatureData) { + val text = RefactoringBundle.message("change.signature.code.vision.text") + val tooltip = RefactoringBundle.message( + "suggested.refactoring.change.signature.gutter.icon.tooltip", + refactoring.nameOfStuffToUpdate, + refactoring.oldSignature.name, + "" + ) + return CodeVisionState.Ready(listOf( + refactoring.declaration.textRange to ChangeSignatureCodeVisionEntry(project, text, tooltip, id) + )) + } + + return CodeVisionState.READY_EMPTY + } + + override val name: String + get() = RefactoringBundle.message("change.signature.code.vision.text") + override val relativeOrderings: List + get() = emptyList() + override val defaultAnchor: CodeVisionAnchorKind + get() = CodeVisionAnchorKind.Top + override val id: String + get() = ID + override val groupId: String + get() = PlatformCodeVisionIds.CHANGE_SIGNATURE.key + + override fun isAvailableFor(project: Project): Boolean { + return CoreFileTypeRegistry.getInstance().registeredFileTypes.any { + RefactoringCodeVisionSupport.isChangeSignatureCodeVisionEnabled(it) + } + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/refactoring/suggested/SuggestedRefactoringAvailabilityIndicator.kt b/platform/lang-impl/src/com/intellij/refactoring/suggested/SuggestedRefactoringAvailabilityIndicator.kt index 0273fce3a48e..1b511b8e4a8e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/suggested/SuggestedRefactoringAvailabilityIndicator.kt +++ b/platform/lang-impl/src/com/intellij/refactoring/suggested/SuggestedRefactoringAvailabilityIndicator.kt @@ -217,8 +217,9 @@ internal fun SuggestedRefactoringAvailabilityIndicator.update( val availabilityRange: TextRange? when { - // The gutter icon should be hidden when the rename inlay is shown - refactoringData is SuggestedRenameData && RefactoringCodeVisionSupport.isRenameCodeVisionEnabled(psiFile.fileType) -> { + // The gutter icon should be hidden when the corresponding inlay is shown + refactoringData is SuggestedRenameData && RefactoringCodeVisionSupport.isRenameCodeVisionEnabled(psiFile.fileType) || + refactoringData is SuggestedChangeSignatureData && RefactoringCodeVisionSupport.isChangeSignatureCodeVisionEnabled(psiFile.fileType) -> { refactoringAvailable = false tooltip = "" markerRange = TextRange.EMPTY_RANGE diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 9932acfb461e..99828f99a162 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -1441,6 +1441,7 @@ + diff --git a/platform/refactoring/resources/messages/RefactoringBundle.properties b/platform/refactoring/resources/messages/RefactoringBundle.properties index 39d78e4ce39c..5e54fa686838 100644 --- a/platform/refactoring/resources/messages/RefactoringBundle.properties +++ b/platform/refactoring/resources/messages/RefactoringBundle.properties @@ -500,6 +500,8 @@ rename.usage.unmodifiable=Usage cannot be updated rename.code.vision.command.name=Rename Code rename.code.vision.text=Rename usages rename.code.vision.label=Rename refactoring +change.signature.code.vision.text=Change signature +change.signature.code.vision.name=Change Signature progress.title.collect.read.only.files=Collecting read-only files\u2026 progress.title.update.added.files=Update added files progress.title.collecting.references=Collecting references\u2026