Skip to content

Commit

Permalink
Support new marks
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexPl292 committed Dec 10, 2021
1 parent ea61e87 commit 134c68c
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 136 deletions.
4 changes: 2 additions & 2 deletions .teamcity/_Self/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ object Constants {
const val EAP_CHANNEL = "eap"
const val DEV_CHANNEL = "Dev"

const val VERSION = "1.9.0"
const val VERSION = "1.9.1"
const val DEV_VERSION = "1.10.0"

const val GITHUB_TESTS = "LATEST-EAP-SNAPSHOT"
Expand All @@ -14,7 +14,7 @@ object Constants {
const val PROPERTY_TESTS = "LATEST-EAP-SNAPSHOT"
const val LONG_RUNNING_TESTS = "LATEST-EAP-SNAPSHOT"
const val QODANA_TESTS = "LATEST-EAP-SNAPSHOT"
const val RELEASE = "2021.2.2"
const val RELEASE = "2021.3"
const val RELEASE_DEV = "LATEST-EAP-SNAPSHOT"
const val RELEASE_EAP = "LATEST-EAP-SNAPSHOT"
}
16 changes: 8 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ configurations {

tasks {
// Include tests for testing on LATEST-EAP-SNAPSHOT
// val test by getting(Test::class) {
// isScanForTestClasses = false
// // Only run tests from classes that end with "Test"
// include("**/*Test.class")
// include("**/*Tests.class")
// exclude("**/ParserTest.class")
// }
//
val test by getting(Test::class) {
isScanForTestClasses = false
// Only run tests from classes that end with "Test"
include("**/*Test.class")
include("**/*Tests.class")
exclude("**/ParserTest.class")
}

compileJava {
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# suppress inspection "UnusedProperty" for whole file

ideaVersion=2021.2.2
ideaVersion=LATEST-EAP-SNAPSHOT
downloadIdeaSources=true
instrumentPluginCode=true
version=SNAPSHOT
Expand Down
19 changes: 11 additions & 8 deletions src/main/java/com/maddyhome/idea/vim/common/Marks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

package com.maddyhome.idea.vim.common

import com.intellij.ide.bookmarks.Bookmark
import com.intellij.ide.bookmarks.BookmarkManager
import com.intellij.ide.bookmark.BookmarkType
import com.intellij.ide.bookmark.BookmarksManager
import com.intellij.ide.bookmark.LineBookmark
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.LogicalPosition
import com.intellij.openapi.project.Project
Expand Down Expand Up @@ -79,26 +80,28 @@ data class VimMark(
}
}

class IntellijMark(bookmark: Bookmark, override val col: Int, project: Project?) : Mark {
class IntellijMark(bookmark: LineBookmark, override val col: Int, project: Project?) : Mark {

private val project: WeakReference<Project?> = WeakReference(project)

override val key = bookmark.mnemonic
override val key = BookmarksManager.getInstance(project)?.getType(bookmark)?.mnemonic!!
override val logicalLine: Int
get() = getMark()?.line ?: 0
override val filename: String
get() = getMark()?.file?.path ?: ""
override val protocol: String
get() = getMark()?.file?.let { MarkGroup.extractProtocol(it) } ?: ""

override fun isClear(): Boolean = getMark()?.isValid?.not() ?: false
override fun isClear(): Boolean = getMark() == null
override fun clear() {
val mark = getMark() ?: return
getProject()?.let { project -> BookmarkManager.getInstance(project).removeBookmark(mark) }
getProject()?.let { project -> BookmarksManager.getInstance(project)?.remove(mark) }
}

private fun getMark(): Bookmark? =
getProject()?.let { project -> BookmarkManager.getInstance(project).findBookmarkForMnemonic(key) }
private fun getMark(): LineBookmark? =
getProject()?.let {
project -> BookmarksManager.getInstance(project)?.getBookmark(BookmarkType.get(key)) as? LineBookmark
}

private fun getProject(): Project? {
val proj = project.get() ?: return null
Expand Down
102 changes: 37 additions & 65 deletions src/main/java/com/maddyhome/idea/vim/group/MarkGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@

package com.maddyhome.idea.vim.group;

import com.intellij.ide.bookmarks.Bookmark;
import com.intellij.ide.bookmarks.BookmarkManager;
import com.intellij.ide.bookmarks.BookmarksListener;
import com.intellij.ide.bookmark.BookmarkGroup;
import com.intellij.ide.bookmark.BookmarkType;
import com.intellij.ide.bookmark.BookmarksManager;
import com.intellij.ide.bookmark.LineBookmark;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.RoamingType;
import com.intellij.openapi.components.State;
Expand All @@ -47,7 +48,6 @@
import com.maddyhome.idea.vim.helper.SearchHelper;
import com.maddyhome.idea.vim.vimscript.services.OptionService;
import org.jdom.Element;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -221,7 +221,7 @@ else if (GLOBAL_MARKS.indexOf(ch) >= 0) {
HashMap<Character, Mark> fmarks = getFileMarks(editor.getDocument());
if (fmarks == null) return false;

Bookmark systemMark = createOrGetSystemMark(ch, lp.line, editor);
@Nullable LineBookmark systemMark = SystemMarks.createOrGetSystemMark(ch, lp.line, editor);
Mark mark;
if (systemMark != null) {
mark = new IntellijMark(systemMark, lp.column, editor.getProject());
Expand All @@ -238,22 +238,6 @@ else if (GLOBAL_MARKS.indexOf(ch) >= 0) {
return true;
}

private @Nullable Bookmark createOrGetSystemMark(char ch, int line, @NotNull Editor editor) {
if (!VimPlugin.getOptionService().isSet(new OptionService.Scope.LOCAL(editor), "ideamarks", "ideamarks")) return null;
final Project project = editor.getProject();
if (project == null) return null;
final BookmarkManager bookmarkManager = BookmarkManager.getInstance(project);

Bookmark bookmark = bookmarkManager.findBookmarkForMnemonic(ch);
if (bookmark != null && bookmark.getLine() == line) return bookmark;

final VirtualFile virtualFile = EditorHelper.getVirtualFile(editor);
if (virtualFile == null) return null;
bookmark = bookmarkManager.addTextBookmark(virtualFile, line, "");
bookmarkManager.setMnemonic(bookmark, ch);
return bookmark;
}

public static String extractProtocol(@NotNull VirtualFile vf) {
return VirtualFileManager.extractProtocol(vf.getUrl());
}
Expand Down Expand Up @@ -746,68 +730,56 @@ public void documentChanged(@NotNull DocumentEvent event) {
}
}

public static class MarkListener implements BookmarksListener {

private final Project project;
private Bookmark bookmarkTemplate = null;
public static class VimBookmarksListener implements com.intellij.ide.bookmark.BookmarksListener {
private final Project myProject;

@Contract(pure = true)
public MarkListener(Project project) {
this.project = project;
public VimBookmarksListener(Project project) {
myProject = project;
}

/**
* IJ has an interesting approach in mnemonic marks initialization. Firstly it creates an unnamed mark,
* then updates it. In general, it creates two events: one for creation and one for mnemonic set.
* However, when IJ starts and reads existing marks from caches, it creates marks with mnemonics already.
*/
@Override
public void bookmarkAdded(@NotNull Bookmark b) {
public void bookmarkAdded(@NotNull BookmarkGroup group, com.intellij.ide.bookmark.@NotNull Bookmark bookmark) {
if (!VimPlugin.isEnabled()) return;
if (!VimPlugin.getOptionService().isSet(OptionService.Scope.GLOBAL.INSTANCE, "ideamarks", "ideamarks")) return;
if (b.getMnemonic() == '\u0000') {
bookmarkTemplate = b;
} else {
createVimMark(b);
}

if (!(bookmark instanceof LineBookmark)) return;
BookmarksManager bookmarksManager = BookmarksManager.getInstance(myProject);
if (bookmarksManager == null) return;
BookmarkType type = bookmarksManager.getType(bookmark);
if (type == null) return;

char mnemonic = type.getMnemonic();
if (GLOBAL_MARKS.indexOf(mnemonic) == -1) return;

createVimMark((LineBookmark)bookmark, mnemonic);
}

@Override
public void bookmarkRemoved(@NotNull Bookmark b) {
public void bookmarkRemoved(@NotNull BookmarkGroup group, com.intellij.ide.bookmark.@NotNull Bookmark bookmark) {
if (!VimPlugin.isEnabled()) return;
if (!VimPlugin.getOptionService().isSet(OptionService.Scope.GLOBAL.INSTANCE, "ideamarks", "ideamarks")) return;

char ch = b.getMnemonic();
if (!(bookmark instanceof LineBookmark)) return;
BookmarksManager bookmarksManager = BookmarksManager.getInstance(myProject);
if (bookmarksManager == null) return;
BookmarkType type = bookmarksManager.getType(bookmark);
if (type == null) return;
char ch = type.getMnemonic();
if (GLOBAL_MARKS.indexOf(ch) != -1) {
FileMarks<Character, Mark> fmarks = VimPlugin.getMark().getFileMarks(b.getFile().getPath());
FileMarks<Character, Mark> fmarks = VimPlugin.getMark().getFileMarks(((LineBookmark)bookmark).getFile().getPath());
fmarks.remove(ch);
VimPlugin.getMark().globalMarks.remove(ch);
// No need to call mark.clear()
}
}

@Override
public void bookmarkChanged(@NotNull Bookmark b) {
if (!VimPlugin.isEnabled()) return;
/* IJ sets named marks in two steps. Firstly it creates an unnamed mark, then adds a mnemonic */
if (!VimPlugin.getOptionService().isSet(OptionService.Scope.GLOBAL.INSTANCE, "ideamarks", "ideamarks")) return;
if (b != bookmarkTemplate) return;
bookmarkTemplate = null;

createVimMark(b);
}

private void createVimMark(@NotNull Bookmark b) {
char ch = b.getMnemonic();
if (GLOBAL_MARKS.indexOf(ch) != -1) {
int col = 0;
Editor editor = EditorHelper.getEditor(b.getFile());
if (editor != null) col = editor.getCaretModel().getCurrentCaret().getLogicalPosition().column;
IntellijMark mark = new IntellijMark(b, col, project);
FileMarks<Character, Mark> fmarks = VimPlugin.getMark().getFileMarks(b.getFile().getPath());
fmarks.put(ch, mark);
VimPlugin.getMark().globalMarks.put(ch, mark);
}
private void createVimMark(@NotNull LineBookmark b, char mnemonic) {
int col = 0;
Editor editor = EditorHelper.getEditor(b.getFile());
if (editor != null) col = editor.getCaretModel().getCurrentCaret().getLogicalPosition().column;
IntellijMark mark = new IntellijMark(b, col, myProject);
FileMarks<Character, Mark> fmarks = VimPlugin.getMark().getFileMarks(b.getFile().getPath());
fmarks.put(mnemonic, mark);
VimPlugin.getMark().globalMarks.put(mnemonic, mark);
}
}

Expand Down
90 changes: 90 additions & 0 deletions src/main/java/com/maddyhome/idea/vim/group/SystemMarks.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2021 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2021 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.maddyhome.idea.vim.group

import com.intellij.ide.bookmark.Bookmark
import com.intellij.ide.bookmark.BookmarkType
import com.intellij.ide.bookmark.BookmarksManager
import com.intellij.ide.bookmark.LineBookmark
import com.intellij.ide.bookmark.providers.LineBookmarkProvider
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.vimscript.services.OptionService.Scope.LOCAL

class SystemMarks {
companion object {
@JvmStatic
fun createOrGetSystemMark(ch: Char, line: Int, editor: Editor): LineBookmark? {
if (!VimPlugin.getOptionService().isSet(LOCAL(editor), "ideamarks", "ideamarks")) return null

val project = editor.project ?: return null
val type = BookmarkType.get(ch)
if (type == BookmarkType.DEFAULT) return null

val bookmarksManager = BookmarksManager.getInstance(project) ?: return null
val foundBookmark = bookmarksManager.getBookmark(type)
if (foundBookmark != null) {
if (foundBookmark is LineBookmark && foundBookmark.line == line) {
return foundBookmark
}
bookmarksManager.remove(foundBookmark)
}

return project.createLineBookmark(editor, line, ch)
}
}
}

internal fun Project.createLineBookmark(editor: Editor, line: Int, mnemonic: Char): LineBookmark? {
val bookmarksManager = BookmarksManager.getInstance(this) ?: return null
val lineBookmarkProvider = LineBookmarkProvider.find(this) ?: return null
val bookmark = lineBookmarkProvider.createBookmark(editor, line) as LineBookmark? ?: return null
val type = BookmarkType.get(mnemonic)
if (type == BookmarkType.DEFAULT) return null

val group = bookmarksManager.defaultGroup ?: bookmarksManager.addGroup("IdeaVim", true) ?: return null
if (group.canAdd(bookmark)) {
group.add(bookmark, type)
return bookmark
}
return null
}

internal fun Bookmark.mnemonic(project: Project?): Char {
return BookmarksManager.getInstance(project)?.getType(this)!!.mnemonic
}
4 changes: 2 additions & 2 deletions src/main/resources/META-INF/includes/VimListeners.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
<listener class="com.maddyhome.idea.vim.listener.IdeaSpecifics$VimTemplateManagerListener"
topic="com.intellij.codeInsight.template.TemplateManagerListener"/>

<listener class="com.maddyhome.idea.vim.group.MarkGroup$MarkListener"
topic="com.intellij.ide.bookmarks.BookmarksListener"/>
<listener class="com.maddyhome.idea.vim.group.MarkGroup$VimBookmarksListener"
topic="com.intellij.ide.bookmark.BookmarksListener"/>

<listener class="com.maddyhome.idea.vim.listener.IdeaSpecifics$VimFindModelListener"
topic="com.intellij.find.FindModelListener"/>
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@

<!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version -->
<!-- Check for [Version Update] tag in YouTrack as well -->
<idea-version since-build="203"/>
<idea-version since-build="213"/>

<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform (including CWM) -->
<depends>com.intellij.modules.platform</depends>
Expand Down
10 changes: 5 additions & 5 deletions src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
*/
package org.jetbrains.plugins.ideavim

import com.intellij.ide.bookmarks.Bookmark
import com.intellij.ide.bookmarks.BookmarkManager
import com.intellij.ide.bookmark.BookmarksManager
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.ide.highlighter.XmlFileType
import com.intellij.json.JsonFileType
Expand Down Expand Up @@ -78,7 +77,6 @@ import com.maddyhome.idea.vim.vimscript.services.OptionService
import com.maddyhome.idea.vim.vimscript.services.VariableServiceImpl
import org.assertj.core.api.Assertions
import org.junit.Assert
import java.util.function.Consumer
import javax.swing.KeyStroke

/**
Expand Down Expand Up @@ -129,8 +127,10 @@ abstract class VimTestCase : UsefulTestCase() {
override fun tearDown() {
val swingTimer = swingTimer
swingTimer?.stop()
val bookmarkManager = BookmarkManager.getInstance(myFixture.project)
bookmarkManager.validBookmarks.forEach(Consumer { bookmark: Bookmark? -> bookmarkManager.removeBookmark(bookmark!!) })
val bookmarksManager = BookmarksManager.getInstance(myFixture.project)
bookmarksManager?.bookmarks?.forEach { bookmark ->
bookmarksManager.remove(bookmark)
}
SelectionVimListenerSuppressor.lock().use { myFixture.tearDown() }
ExEntryPanel.getInstance().deactivate(false)
(VimPlugin.getVariableService() as VariableServiceImpl).clear()
Expand Down
Loading

0 comments on commit 134c68c

Please sign in to comment.