diff --git a/platform/analysis-api/src/com/intellij/codeInsight/completion/NewRdCompletionSupport.kt b/platform/analysis-api/src/com/intellij/codeInsight/completion/NewRdCompletionSupport.kt index d6ba6b225b98..927bd1a4dc4f 100644 --- a/platform/analysis-api/src/com/intellij/codeInsight/completion/NewRdCompletionSupport.kt +++ b/platform/analysis-api/src/com/intellij/codeInsight/completion/NewRdCompletionSupport.kt @@ -19,6 +19,8 @@ interface NewRdCompletionSupport { */ fun scheduleAutopopup(project: Project, editor: Editor, completionType: CompletionType) + fun isFrontendForIntelliJBackendImpl(): Boolean + companion object { @JvmStatic fun isFrontendRdCompletionOn(): Boolean = service().isFrontendRdCompletionOnImpl() @@ -32,6 +34,9 @@ interface NewRdCompletionSupport { @JvmStatic fun getInstance(): NewRdCompletionSupport = service() + + fun isFrontendForIntelliJBackend(): Boolean = + getInstance().isFrontendForIntelliJBackendImpl() } } @@ -40,4 +45,6 @@ internal class NoOpNewCompletionSupport : NewRdCompletionSupport { override fun scheduleAutopopup(project: Project, editor: Editor, completionType: CompletionType) = throw UnsupportedOperationException("Is not expected to be called, use AutopopupController directly instead") + + override fun isFrontendForIntelliJBackendImpl(): Boolean = false } \ No newline at end of file diff --git a/platform/completion/common/src/protocol/RpcCompletionItem.kt b/platform/completion/common/src/protocol/RpcCompletionItem.kt index 9f24110fe5dd..cef96ced84f4 100644 --- a/platform/completion/common/src/protocol/RpcCompletionItem.kt +++ b/platform/completion/common/src/protocol/RpcCompletionItem.kt @@ -3,6 +3,7 @@ package com.intellij.platform.completion.common.protocol import com.intellij.codeInsight.completion.CodeCompletionHandlerBase import com.intellij.codeInsight.completion.CompletionResult +import com.intellij.codeInsight.completion.command.RemDevCommandCompletionHelpers import com.intellij.codeInsight.lookup.AutoCompletionPolicy import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementInsertStopper @@ -24,6 +25,7 @@ data class RpcCompletionItem( val shouldStopLookupInsertion: Boolean = false, val isDirectInsertion: Boolean = false, val isWorthShowingInAutoPopup: Boolean = false, + val commandState: RemDevCommandCompletionHelpers.CommandState? = null ) { override fun toString(): String = buildToString("RpcCompletionItem") { field("id", id) @@ -61,6 +63,7 @@ fun CompletionResult.toRpc(): RpcCompletionItem { isDirectInsertion = element.getUserData(CodeCompletionHandlerBase.DIRECT_INSERTION) != null, prefixMatcher = prefixMatcher.toRpc(id), isWorthShowingInAutoPopup = element.isWorthShowingInAutoPopup(), + commandState = RemDevCommandCompletionHelpers.getCommandState(element) ) } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/command/CommandCompletionService.kt b/platform/lang-impl/src/com/intellij/codeInsight/completion/command/CommandCompletionService.kt index 811f3950c1ff..6edd1d2951da 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/command/CommandCompletionService.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/command/CommandCompletionService.kt @@ -2,6 +2,8 @@ package com.intellij.codeInsight.completion.command import com.intellij.codeInsight.CodeInsightBundle +import com.intellij.codeInsight.completion.command.RemDevCommandCompletionHelpers.isCommand +import com.intellij.codeInsight.completion.command.RemDevCommandCompletionHelpers.isPostfix import com.intellij.codeInsight.completion.command.configuration.ApplicationCommandCompletionService import com.intellij.codeInsight.daemon.impl.HintRenderer import com.intellij.codeInsight.editorLineStripeHint.EditorLineStripeTextRenderer @@ -16,7 +18,6 @@ import com.intellij.codeInsight.lookup.LookupManagerListener import com.intellij.codeInsight.lookup.impl.LookupCustomizer import com.intellij.codeInsight.lookup.impl.LookupImpl import com.intellij.codeInsight.template.impl.TemplateColors -import com.intellij.codeInsight.template.postfix.completion.PostfixTemplateLookupElement import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings import com.intellij.lang.Language import com.intellij.lang.LanguageExtension @@ -136,7 +137,7 @@ internal class CommandCompletionService( if (showIfMeaningless) { lookup.showIfMeaningless() // stop hiding } - lookup.arranger.additionalMatcher = CommandCompletionLookupItemMatcher(PostfixTemplatesSettings.getInstance().isShowAsSeparateGroup) + lookup.arranger.additionalMatcher = CommandCompletionLookupItemMatcher(PostfixTemplatesSettings.getInstance().isShowAsSeparateGroup) // todo settings move frontend lookup.arranger.prefixChanged(lookup) lookup.requestResize() lookup.refreshUi(false, true) @@ -186,15 +187,14 @@ internal class CommandCompletionService( } private class CommandCompletionLookupItemMatcher(private val showPostfixAsSeparateGroup: Boolean) : Condition { - override fun value(e: LookupElement): Boolean = - e.`as`(CommandCompletionLookupElement::class.java) != null || - (showPostfixAsSeparateGroup && e.`as`(PostfixTemplateLookupElement::class.java) != null) + override fun value(element: LookupElement): Boolean = + isCommand(element) || + (showPostfixAsSeparateGroup && isPostfix(element)) } private object NotPostfixCompletionLookupItemMatcher : Condition { - override fun value(e: LookupElement?): Boolean { - return e != null && e.`as`(PostfixTemplateLookupElement::class.java) == null - } + override fun value(element: LookupElement): Boolean = + !isPostfix(element) } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/command/RemDevCommandCompletionHelpers.kt b/platform/lang-impl/src/com/intellij/codeInsight/completion/command/RemDevCommandCompletionHelpers.kt new file mode 100644 index 000000000000..f4ea6c450dbb --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/command/RemDevCommandCompletionHelpers.kt @@ -0,0 +1,39 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.codeInsight.completion.command + +import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.codeInsight.template.postfix.completion.PostfixTemplateLookupElement +import com.intellij.openapi.util.Key +import org.jetbrains.annotations.ApiStatus + +@ApiStatus.Internal +object RemDevCommandCompletionHelpers { + enum class CommandState { + Postfix, + Command, + } + + private val COMMAND_FLAG: Key = Key("COMMAND_FLAG") + + fun isPostfix(element: LookupElement): Boolean = + element.`as`(PostfixTemplateLookupElement::class.java) != null || + element.getUserData(COMMAND_FLAG) == CommandState.Postfix + + fun isCommand(element: LookupElement): Boolean = + element.`as`(CommandCompletionLookupElement::class.java) != null || + element.getUserData(COMMAND_FLAG) == CommandState.Command + + fun getCommandState(element: LookupElement): CommandState? { + val flag = element.getUserData(COMMAND_FLAG) + return when { + flag != null -> flag + isCommand(element) -> CommandState.Command + isPostfix(element) -> CommandState.Postfix + else -> null + } + } + + fun installCommandState(element: LookupElement, commandState: CommandState?) { + element.putUserData(COMMAND_FLAG, commandState) + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/command/configuration/ApplicationCommandCompletionService.kt b/platform/lang-impl/src/com/intellij/codeInsight/completion/command/configuration/ApplicationCommandCompletionService.kt index 67d57c1e24bc..eb20a73d0b90 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/command/configuration/ApplicationCommandCompletionService.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/command/configuration/ApplicationCommandCompletionService.kt @@ -1,6 +1,7 @@ // Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.completion.command.configuration +import com.intellij.codeInsight.completion.NewRdCompletionSupport import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.PersistentStateComponent import com.intellij.openapi.components.RoamingType @@ -118,12 +119,27 @@ internal class AppCommandCompletionSettings( } private fun calculateFromRegistry(): Boolean { + // unit tests if (ApplicationManager.getApplication().isUnitTestMode() && - Registry.`is`("ide.completion.command.force.enabled")) return true - if (!PlatformUtils.isIntelliJ()) return false - return Registry.`is`("ide.completion.command.force.enabled") || - (!ApplicationManager.getApplication().isUnitTestMode() && - Registry.`is`("ide.completion.command.enabled")) + Registry.`is`("ide.completion.command.force.enabled")) { + return true + } + + // production + if ( + PlatformUtils.isIntelliJ() || + NewRdCompletionSupport.isFrontendRdCompletionOn() && NewRdCompletionSupport.isFrontendForIntelliJBackend() + ) { + if (Registry.`is`("ide.completion.command.force.enabled")) { + return true + } + + if (Registry.`is`("ide.completion.command.enabled")) { + return !ApplicationManager.getApplication().isUnitTestMode() + } + } + + return false } }