Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fixes for IdeaVim and Code With Me #819

Merged
merged 10 commits into from
Feb 23, 2024
29 changes: 0 additions & 29 deletions src/main/java/com/maddyhome/idea/vim/EventFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.ShortcutSet;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.actionSystem.TypedAction;
Expand Down Expand Up @@ -80,14 +79,6 @@ public void unregisterCustomShortcutSet(@NotNull AnAction action, @NotNull JComp
action.unregisterCustomShortcutSet(component);
}

public void addDocumentListener(@NotNull Document document, @NotNull DocumentListener listener) {
document.addDocumentListener(listener);
}

public void removeDocumentListener(@NotNull Document document, @NotNull DocumentListener listener) {
document.removeDocumentListener(listener);
}

public void addEditorFactoryListener(@NotNull EditorFactoryListener listener, @NotNull Disposable parentDisposable) {
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
}
Expand All @@ -98,51 +89,31 @@ public void addCaretListener(@NotNull Editor editor,
editor.getCaretModel().addCaretListener(listener, disposable);
}

public void removeCaretListener(@NotNull Editor editor, @NotNull CaretListener listener) {
editor.getCaretModel().removeCaretListener(listener);
}

public void addEditorMouseListener(@NotNull Editor editor,
@NotNull EditorMouseListener listener,
@NotNull Disposable disposable) {
editor.addEditorMouseListener(listener, disposable);
}

public void removeEditorMouseListener(@NotNull Editor editor, @NotNull EditorMouseListener listener) {
editor.removeEditorMouseListener(listener);
}

public void addComponentMouseListener(@NotNull Component component,
@NotNull MouseListener mouseListener,
@NotNull Disposable disposable) {
component.addMouseListener(mouseListener);
Disposer.register(disposable, () -> component.removeMouseListener(mouseListener));
}

public void removeComponentMouseListener(@NotNull Component component, @NotNull MouseListener mouseListener) {
component.removeMouseListener(mouseListener);
}

public void addEditorMouseMotionListener(@NotNull Editor editor,
@NotNull EditorMouseMotionListener listener,
@NotNull Disposable disposable) {
editor.addEditorMouseMotionListener(listener, disposable);
}

public void removeEditorMouseMotionListener(@NotNull Editor editor, @NotNull EditorMouseMotionListener listener) {
editor.removeEditorMouseMotionListener(listener);
}

public void addEditorSelectionListener(@NotNull Editor editor,
@NotNull SelectionListener listener,
@NotNull Disposable disposable) {
editor.getSelectionModel().addSelectionListener(listener, disposable);
}

public void removeEditorSelectionListener(@NotNull Editor editor, @NotNull SelectionListener listener) {
editor.getSelectionModel().removeSelectionListener(listener);
}

private @NotNull TypedAction getTypedAction() {
return TypedAction.getInstance();
}
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/maddyhome/idea/vim/PluginStartup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import com.intellij.openapi.project.ProjectManagerListener
import com.intellij.openapi.startup.ProjectActivity
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.localEditors
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.globalIjOptions

