mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-02-25 02:46:01 +01:00
implementing cursor and using mockito to mock editor
rebasing
This commit is contained in:
parent
db14afdf3a
commit
23c2b008c9
vim-engine
build.gradle.kts
src
main/kotlin/com/maddyhome/idea/vim/regexp
test/kotlin/com/maddyhome/idea/vim/regexp
@ -53,6 +53,8 @@ dependencies {
|
||||
ksp(project(":annotation-processors"))
|
||||
implementation(project(":annotation-processors"))
|
||||
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:$kotlinxSerializationVersion")
|
||||
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:5.0.0")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.regexp.nfa.matcher
|
||||
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.common.Offset
|
||||
|
||||
public class CursorMatcher : Matcher {
|
||||
override fun matches(editor: VimEditor, index: Int): Boolean {
|
||||
return editor.carets().map { it.offset }.contains(Offset(index))
|
||||
}
|
||||
|
||||
override fun isEpsilon(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ package com.maddyhome.idea.vim.regexp.parser.visitors
|
||||
import com.maddyhome.idea.vim.regexp.nfa.MultiDelimiter
|
||||
import com.maddyhome.idea.vim.regexp.nfa.NFA
|
||||
import com.maddyhome.idea.vim.regexp.nfa.matcher.CharacterMatcher
|
||||
import com.maddyhome.idea.vim.regexp.nfa.matcher.CursorMatcher
|
||||
import com.maddyhome.idea.vim.regexp.nfa.matcher.DotMatcher
|
||||
import com.maddyhome.idea.vim.regexp.parser.generated.RegexParser
|
||||
import com.maddyhome.idea.vim.regexp.parser.generated.RegexParserBaseVisitor
|
||||
@ -81,6 +82,10 @@ internal class PatternVisitor : RegexParserBaseVisitor<NFA>() {
|
||||
return NFA.fromMatcher(DotMatcher(true))
|
||||
}
|
||||
|
||||
override fun visitCursor(ctx: RegexParser.CursorContext?): NFA {
|
||||
return NFA.fromMatcher(CursorMatcher())
|
||||
}
|
||||
|
||||
private fun cleanLiteralChar(str : String) : Char {
|
||||
return if (str.length == 2 && str[0] == '\\') str[1]
|
||||
else str[0]
|
||||
|
@ -8,7 +8,9 @@
|
||||
|
||||
package com.maddyhome.idea.vim.regexp
|
||||
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.common.Offset
|
||||
import com.maddyhome.idea.vim.regexp.match.VimMatchResult
|
||||
import com.maddyhome.idea.vim.regexp.nfa.NFA
|
||||
import com.maddyhome.idea.vim.regexp.parser.RegexParser
|
||||
@ -17,6 +19,8 @@ import com.maddyhome.idea.vim.regexp.parser.visitors.PatternVisitor
|
||||
import org.antlr.v4.runtime.CharStreams
|
||||
import org.antlr.v4.runtime.CommonTokenStream
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
@ -312,7 +316,7 @@ class NFATest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `text sequence of any characters with newline`() {
|
||||
fun `test sequence of any characters with newline`() {
|
||||
assertCorrectRange(
|
||||
"Lorem Ipsum\n" +
|
||||
"\n" +
|
||||
@ -325,8 +329,44 @@ class NFATest {
|
||||
)
|
||||
}
|
||||
|
||||
private fun assertCorrectRange(text: CharSequence, pattern: String, expectedResultRange: IntRange, offset: Int = 0) {
|
||||
val editor = buildEditor(text)
|
||||
@Test
|
||||
fun `test single cursor`() {
|
||||
assertCorrectRange(
|
||||
"Lorem Ipsum\n" +
|
||||
"\n" +
|
||||
"Lorem ipsum dolor sit amet,\n" +
|
||||
"consectetur adipiscing elit\n" +
|
||||
"Sed in orci mauris.\n" +
|
||||
"Cras id tellus in ex imperdiet egestas.",
|
||||
"Lo\\%#rem",
|
||||
0 until 5,
|
||||
carets = listOf(2)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test single cursor should fail`() {
|
||||
assertFailure(
|
||||
"Lorem Ipsum\n" +
|
||||
"\n" +
|
||||
"Lorem ipsum dolor sit amet,\n" +
|
||||
"consectetur adipiscing elit\n" +
|
||||
"Sed in orci mauris.\n" +
|
||||
"Cras id tellus in ex imperdiet egestas.",
|
||||
"\\%#Lorem",
|
||||
carets = listOf(2)
|
||||
)
|
||||
}
|
||||
|
||||
private fun assertCorrectRange(
|
||||
text: CharSequence,
|
||||
pattern: String,
|
||||
expectedResultRange:
|
||||
IntRange,
|
||||
offset: Int = 0,
|
||||
carets: List<Int> = emptyList()
|
||||
) {
|
||||
val editor = buildEditor(text, carets)
|
||||
val nfa = buildNFA(pattern)
|
||||
val result = nfa.simulate(editor, offset)
|
||||
when (result) {
|
||||
@ -335,8 +375,15 @@ class NFATest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertCorrectGroupRange(text: CharSequence, pattern: String, expectedResultRange: IntRange, groupNumber: Int, offset: Int = 0) {
|
||||
val editor = buildEditor(text)
|
||||
private fun assertCorrectGroupRange(
|
||||
text: CharSequence,
|
||||
pattern: String,
|
||||
expectedResultRange: IntRange,
|
||||
groupNumber: Int,
|
||||
offset: Int = 0,
|
||||
carets: List<Int> = emptyList()
|
||||
) {
|
||||
val editor = buildEditor(text, carets)
|
||||
val nfa = buildNFA(pattern)
|
||||
val result = nfa.simulate(editor, offset)
|
||||
when (result) {
|
||||
@ -345,14 +392,24 @@ class NFATest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertFailure(text: CharSequence, pattern: String, offset: Int = 0) {
|
||||
val editor = buildEditor(text)
|
||||
private fun assertFailure(text: CharSequence, pattern: String, offset: Int = 0, carets: List<Int> = emptyList()) {
|
||||
val editor = buildEditor(text, carets)
|
||||
val nfa = buildNFA(pattern)
|
||||
assertTrue(nfa.simulate(editor, offset) is VimMatchResult.Failure)
|
||||
}
|
||||
|
||||
private fun buildEditor(text: CharSequence) : VimEditor {
|
||||
return VimEditorMock(text)
|
||||
private fun buildEditor(text: CharSequence, carets: List<Int> = emptyList()) : VimEditor {
|
||||
val editorMock = mock<VimEditor>()
|
||||
whenever(editorMock.text()).thenReturn(text)
|
||||
|
||||
val trueCarets = ArrayList<VimCaret>()
|
||||
for (caret in carets) {
|
||||
val caretMock = mock<VimCaret>()
|
||||
whenever(caretMock.offset).thenReturn(Offset(caret))
|
||||
trueCarets.add(caretMock)
|
||||
}
|
||||
whenever(editorMock.carets()).thenReturn(trueCarets)
|
||||
return editorMock
|
||||
}
|
||||
|
||||
private fun buildNFA(pattern: String) : NFA {
|
||||
|
@ -1,254 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.regexp
|
||||
|
||||
import com.maddyhome.idea.vim.api.BufferPosition
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||
import com.maddyhome.idea.vim.api.LineDeleteShift
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimCaretListener
|
||||
import com.maddyhome.idea.vim.api.VimDocument
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.VimScrollingModel
|
||||
import com.maddyhome.idea.vim.api.VimSelectionModel
|
||||
import com.maddyhome.idea.vim.api.VimVisualPosition
|
||||
import com.maddyhome.idea.vim.api.VirtualFile
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.command.SelectionType
|
||||
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||
import com.maddyhome.idea.vim.common.ChangesListener
|
||||
import com.maddyhome.idea.vim.common.EditorLine
|
||||
import com.maddyhome.idea.vim.common.LiveRange
|
||||
import com.maddyhome.idea.vim.common.Offset
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
|
||||
/**
|
||||
* Simplified implementation of the VimEditor interface used just for testing.
|
||||
* Currently only has a way to retrieve text. Need to mock other functionalities
|
||||
* like carets, marks, etc.
|
||||
*/
|
||||
internal class VimEditorMock(val text: CharSequence,
|
||||
override val lfMakesNewLine: Boolean = false,
|
||||
override var vimChangeActionSwitchMode: VimStateMachine.Mode? = null,
|
||||
override var vimKeepingVisualOperatorAction: Boolean = false,
|
||||
override var vimLastSelectionType: SelectionType? = null,
|
||||
override var insertMode: Boolean = false,
|
||||
override val document: VimDocument = VimDocumentMock()
|
||||
) : VimEditor {
|
||||
|
||||
override fun text(): CharSequence {
|
||||
return text
|
||||
}
|
||||
override fun fileSize(): Long {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun nativeLineCount(): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getLineRange(line: EditorLine.Pointer): Pair<Offset, Offset> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun carets(): List<VimCaret> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun nativeCarets(): List<VimCaret> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun forEachCaret(action: (VimCaret) -> Unit) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun forEachNativeCaret(action: (VimCaret) -> Unit, reverse: Boolean) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun primaryCaret(): VimCaret {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun currentCaret(): VimCaret {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isWritable(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isDocumentWritable(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isOneLineMode(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun search(
|
||||
pair: Pair<Offset, Offset>,
|
||||
editor: VimEditor,
|
||||
shiftType: LineDeleteShift,
|
||||
): Pair<Pair<Offset, Offset>, LineDeleteShift>? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun updateCaretsVisualAttributes() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun updateCaretsVisualPosition() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun offsetToBufferPosition(offset: Int): BufferPosition {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun bufferPositionToOffset(position: BufferPosition): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun offsetToVisualPosition(offset: Int): VimVisualPosition {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun visualPositionToOffset(position: VimVisualPosition): Offset {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun visualPositionToBufferPosition(position: VimVisualPosition): BufferPosition {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun bufferPositionToVisualPosition(position: BufferPosition): VimVisualPosition {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getVirtualFile(): VirtualFile? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun deleteString(range: TextRange) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getSelectionModel(): VimSelectionModel {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getScrollingModel(): VimScrollingModel {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun removeCaret(caret: VimCaret) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun removeSecondaryCarets() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun vimSetSystemBlockSelectionSilently(start: BufferPosition, end: BufferPosition) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getLineStartOffset(line: Int): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getLineEndOffset(line: Int): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun addCaretListener(listener: VimCaretListener) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun removeCaretListener(listener: VimCaretListener) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isDisposed(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun removeSelection() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getPath(): String? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun extractProtocol(): String? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun exitInsertMode(context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun exitSelectModeNative(adjustCaret: Boolean) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isTemplateActive(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun startGuardedBlockChecking() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun stopGuardedBlockChecking() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun hasUnsavedChanges(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getLastVisualLineColumnNumber(line: Int): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun createLiveMarker(start: Offset, end: Offset): LiveRange {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun createIndentBySize(size: Int): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getCollapsedRegionAtOffset(offset: Int): TextRange? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun <T : ImmutableVimCaret> findLastVersionOfCaret(caret: T): T? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
private class VimDocumentMock : VimDocument {
|
||||
override fun addChangeListener(listener: ChangesListener) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun removeChangeListener(listener: ChangesListener) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getOffsetGuard(offset: Offset): LiveRange? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -8,9 +8,13 @@
|
||||
|
||||
package com.maddyhome.idea.vim.regexp
|
||||
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.common.Offset
|
||||
import com.maddyhome.idea.vim.regexp.match.VimMatchResult
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.kotlin.whenever
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.fail
|
||||
|
||||
@ -129,7 +133,17 @@ class VimRegexTest {
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildEditor(text: CharSequence) : VimEditor {
|
||||
return VimEditorMock(text)
|
||||
private fun buildEditor(text: CharSequence, carets: List<Int> = emptyList()) : VimEditor {
|
||||
val editorMock = Mockito.mock<VimEditor>()
|
||||
whenever(editorMock.text()).thenReturn(text)
|
||||
|
||||
val trueCarets = ArrayList<VimCaret>()
|
||||
for (caret in carets) {
|
||||
val caretMock = Mockito.mock<VimCaret>()
|
||||
whenever(caretMock.offset).thenReturn(Offset(caret))
|
||||
trueCarets.add(caretMock)
|
||||
}
|
||||
whenever(editorMock.carets()).thenReturn(trueCarets)
|
||||
return editorMock
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user