diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt index 59e6e072b21..d7a121b583f 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt @@ -41,9 +41,10 @@ internal abstract class KtGenerateMembersHandler : AbstractGenerateMembersHandle ) { // Using hackyAllowRunningOnEdt here because we don't want to pre-populate all possible textual overrides before user selection. val (commands, insertedBlocks) = hackyAllowRunningOnEdt { - val insertedBlocks = analyse(classOrObject) { + val entryMembers = analyse(classOrObject) { this.generateMembers(editor, classOrObject, selectedElements, copyDoc) } + val insertedBlocks = insertMembersAccordingToPreferredOrder(entryMembers, editor, classOrObject) // Reference shortening is done in a separate analysis session because the session need to be aware of the newly generated // members. val commands = analyse(classOrObject) { @@ -81,7 +82,7 @@ internal abstract class KtGenerateMembersHandler : AbstractGenerateMembersHandle currentClass: KtClassOrObject, selectedElements: Collection, copyDoc: Boolean - ): List { + ): List { if (selectedElements.isEmpty()) return emptyList() val selectedMemberSymbolsAndGeneratedPsi: Map = selectedElements.associate { it.symbol to generateMember(currentClass.project, it, currentClass, copyDoc) @@ -93,14 +94,11 @@ internal abstract class KtGenerateMembersHandler : AbstractGenerateMembersHandle // Insert members at the cursor position if the cursor is within the class body. Or, if there is no body, generate the body and put // stuff in it. if (classBody == null || isCursorInsideClassBodyExcludingBraces(classBody, offset)) { - return runWriteAction { - listOf(InsertedBlock(insertMembersAfter(editor, currentClass, selectedMemberSymbolsAndGeneratedPsi.values))) - } + return selectedMemberSymbolsAndGeneratedPsi.values.map { MemberEntry.NewEntry(it) } } // Insert members at positions such that the result aligns with ordering of members in super types. - val orderedMembers = getMembersOrderedByRelativePositionsInSuperTypes(currentClass, selectedMemberSymbolsAndGeneratedPsi) - return insertMembersAccordingToPreferredOrder(orderedMembers, classBody.lBrace, editor, currentClass) + return getMembersOrderedByRelativePositionsInSuperTypes(currentClass, selectedMemberSymbolsAndGeneratedPsi) } private fun isCursorInsideClassBodyExcludingBraces(classBody: KtClassBody, offset: Int): Boolean { @@ -222,16 +220,15 @@ internal abstract class KtGenerateMembersHandler : AbstractGenerateMembersHandle @OptIn(ExperimentalStdlibApi::class) private fun insertMembersAccordingToPreferredOrder( symbolsInPreferredOrder: List, - classLeftBrace: PsiElement?, editor: Editor, currentClass: KtClassOrObject ): List { - require(symbolsInPreferredOrder.isNotEmpty()) { "symbolsInPreferredOrder must not be empty" } + if (symbolsInPreferredOrder.isEmpty()) return emptyList() var firstAnchor: PsiElement? = null if (symbolsInPreferredOrder.first() is MemberEntry.NewEntry) { val firstExistingEntry = symbolsInPreferredOrder.firstIsInstanceOrNull() if (firstExistingEntry != null) { - firstAnchor = firstExistingEntry.psi.prevSiblingOfSameType() ?: classLeftBrace + firstAnchor = firstExistingEntry.psi.prevSiblingOfSameType() ?: currentClass.body?.lBrace } } diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtOverrideMembersHandler.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtOverrideMembersHandler.kt index 6da4f5dd867..829465b09f0 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtOverrideMembersHandler.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtOverrideMembersHandler.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassKind import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtIconProvider.getIcon -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithModality import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT import org.jetbrains.kotlin.idea.frontend.api.tokens.hackyAllowRunningOnEdt diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOverrideImplementTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOverrideImplementTest.kt index 2f5ad5e160c..e6b31e83045 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOverrideImplementTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOverrideImplementTest.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.dumpErrorLines import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.InTextDirectivesUtils