[kotlin] KTIJ-35779 Fix Implement members when body has no braces

GitOrigin-RevId: bc8a0d005478d6bbdc86936718251ec2abe7473f
This commit is contained in:
Vladimir Dolzhenko
2025-09-29 20:35:06 +00:00
committed by intellij-monorepo-bot
parent 1c37e2e155
commit f49bd55a33
6 changed files with 50 additions and 6 deletions
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.psi.psiUtil.allChildren
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import kotlin.math.min
fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
@@ -222,11 +223,13 @@ fun <T : KtDeclaration> insertMembersAfter(
commentOrSpace.copy().also { commentOrSpace.delete() }
}
}
val body = classOrObject.getOrCreateBody()
val lBrace = body.lBrace
if (lBrace != null) {
tailComments.reversed().map { body.addAfter(it, lBrace) }
val existedBody = classOrObject.body
val body = existedBody?.takeIf { it.lBrace != null } ?: run {
existedBody?.delete()
classOrObject.getOrCreateBody()
}
val lBrace = body.lBrace ?: throw KotlinExceptionWithAttachments("no lBrace").withPsiAttachment("classOrObject", classOrObject)
tailComments.reversed().forEach { body.addAfter(it, lBrace) }
var afterAnchor = anchor ?: findInsertAfterAnchor(editor, body) ?: return emptyList()
otherMembers.mapTo(insertedMembers) {
@@ -242,7 +245,7 @@ fun <T : KtDeclaration> insertMembersAfter(
afterAnchor = bound
}
} else if (bound == null && body.declarations.isNotEmpty()) {
afterAnchor = body.lBrace!!
afterAnchor = lBrace
} else if (bound != null && afterAnchor.startOffset > bound.startOffset) {
afterAnchor = bound.prevSibling!!
}
@@ -182,7 +182,7 @@ abstract class KtGenerateMembersHandler(
* implementation for the chosen symbol.
*/
context(_: KaSession)
private fun getMembersOrderedByRelativePositionsInSuperTypes(
private fun getMembersOrderedByRelativePositionsInSuperTypes(
currentClass: KtClassOrObject,
newMemberSymbolsAndGeneratedPsi: Map<KaCallableSymbol, KtCallableDeclaration>
): List<MemberEntry> {
@@ -144,6 +144,10 @@ internal class FirOverrideImplementTest : OverrideImplementTest<KtClassMember>()
super.testOverrideFunctionProperty()
}
override fun testOverrideFunctionPropertyWithoutBody() {
super.testOverrideFunctionPropertyWithoutBody()
}
override fun testOverridePrimitiveProperty() {
super.testOverridePrimitiveProperty()
}
@@ -133,6 +133,10 @@ abstract class OverrideImplementTest<T : ClassMember> : AbstractOverrideImplemen
doOverrideFileTest()
}
open fun testOverrideFunctionPropertyWithoutBody() {
doOverrideFileTest()
}
open fun testOverridePrimitiveProperty() {
doMultiImplementFileTest()
}
@@ -0,0 +1,15 @@
// FIR_IDENTICAL
open class A() {
open val method : () -> Unit? = {println("hello")}
}
fun some() : A {
return object : A()<caret>
}
// TODO: need better selection and caret
// MEMBER: "method: () -> Unit?"
// MEMBER: "equals(other: Any?): Boolean"
// MEMBER: "hashCode(): Int"
// MEMBER: "toString(): String"
@@ -0,0 +1,18 @@
// FIR_IDENTICAL
open class A() {
open val method : () -> Unit? = {println("hello")}
}
fun some() : A {
return object : A() {
override val method: () -> Unit?
get() = <selection><caret>super.method</selection>
}
}
// TODO: need better selection and caret
// MEMBER: "method: () -> Unit?"
// MEMBER: "equals(other: Any?): Boolean"
// MEMBER: "hashCode(): Int"
// MEMBER: "toString(): String"