diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMembersHandler.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMembersHandler.kt index 166481c452b..3e49935b45b 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMembersHandler.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMembersHandler.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea.core.overrideImplement import com.intellij.openapi.project.Project +import com.intellij.util.SmartList import org.jetbrains.kotlin.descriptors.* import java.util.* @@ -29,14 +30,19 @@ public class OverrideMembersHandler : OverrideImplementMembersHandler() { val overridden = member.overriddenDescriptors if (overridden.any { it.modality == Modality.FINAL || it.visibility.normalize() == Visibilities.PRIVATE }) continue - val realSuperToImmediates = LinkedHashMap>() + class Data( + val realSuper: CallableMemberDescriptor, + val immediateSupers: MutableList = SmartList() + ) + + val byOriginalRealSupers = LinkedHashMap() for (immediateSuper in overridden) { for (realSuper in toRealSupers(immediateSuper)) { - realSuperToImmediates.getOrPut(realSuper) { ArrayList(1) }.add(immediateSuper) + byOriginalRealSupers.getOrPut(realSuper.original) { Data(realSuper) }.immediateSupers.add(immediateSuper) } } - val realSupers = realSuperToImmediates.keySet() + val realSupers = byOriginalRealSupers.values().map { it.realSuper } val nonAbstractRealSupers = realSupers.filter { it.modality != Modality.ABSTRACT } val realSupersToUse = if (nonAbstractRealSupers.isNotEmpty()) { nonAbstractRealSupers @@ -46,7 +52,7 @@ public class OverrideMembersHandler : OverrideImplementMembersHandler() { } for (realSuper in realSupersToUse) { - val immediateSupers = realSuperToImmediates[realSuper]!! + val immediateSupers = byOriginalRealSupers[realSuper.original]!!.immediateSupers assert(immediateSupers.isNotEmpty()) val immediateSuperToUse = if (immediateSupers.size() == 1) { @@ -76,7 +82,7 @@ public class OverrideMembersHandler : OverrideImplementMembersHandler() { } val overridden = immediateSuper.overriddenDescriptors assert(overridden.isNotEmpty()) - return overridden.flatMap { toRealSupers(it) }.toSet() + return overridden.flatMap { toRealSupers(it) }.distinctBy { it.original } } override fun getChooserTitle() = "Override Members" diff --git a/idea/testData/codeInsight/overrideImplement/duplicatedAnyMembersBug.kt b/idea/testData/codeInsight/overrideImplement/duplicatedAnyMembersBug.kt new file mode 100644 index 00000000000..adffe1ffe58 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/duplicatedAnyMembersBug.kt @@ -0,0 +1,8 @@ +open class A { +} + +interface I + +class B : A(), I { + +} diff --git a/idea/testData/codeInsight/overrideImplement/duplicatedAnyMembersBug.kt.after b/idea/testData/codeInsight/overrideImplement/duplicatedAnyMembersBug.kt.after new file mode 100644 index 00000000000..bba212e0262 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/duplicatedAnyMembersBug.kt.after @@ -0,0 +1,18 @@ +open class A { +} + +interface I + +class B : A(), I { + override fun equals(other: Any?): Boolean { + return super.equals(other) + } + + override fun hashCode(): Int { + return super.hashCode() + } + + override fun toString(): String { + return super.toString() + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt index 2f40f38f51d..e25acc18361 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.idea.codeInsight -import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMembersHandler import org.jetbrains.kotlin.idea.test.PluginTestCaseBase public class OverrideImplementTest : AbstractOverrideImplementTest() { @@ -228,4 +227,8 @@ public class OverrideImplementTest : AbstractOverrideImplementTest() { public fun testGenericSuperClass() { doOverrideFileTest("size") } + + public fun testDuplicatedAnyMembersBug() { + doMultiOverrideFileTest() + } }