[inline-completion] IDEA-373460: fix 'insert inline completion' at the start of RTL text

(cherry picked from commit 4dcdf0e831082252f1e4deb123cd9d9efd4fb3e9)

IJ-MR-164742

GitOrigin-RevId: 6f4c509174230355054656ff905a68ae4a8eb82e
This commit is contained in:
Kirill.Karnaukhov
2025-06-03 12:36:25 +02:00
committed by intellij-monorepo-bot
parent e8f748f7eb
commit 84d1f0c705
3 changed files with 62 additions and 1 deletions

View File

@@ -306,6 +306,10 @@ internal class InlineCompletionTextRenderManager private constructor(
}
private fun Editor.forceLeanLeft() {
if (caretModel.currentCaret.isAtRtlLocation) {
// IDEA-373460: otherwise, we may move the caret which invalidates the current inline completion session
return
}
val visualPosition = caretModel.visualPosition
if (visualPosition.leansRight) {
val leftLeaningPosition = VisualPosition(visualPosition.line, visualPosition.column, false)

View File

@@ -0,0 +1,57 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.inline.completion
import com.intellij.codeInsight.inline.completion.elements.InlineCompletionElement
import com.intellij.codeInsight.inline.completion.elements.InlineCompletionGrayTextElement
import com.intellij.codeInsight.inline.completion.impl.SimpleInlineCompletionProvider
import com.intellij.openapi.fileTypes.PlainTextFileType
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
internal class RTLInlineCompletionTest : InlineCompletionTestCase() {
private fun registerSuggestion(vararg suggestion: InlineCompletionElement) {
InlineCompletionHandler.registerTestHandler(Provider(suggestion.toList()), testRootDisposable)
}
@Test
fun `test accept RTL inline suggestion at the start position`() = myFixture.testInlineCompletion {
init(PlainTextFileType.INSTANCE, "<caret> مرحبا، كيف حالك")
caret {
// Forcing RTL
moveRight(); moveRight()
}
registerSuggestion(InlineCompletionGrayTextElement("اليوم؟"))
callInlineCompletion()
delay()
assertInlineRender("اليوم؟")
typeChar('ا')
assertInlineRender("ليوم؟")
insertWithTab()
assertInlineHidden()
assertFileContent(" مرحبا، كيف حالكاليوم؟<caret>") // it's actually " <caret>arabic". It's just rendered this way in IJ.
}
@Test
fun `test accept RTL inline suggestion inside RTL part`() = myFixture.testInlineCompletion {
init(PlainTextFileType.INSTANCE, "<caret> مرحبا، كيف حالك")
caret {
// RTL position after the first (last) letter
moveRight(); moveRight(); moveRight()
}
registerSuggestion(InlineCompletionGrayTextElement("اليوم؟"))
callInlineCompletion()
delay()
assertInlineRender("اليوم؟")
insertWithTab()
assertFileContent(" مرحبا، كيف حالاليوم؟<caret>ك")
}
private class Provider(suggestion: List<InlineCompletionElement>) : SimpleInlineCompletionProvider(suggestion) {
override fun isEnabled(event: InlineCompletionEvent): Boolean {
return super.isEnabled(event) || event is InlineCompletionEvent.DirectCall
}
}
}

View File

@@ -81,7 +81,7 @@ internal class GradualMultiSuggestInlineCompletionProvider(
}
}
internal class SimpleInlineCompletionProvider(val suggestion: List<InlineCompletionElement>) : InlineCompletionProvider {
internal open class SimpleInlineCompletionProvider(val suggestion: List<InlineCompletionElement>) : InlineCompletionProvider {
override val id: InlineCompletionProviderID = InlineCompletionProviderID("SimpleInlineCompletionProvider")
override suspend fun getSuggestion(request: InlineCompletionRequest): InlineCompletionSingleSuggestion {