[command-completion] IJ-CR-176087 IDEA-379364 Go to command should put caret at the end of an identifier

- delete unnecessary annotations
- improve `selectItem`

GitOrigin-RevId: fc66dce8d56eac5d0580acdf42ac8790e0cfaffd
This commit is contained in:
Mikhail Pyltsin
2025-09-30 08:50:24 +00:00
committed by intellij-monorepo-bot
parent 6b73afd322
commit 3ecfea2898
6 changed files with 32 additions and 67 deletions
@@ -2,7 +2,7 @@ a:com.intellij.codeInsight.completion.CompletionService
- *p:getVariantsFromGroupContributors(com.intellij.codeInsight.completion.CompletionParameters,com.intellij.codeInsight.completion.PrefixMatcher,com.intellij.util.Consumer):V
*:com.intellij.codeInsight.completion.command.CommandCompletionFactory
- com.intellij.openapi.project.PossiblyDumbAware
- *:adjustCaret(com.intellij.psi.PsiFile,I):java.lang.Integer
- adjustCaret(com.intellij.psi.PsiFile,I):java.lang.Integer
- commandProviders(com.intellij.openapi.project.Project,com.intellij.lang.Language):java.util.List
- createFile(com.intellij.psi.PsiFile,java.lang.String):com.intellij.psi.PsiFile
- filterSuffix():java.lang.Character
@@ -78,7 +78,6 @@ interface CommandCompletionFactory : PossiblyDumbAware {
* Adjust the caret position after GoTo command completion.
* @return the new caret position or null if no adjustment is needed
*/
@ApiStatus.Experimental
fun adjustCaret(psiFile: PsiFile, offset: Int): Int? {
val element = psiFile.findElementAt(offset) ?: return null
if (element.textRange.startOffset != offset) return null
@@ -214,7 +214,6 @@ open class ActionCompletionCommand(
return null
}
@ApiStatus.Experimental
@ApiStatus.Internal
protected open fun customizeEvent(event: AnActionEvent) {
}
@@ -1,15 +1,10 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.fir.completion.commands
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupEvent
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl
import com.intellij.openapi.util.registry.Registry
import com.intellij.testFramework.PlatformTestUtil
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import java.util.concurrent.TimeUnit
class K2CommandCompletionGoToTest : KotlinLightCodeInsightFixtureTestCase() {
override val pluginMode = KotlinPluginMode.K2
@@ -36,7 +31,7 @@ class K2CommandCompletionGoToTest : KotlinLightCodeInsightFixtureTestCase() {
}""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Go to super", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Go to super", ignoreCase = true) })
myFixture.checkResult(
"""
open class TestSuper {
@@ -63,7 +58,7 @@ class K2CommandCompletionGoToTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Go to decl", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Go to decl", ignoreCase = true) })
myFixture.checkResult(
"""
fun main() {
@@ -92,7 +87,7 @@ class K2CommandCompletionGoToTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Go to impl", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Go to impl", ignoreCase = true) })
NonBlockingReadActionImpl.waitForAsyncTaskCompletion()
myFixture.checkResult(
"""
@@ -110,16 +105,4 @@ class K2CommandCompletionGoToTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
}
private fun selectItem(item: LookupElement, completionChar: Char = 0.toChar()) {
val lookup: LookupImpl = myFixture.lookup as LookupImpl
lookup.setCurrentItem(item)
if (LookupEvent.isSpecialCompletionChar(completionChar)) {
lookup.finishLookup(completionChar)
} else {
myFixture.type(completionChar)
}
NonBlockingReadActionImpl.waitForAsyncTaskCompletion()
PlatformTestUtil.waitForAllDocumentsCommitted(10, TimeUnit.SECONDS)
}
}
@@ -1,15 +1,10 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.fir.completion.commands
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupEvent
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl
import com.intellij.openapi.util.registry.Registry
import com.intellij.testFramework.PlatformTestUtil
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import java.util.concurrent.TimeUnit
class K2CommandCompletionSurroundWithTest : KotlinLightCodeInsightFixtureTestCase() {
override val pluginMode = KotlinPluginMode.K2
@@ -45,7 +40,7 @@ class K2CommandCompletionSurroundWithTest : KotlinLightCodeInsightFixtureTestCas
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Surround with 'If'", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Surround with 'If'", ignoreCase = true) })
NonBlockingReadActionImpl.waitForAsyncTaskCompletion()
myFixture.checkResult(
"""
@@ -72,16 +67,4 @@ class K2CommandCompletionSurroundWithTest : KotlinLightCodeInsightFixtureTestCas
val elements = myFixture.completeBasic()
assertNull(elements.firstOrNull { element -> element.lookupString.contains("Surround with 'If'", ignoreCase = true) } )
}
private fun selectItem(item: LookupElement, completionChar: Char = 0.toChar()) {
val lookup: LookupImpl = myFixture.lookup as LookupImpl
lookup.setCurrentItem(item)
if (LookupEvent.isSpecialCompletionChar(completionChar)) {
lookup.finishLookup(completionChar)
} else {
myFixture.type(completionChar)
}
NonBlockingReadActionImpl.waitForAsyncTaskCompletion()
PlatformTestUtil.waitForAllDocumentsCommitted(10, TimeUnit.SECONDS)
}
}
@@ -12,10 +12,10 @@ import com.intellij.openapi.application.impl.NonBlockingReadActionImpl
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.registry.Registry
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import java.util.concurrent.TimeUnit
class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
override val pluginMode = KotlinPluginMode.K2
@@ -35,7 +35,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Change type of", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Change type of", ignoreCase = true) })
myFixture.checkResult(
"""
fun main() {
@@ -207,7 +207,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.equals("Reformat code", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.equals("Reformat code", ignoreCase = true) })
myFixture.checkResult(
"""
fun main() {
@@ -227,7 +227,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Comment with line", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Comment with line", ignoreCase = true) })
myFixture.checkResult(
"""
//fun main() {
@@ -247,7 +247,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Comment with block", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Comment with block", ignoreCase = true) })
myFixture.checkResult(
"""
/*
@@ -269,7 +269,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Delete", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Delete", ignoreCase = true) })
myFixture.checkResult(
""
)
@@ -285,7 +285,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Generate 'Secondary", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Generate 'Secondary", ignoreCase = true) })
myFixture.checkResult(
"""
class A{
@@ -316,7 +316,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Copy ref", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Copy ref", ignoreCase = true) })
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_PASTE)
myFixture.checkResult(
"""
@@ -350,7 +350,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
}""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Introduce parameter", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Introduce parameter", ignoreCase = true) })
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_PASTE)
myFixture.checkResult(
"""
@@ -482,7 +482,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
myFixture.checkResult(
"""
fun bar() {
@@ -506,7 +506,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
myFixture.checkResult(
"""
fun bar() {
@@ -530,7 +530,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
myFixture.checkResult(
"""
fun bar() {
@@ -551,7 +551,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
""".trimIndent()
)
val elements = myFixture.completeBasic()
selectItem(elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Inline", ignoreCase = true) })
myFixture.checkResult(
"""
fun bar(): Int {
@@ -606,7 +606,7 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
myFixture.type(".aaaa")
val elements = myFixture.completeBasic()
TemplateManagerImpl.setTemplateTesting(myFixture.testRootDisposable)
selectItem(elements.first { element -> element.lookupString.contains("Create method", ignoreCase = true) })
selectItem(myFixture, elements.first { element -> element.lookupString.contains("Create method", ignoreCase = true) })
NonBlockingReadActionImpl.waitForAsyncTaskCompletion()
myFixture.checkResult(
@@ -765,17 +765,18 @@ class K2CommandCompletionTest : KotlinLightCodeInsightFixtureTestCase() {
val elements = myFixture.completeBasic()
assertTrue(elements.any { element -> element.lookupString.contains("Optimize im", ignoreCase = true) })
}
}
private fun selectItem(item: LookupElement, completionChar: Char = 0.toChar()) {
val lookup: LookupImpl = myFixture.lookup as LookupImpl
lookup.setCurrentItem(item)
if (LookupEvent.isSpecialCompletionChar(completionChar)) {
lookup.finishLookup(completionChar)
} else {
myFixture.type(completionChar)
}
NonBlockingReadActionImpl.waitForAsyncTaskCompletion()
PlatformTestUtil.waitForAllDocumentsCommitted(10, TimeUnit.SECONDS)
internal fun selectItem(fixture: JavaCodeInsightTestFixture,
item: LookupElement,
completionChar: Char = 0.toChar()) {
val lookup: LookupImpl = fixture.lookup as LookupImpl
lookup.setCurrentItem(item)
if (LookupEvent.isSpecialCompletionChar(completionChar)) {
lookup.finishLookup(completionChar)
} else {
fixture.type(completionChar)
}
}
NonBlockingReadActionImpl.waitForAsyncTaskCompletion()
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
}