1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-05-15 00:34:06 +02:00

Fix(VIM-3376): Refactor the way IdeaVim executes actions

Now instead of a few hacks, we use a special function from the platform
This commit is contained in:
Alex Plate 2024-07-10 10:06:44 +03:00
parent ff44596c1a
commit 24514039e1
No known key found for this signature in database
GPG Key ID: 0B97153C8FFEC09F
7 changed files with 74 additions and 55 deletions
.teamcity/_Self
gradle.properties
src
main/java/com/maddyhome/idea/vim
test/java/org/jetbrains/plugins/ideavim/action

View File

@ -5,13 +5,13 @@ object Constants {
const val EAP_CHANNEL = "eap"
const val DEV_CHANNEL = "Dev"
const val GITHUB_TESTS = "2024.1.1"
const val NVIM_TESTS = "2024.1.1"
const val PROPERTY_TESTS = "2024.1.1"
const val LONG_RUNNING_TESTS = "2024.1.1"
const val QODANA_TESTS = "2024.1.1"
const val RELEASE = "2024.1.1"
const val GITHUB_TESTS = "2024.1.2"
const val NVIM_TESTS = "2024.1.2"
const val PROPERTY_TESTS = "2024.1.2"
const val LONG_RUNNING_TESTS = "2024.1.2"
const val QODANA_TESTS = "2024.1.2"
const val RELEASE = "2024.1.2"
const val RELEASE_DEV = "2024.1.1"
const val RELEASE_EAP = "2024.1.1"
const val RELEASE_DEV = "2024.1.2"
const val RELEASE_EAP = "2024.1.2"
}

View File

@ -16,7 +16,7 @@
# https://data.services.jetbrains.com/products?code=IC
# Maven releases are here: https://www.jetbrains.com/intellij-repository/releases
# And snapshots: https://www.jetbrains.com/intellij-repository/snapshots
ideaVersion=2024.1.1
ideaVersion=2024.1.2
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
ideaType=IC
instrumentPluginCode=true

View File

@ -36,6 +36,7 @@ import com.maddyhome.idea.vim.helper.isPrimaryEditor
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
import com.maddyhome.idea.vim.newapi.actionStartedFromVim
import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.newapi.runningIJAction
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
import java.awt.event.KeyEvent
@ -164,6 +165,7 @@ internal abstract class OctopusHandler(private val nextHandler: EditorActionHand
}
if (dataContext?.actionStartedFromVim == true) return true
if (runningIJAction) return true
return false
}

View File