/**
Expand All @@ -36,8 +36,10 @@ internal class PluginStartup : ProjectActivity/*, LightEditCompatible*/ {
// This is a temporal workaround for VIM-2487
internal class PyNotebooksCloseWorkaround : ProjectManagerListener {
override fun projectClosingBeforeSave(project: Project) {
// TODO: Confirm context in CWM scenario
if (injector.globalIjOptions().closenotebooks) {
localEditors().forEach { editor ->
injector.editorGroup.localEditors().forEach { vimEditor ->
val editor = (vimEditor as IjVimEditor).editor
val virtualFile = EditorHelper.getVirtualFile(editor)
if (virtualFile?.extension == "ipynb") {
val fileEditorManager = FileEditorManagerEx.getInstanceEx(project)
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/com/maddyhome/idea/vim/RegisterActions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public object RegisterActions {
@JvmStatic
public fun registerActions() {
registerVimCommandActions()
registerEmptyShortcuts() // todo most likely it is not needed
registerShortcutsWithoutActions()
}

public fun findAction(id: String): EditorActionHandlerBase? {
Expand All @@ -46,12 +46,11 @@ public object RegisterActions {
IntellijCommandProvider.getCommands().forEach { parser.registerCommandAction(it) }
}

private fun registerEmptyShortcuts() {
private fun registerShortcutsWithoutActions() {
val parser = VimPlugin.getKey()

// The {char1} <BS> {char2} shortcut is handled directly by KeyHandler#handleKey, so doesn't have an action. But we
// still need to register the shortcut, to make sure the editor doesn't swallow it.
parser
.registerShortcutWithoutAction(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), MappingOwner.IdeaVim.System)
parser.registerShortcutWithoutAction(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), MappingOwner.IdeaVim.System)
}
}
1 change: 1 addition & 0 deletions src/main/java/com/maddyhome/idea/vim/VimPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ private void turnOffPlugin(boolean unsubscribe) {

if (onOffDisposable != null) {
Disposer.dispose(onOffDisposable);
onOffDisposable = null;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package com.maddyhome.idea.vim.action
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
import com.intellij.openapi.project.DumbAwareToggleAction
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.helper.MessageHelper
Expand All @@ -19,7 +20,7 @@ import com.maddyhome.idea.vim.helper.MessageHelper
* This class is used to handle the Vim Plugin enabled/disabled toggle. This is most likely used as a menu option
* but could also be used as a toolbar item.
*/
internal class VimPluginToggleAction : DumbAwareToggleAction()/*, LightEditCompatible*/ {
internal class VimPluginToggleAction : DumbAwareToggleAction(), ActionRemoteBehaviorSpecification.Disabled/*, LightEditCompatible*/ {
override fun isSelected(event: AnActionEvent): Boolean = VimPlugin.isEnabled()

override fun setSelected(event: AnActionEvent, b: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.AnActionWrapper
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
import com.intellij.openapi.application.invokeLater
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.editor.Editor
Expand Down Expand Up @@ -59,7 +60,7 @@ import javax.swing.KeyStroke
* This class is used in Which-Key plugin, so don't make it internal. Generally, we should provide a proper
* way to get ideavim keys for this plugin. See VIM-3085
*/
public class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatible*/ {
public class VimShortcutKeyAction : AnAction(), DumbAware, ActionRemoteBehaviorSpecification.Disabled/*, LightEditCompatible*/ {
private val traceTime: Boolean
get() {
// Make sure the injector is initialized
Expand Down Expand Up @@ -390,4 +391,4 @@ private class ActionEnableStatus(

private enum class LogLevel {
DEBUG, INFO, ERROR,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorCustomElementRenderer
import com.intellij.openapi.editor.Inlay
Expand All @@ -32,7 +33,7 @@ import java.util.*
import javax.swing.UIManager
import kotlin.math.max

internal class AddBlockInlaysAction : AnAction() {
internal class AddBlockInlaysAction : AnAction(), ActionRemoteBehaviorSpecification.Disabled {
override fun actionPerformed(e: AnActionEvent) {
val dataContext = e.dataContext
val editor = getEditor(dataContext) ?: return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.VisualPosition
import com.maddyhome.idea.vim.api.lineLength
Expand All @@ -22,7 +23,7 @@ import com.maddyhome.idea.vim.newapi.vim
import java.util.*
import kotlin.math.max

internal class AddInlineInlaysAction : AnAction() {
internal class AddInlineInlaysAction : AnAction(), ActionRemoteBehaviorSpecification.Disabled {
companion object {
private val random = Random()
}
Expand Down
27 changes: 23 additions & 4 deletions src/main/java/com/maddyhome/idea/vim/group/EditorGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.find.EditorSearchSession;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.client.ClientAppSession;
import com.intellij.openapi.client.ClientKind;
import com.intellij.openapi.client.ClientSessionsManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
Expand All @@ -34,6 +37,7 @@

import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.maddyhome.idea.vim.api.VimInjectorKt.injector;
import static com.maddyhome.idea.vim.api.VimInjectorKt.options;
Expand Down Expand Up @@ -204,7 +208,6 @@ public void closeEditorSearchSession(@NotNull Editor editor) {
}

public void editorCreated(@NotNull Editor editor) {
DocumentManager.INSTANCE.addListeners(editor.getDocument());
VimPlugin.getKey().registerRequiredShortcutKeys(new IjVimEditor(editor));

initLineNumbers(editor);
Expand Down Expand Up @@ -253,7 +256,6 @@ public void editorDeinit(@NotNull Editor editor, boolean isReleased) {
deinitLineNumbers(editor, isReleased);
UserDataManager.unInitializeEditor(editor);
VimPlugin.getKey().unregisterShortcutKeys(new IjVimEditor(editor));
DocumentManager.INSTANCE.removeListeners(editor.getDocument());
CaretVisualAttributesHelperKt.removeCaretsVisualAttributes(editor);
}

Expand Down Expand Up @@ -327,7 +329,7 @@ public Integer getMaxLineNumber(@NotNull Editor editor) {
@NotNull
@Override
public Collection<VimEditor> localEditors() {
return HelperKt.localEditors().stream()
return getLocalEditors()
.map(IjVimEditor::new)
.collect(Collectors.toList());
}
Expand All @@ -336,8 +338,25 @@ public Collection<VimEditor> localEditors() {
@Override
public Collection<VimEditor> localEditors(@NotNull VimDocument buffer) {
final Document document = ((IjVimDocument)buffer).getDocument();
return HelperKt.localEditors(document).stream()
return getLocalEditors()
.filter(editor -> editor.getDocument().equals(document))
.map(IjVimEditor::new)
.collect(Collectors.toList());
}

private Stream<Editor> getLocalEditors() {
// Always fetch local editors. If we're hosting a Code With Me session, any connected guests will create hidden
// editors to handle syntax highlighting, completion requests, etc. We need to make sure that IdeaVim only makes
// changes (e.g. adding search highlights) to local editors, so things don't incorrectly flow through to any Clients.
// In non-CWM scenarios, or if IdeaVim is installed on the Client, there are only ever local editors, so this will
// also work there. In Gateway remote development scenarios, IdeaVim should not be installed on the host, only the
// Client, so all should work there too.
// Note that most IdeaVim operations are in response to interactive keystrokes, which would mean that
// ClientEditorManager.getCurrentInstance would return local editors. However, some operations are in response to
// events such as document change (to update search highlights) and these can come from CWM guests, and we'd get the
// remote editors.
// This invocation will always get local editors, regardless of current context.
final ClientAppSession localSession = ClientSessionsManager.getAppSessions(ClientKind.LOCAL).get(0);
return localSession.getService(ClientEditorManager.class).editors();
}
}
5 changes: 1 addition & 4 deletions src/main/java/com/maddyhome/idea/vim/group/FileGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,11 @@ else if (FileDocumentManager.getInstance().isDocumentUnsaved(doc)) {
private static final @NotNull Logger logger = Logger.getInstance(FileGroup.class.getName());

/**
* This method listens for editor tab changes so any insert/replace modes that need to be reset can be.
* Respond to editor tab selection and remember the last used tab
*/
public static void fileEditorManagerSelectionChangedCallback(@NotNull FileEditorManagerEvent event) {
// The user has changed the editor they are working with - exit insert/replace mode, and complete any
// appropriate repeat
if (event.getOldFile() != null) {
LastTabService.getInstance(event.getManager().getProject()).setLastTab(event.getOldFile());
}
}
}

7 changes: 3 additions & 4 deletions src/main/java/com/maddyhome/idea/vim/group/KeyGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import com.maddyhome.idea.vim.api.*;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.helper.HelperKt;
import com.maddyhome.idea.vim.key.*;
import com.maddyhome.idea.vim.newapi.IjNativeAction;
import com.maddyhome.idea.vim.newapi.IjVimEditor;
Expand Down Expand Up @@ -99,9 +98,9 @@ public boolean showKeyMappings(@NotNull Set<? extends MappingMode> modes, @NotNu

@Override
public void updateShortcutKeysRegistration() {
for (Editor editor : HelperKt.localEditors()) {
unregisterShortcutKeys(new IjVimEditor(editor));
registerRequiredShortcutKeys(new IjVimEditor(editor));
for (VimEditor editor : injector.getEditorGroup().localEditors()) {
unregisterShortcutKeys(editor);
registerRequiredShortcutKeys(editor);
}
}

Expand Down
Loading
Loading