diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt index f7d32833967..b4a931a5c70 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt @@ -24,6 +24,7 @@ import com.intellij.psi.PsiDocCommentOwner import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.core.TemplateKind import org.jetbrains.kotlin.idea.core.getFunctionBodyTextFromTemplate @@ -32,6 +33,7 @@ import org.jetbrains.kotlin.idea.j2k.IdeaDocCommentConverter import org.jetbrains.kotlin.idea.kdoc.KDocElementFactory import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes +import org.jetbrains.kotlin.idea.util.expectedDescriptors import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.findDocComment.findDocComment @@ -40,6 +42,7 @@ import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.renderer.* import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden +import org.jetbrains.kotlin.util.findCallableMemberBySignature interface OverrideMemberChooserObject : ClassMember { sealed class BodyType { @@ -118,7 +121,12 @@ fun OverrideMemberChooserObject.generateMember(targetClass: KtClassOrObject, cop else -> error("Unknown member to override: $descriptor") } - if (!targetClass.hasActualModifier()) { + if (targetClass.hasActualModifier()) { + val expectClassDescriptors = targetClass.resolveToDescriptorIfAny()?.expectedDescriptors() ?: emptyList() + if (expectClassDescriptors.any { (it as? ClassDescriptor)?.findCallableMemberBySignature(immediateSuper)?.isExpect == true }) { + newMember.addModifier(KtTokens.ACTUAL_KEYWORD) + } + } else { newMember.removeModifier(KtTokens.IMPL_KEYWORD) newMember.removeModifier(KtTokens.ACTUAL_KEYWORD) } diff --git a/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/header/header.kt b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/header/header.kt new file mode 100644 index 00000000000..07f45ec2985 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/header/header.kt @@ -0,0 +1,7 @@ +interface I { + fun f() +} + +expect class C : I { + override fun f() +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/header/header.kt.after b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/header/header.kt.after new file mode 100644 index 00000000000..07f45ec2985 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/header/header.kt.after @@ -0,0 +1,7 @@ +interface I { + fun f() +} + +expect class C : I { + override fun f() +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/jvm/jvm.kt b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/jvm/jvm.kt new file mode 100644 index 00000000000..b8c3322a6f9 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/jvm/jvm.kt @@ -0,0 +1,4 @@ +// "Implement members" "true" +// DISABLE-ERRORS + +actual class C : I \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/jvm/jvm.kt.after b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/jvm/jvm.kt.after new file mode 100644 index 00000000000..040eb32c115 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/jvm/jvm.kt.after @@ -0,0 +1,8 @@ +// "Implement members" "true" +// DISABLE-ERRORS + +actual class C : I { + actual override fun f() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTestGenerated.java index 6455ee86e89..1c5456f157e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTestGenerated.java @@ -184,6 +184,11 @@ public class QuickFixMultiModuleTestGenerated extends AbstractQuickFixMultiModul runTest("idea/testData/multiModuleQuickFix/functionTypeReceiverToParameterByImpl/"); } + @TestMetadata("implementAbstractExpectMemberInheritedFromInterface") + public void testImplementAbstractExpectMemberInheritedFromInterface() throws Exception { + runTest("idea/testData/multiModuleQuickFix/implementAbstractExpectMemberInheritedFromInterface/"); + } + @TestMetadata("implementMembersInImplClassNonImplInheritor") public void testImplementMembersInImplClassNonImplInheritor() throws Exception { runTest("idea/testData/multiModuleQuickFix/implementMembersInImplClassNonImplInheritor/");