@ -8,7 +8,6 @@
package com.maddyhome.idea.vim.helper
import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.AnAction
@ -17,6 +16,7 @@ import com.intellij.openapi.actionSystem.AnActionResult
import com.intellij.openapi.actionSystem.DataContextWrapper
import com.intellij.openapi.actionSystem.EmptyAction
import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.openapi.actionSystem.PlatformCoreDataKeys
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.actionSystem.ex.ActionManagerEx
import com.intellij.openapi.actionSystem.ex.ActionUtil
@ -24,10 +24,13 @@ import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.command.UndoConfirmationPolicy
import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId
import com.intellij.openapi.project.IndexNotReadyException
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.ActionCallback
import com.intellij.openapi.util.NlsContexts
import com.intellij.openapi.util.await
import com.intellij.openapi.util.registry.Registry
import com.intellij.util.SlowOperations
import com.maddyhome.idea.vim.RegisterActions
import com.maddyhome.idea.vim.api.ExecutionContext
@ -39,10 +42,11 @@ import com.maddyhome.idea.vim.handler.EditorActionHandlerBase
import com.maddyhome.idea.vim.newapi.IjNativeAction
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.runFromVimKey
import com.maddyhome.idea.vim.newapi.runningIJAction
import kotlinx.coroutines.runBlocking
import org.jetbrains.annotations.NonNls
import java.awt.Component
import javax.swing.JComponent
import javax.swing.SwingUtilities
@Service
internal class IjActionExecutor : VimActionExecutor {
@ -77,45 +81,54 @@ internal class IjActionExecutor : VimActionExecutor {
val dataContext = DataContextWrapper(context.ij)
dataContext.putUserData(runFromVimKey, true)
val actionId = ActionManager.getInstance().getId(ijAction)
val event = AnActionEvent(
null,
dataContext,
ActionPlaces.KEYBOARD_SHORTCUT,
ijAction.templatePresentation.clone(),
ActionManager.getInstance(),
0,
)
// beforeActionPerformedUpdate should be called to update the action. It fixes some rider-specific problems.
// because rider use async update method. See VIM-1819.
// This method executes inside of lastUpdateAndCheckDumb
// Another related issue: VIM-2604
// This is a hack to fix the tests and fix VIM-3332
// We should get rid of it in VIM-3376
if (actionId == "RunClass" || actionId == IdeActions.ACTION_COMMENT_LINE || actionId == IdeActions.ACTION_COMMENT_BLOCK) {
ijAction.beforeActionPerformedUpdate(event)
if (!event.presentation.isEnabled) return false
} else {
if (!ActionUtil.lastUpdateAndCheckDumb(ijAction, event, false)) return false
}
if (ijAction is ActionGroup && !event.presentation.isPerformGroup) {
// Some ActionGroups should not be performed, but shown as a popup
val popup = JBPopupFactory.getInstance()
.createActionGroupPopup(event.presentation.text, ijAction, dataContext, false, null, -1)
val component = dataContext.getData(PlatformDataKeys.CONTEXT_COMPONENT)
if (component != null) {
val window = SwingUtilities.getWindowAncestor(component)
if (window != null) {
popup.showInCenterOf(window)
}
return true
val contextComponent = PlatformCoreDataKeys.CONTEXT_COMPONENT.getData(dataContext)
?: editor?.ij?.component ?: run {
LOG.error("Can't get the context component")
return false
}
popup.showInFocusCenter()
return true
} else {
performDumbAwareWithCallbacks(ijAction, event) { ijAction.actionPerformed(event) }
return true
val result = withRunningAction {
val result = withStringRegistryOption {
ActionManager.getInstance()
.tryToExecute(ijAction, null, contextComponent, ActionPlaces.KEYBOARD_SHORTCUT, true)
}
result.wait()
}
return result.isDone
}
private fun <T> withRunningAction(block: () -> T): T {
runningIJAction = true
try {
return block()
} finally {
runningIJAction = false
}
}
private fun ActionCallback.wait(): ActionCallback {
runBlocking {
try {
await()
} catch (_: RuntimeException) {
// Nothing
// The exception happens when the action is rejected
// and the exception message explains the reason for rejection
// At the moment, we don't process this information
}
}
return this
}
@Suppress("SameParameterValue")
private fun <T> withStringRegistryOption(block: () -> T): T {
val registry = Registry.get("actionSystem.update.beforeActionPerformedUpdate")
val oldValue = registry.asString()
registry.setValue("on")
try {
return block()
} finally {
registry.setValue(oldValue)
}
}
@ -245,4 +258,8 @@ internal class IjActionExecutor : VimActionExecutor {
override fun getActionIdList(idPrefix: String): List<String> {
return ActionManager.getInstance().getActionIdList(idPrefix)
}
companion object {
private val LOG = logger<IjActionExecutor>()
}
}

View File

@ -18,6 +18,11 @@ internal open class IjEditorExecutionContext(override val context: DataContext)
// This key is stored in data context when the action is started from vim
internal val runFromVimKey = Key.create<Boolean>("RunFromVim")
/**
* Sometimes we can't rely on [runFromVimKey] because the data context is created after the execution
*/
internal var runningIJAction: Boolean = false
/**
* Check if the action with this data context was started from Vim
*/

View File

@ -16,7 +16,6 @@ import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
/**
@ -51,7 +50,6 @@ class MotionActionTest : VimTestCase() {
}
@Test
@Disabled("VIM-3376")
fun testEscapeInCommand() {
val content = """
on${c}e two

View File

@ -13,7 +13,6 @@ import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
/**
@ -74,7 +73,6 @@ class SelectKeyHandlerTest : VimTestCase() {
@TestWithoutNeovim(SkipNeovimReason.SELECT_MODE)
@Test
@Disabled("VIM-3376")
fun `test char mode backspace`() {
this.doTest(
listOf("gh", "<BS>"),
@ -100,7 +98,6 @@ class SelectKeyHandlerTest : VimTestCase() {
@TestWithoutNeovim(SkipNeovimReason.SELECT_MODE)
@Test
@Disabled("VIM-3376")
fun `test char mode delete`() {
this.doTest(
listOf("gh", "<DEL>"),