SmartPointers in Smart Completion for anonymous object generation

#KT-32615 Fixed
This commit is contained in:
Alexander Podkhalyuzin
2019-11-01 13:24:00 +03:00
parent d321f4626f
commit d2ae39489f
5 changed files with 36 additions and 11 deletions
@@ -0,0 +1,5 @@
import test.foo.Foo
fun foo() {
val x: Foo = FooC<caret>
}
@@ -0,0 +1,9 @@
package test.foo
interface Foo {
fun run(): Unit
}
abstract class FooClass : Foo {
}
@@ -0,0 +1,10 @@
import test.foo.Foo
import test.foo.FooClass
fun foo() {
val x: Foo = object : FooClass() {
override fun run() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}
@@ -22,6 +22,8 @@ class SmartCompletionMultifileHandlerTest : KotlinCompletionTestCase() {
fun testAnonymousObjectGenericJava() { doTest() } fun testAnonymousObjectGenericJava() { doTest() }
fun testImportAnonymousObject() { doTest() }
fun testNestedSamAdapter() { doTest(lookupString = "Nested") } fun testNestedSamAdapter() { doTest(lookupString = "Nested") }
override fun setUp() { override fun setUp() {
@@ -19,10 +19,7 @@ package org.jetbrains.kotlin.idea.core
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ScrollType import com.intellij.openapi.editor.ScrollType
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.*
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.SmartPointerManager
import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.SmartList import com.intellij.util.SmartList
@@ -225,7 +222,8 @@ fun <T : KtDeclaration> insertMembersAfter(
members.ifEmpty { return emptyList() } members.ifEmpty { return emptyList() }
val project = classOrObject.project val project = classOrObject.project
return runWriteAction { return runWriteAction {
val insertedMembers = SmartList<T>() val insertedMembers = SmartList<SmartPsiElementPointer<T>>()
fun insertedMembersElements() = insertedMembers.mapNotNull { it.element }
val (parameters, otherMembers) = members.partition { it is KtParameter } val (parameters, otherMembers) = members.partition { it is KtParameter }
@@ -233,7 +231,7 @@ fun <T : KtDeclaration> insertMembersAfter(
if (classOrObject !is KtClass) return@mapNotNullTo null if (classOrObject !is KtClass) return@mapNotNullTo null
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(classOrObject.createPrimaryConstructorParameterListIfAbsent().addParameter(it as KtParameter) as T) SmartPointerManager.createPointer(classOrObject.createPrimaryConstructorParameterListIfAbsent().addParameter(it as KtParameter) as T)
} }
if (otherMembers.isNotEmpty()) { if (otherMembers.isNotEmpty()) {
@@ -260,20 +258,21 @@ fun <T : KtDeclaration> insertMembersAfter(
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(body.addAfter(it, afterAnchor) as T).apply { afterAnchor = this } SmartPointerManager.createPointer((body.addAfter(it, afterAnchor) as T).apply { afterAnchor = this })
} }
} }
@Suppress("UNCHECKED_CAST") val resultMembers = ShortenReferences.DEFAULT.process(insertedMembers) as Collection<T> ShortenReferences.DEFAULT.process(insertedMembersElements())
val firstElement = resultMembers.firstOrNull() ?: return@runWriteAction emptyList()
val firstElement = insertedMembersElements().firstOrNull() ?: return@runWriteAction emptyList()
if (editor != null) { if (editor != null) {
moveCaretIntoGeneratedElement(editor, firstElement) moveCaretIntoGeneratedElement(editor, firstElement)
} }
val codeStyleManager = CodeStyleManager.getInstance(project) val codeStyleManager = CodeStyleManager.getInstance(project)
resultMembers.forEach { codeStyleManager.reformat(it) } insertedMembersElements().forEach { codeStyleManager.reformat(it) }
resultMembers.toList() insertedMembersElements().toList()
} }
} }