1
0
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:
Emanuel Gestosa 2023-08-07 16:14:56 +01:00 committed by lippfi
parent db14afdf3a
commit 23c2b008c9
6 changed files with 111 additions and 265 deletions
vim-engine
build.gradle.kts
src
main/kotlin/com/maddyhome/idea/vim/regexp
nfa/matcher
parser/visitors
test/kotlin/com/maddyhome/idea/vim/regexp

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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]

View File

@ -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 {

View File

@ -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")
}
}

View File

@ -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
}
}