From 3612c2983ee04425a5ff3098a50834eab9ec1a48 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 13 Nov 2018 15:41:23 +0300 Subject: [PATCH] Use OverrideMemberChooserObject to generate actual decls in quick-fixes This can fix a lot of issues related to inexact generation, in particular #KT-27093 Fixed --- .../ImplementMembersHandler.kt | 4 +- .../OverrideMemberChooserObject.kt | 233 ++++++++++++------ .../OverrideMembersHandler.kt | 2 +- .../KotlinGenerateTestSupportActionBase.kt | 2 +- ...KotlinGenerateTestSupportActionBase.kt.181 | 2 +- .../kotlin/idea/actions/generate/utils.kt | 2 +- .../ImplementAbstractMemberIntention.kt | 2 +- .../ImplementAbstractMemberIntention.kt.181 | 2 +- .../quickfix/expectactual/AddActualFix.kt | 7 +- .../quickfix/expectactual/CreateActualFix.kt | 86 +++---- .../abstract/js/Abstract.kt.after | 2 +- .../multiModuleQuickFix/class/jvm/My.kt.after | 7 +- .../jvm/My.kt.after | 3 +- .../jvm/My.kt.after | 3 +- .../jvm/My.kt.after | 3 +- .../jvm/My.kt.after | 2 +- .../classSomeProperties/jvm/My.kt.after | 4 +- .../jvm/My.kt.after | 4 +- .../proj_common_dep(stdlib)/common.kt | 7 + .../proj_common_dep(stdlib)/common.kt.after | 7 + .../proj_jvm_dep(stdlib)/MyGenerator.kt | 1 + .../proj_jvm_dep(stdlib)/MyGenerator.kt.after | 8 + .../jvm/WithCompanion.kt.after | 3 +- .../jvm/C.kt.after | 3 +- .../enum/js/MyEnum.kt.after | 2 +- .../interface/jvm/Interface.kt.after | 3 +- .../nested/jvm/WithNested.kt.after | 6 +- .../property/jvm/x.kt.after | 2 +- .../a_jvm_test/test/testHelper.kt.after | 3 +- .../withTestDummy/a_jvm/testHelper.kt.after | 3 +- .../QuickFixMultiModuleTestGenerated.java | 5 + 31 files changed, 261 insertions(+), 162 deletions(-) create mode 100644 idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt create mode 100644 idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt.after create mode 100644 idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt create mode 100644 idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt.after diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/ImplementMembersHandler.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/ImplementMembersHandler.kt index 10c1e778bb1..a9ffad94089 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/ImplementMembersHandler.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/ImplementMembersHandler.kt @@ -34,7 +34,7 @@ import org.jetbrains.kotlin.resolve.OverrideResolver open class ImplementMembersHandler : OverrideImplementMembersHandler(), IntentionAction { override fun collectMembersToGenerate(descriptor: ClassDescriptor, project: Project): Collection { return OverrideResolver.getMissingImplementations(descriptor) - .map { OverrideMemberChooserObject.create(project, it, it, OverrideMemberChooserObject.BodyType.EMPTY) } + .map { OverrideMemberChooserObject.create(project, it, it, OverrideMemberChooserObject.BodyType.FROM_TEMPLATE) } } override fun getChooserTitle() = "Implement Members" @@ -67,6 +67,6 @@ class ImplementAsConstructorParameter : ImplementMembersHandler() { override fun collectMembersToGenerate(descriptor: ClassDescriptor, project: Project): Collection { return OverrideResolver.getMissingImplementations(descriptor) .filter { it is PropertyDescriptor } - .map { OverrideMemberChooserObject.create(project, it, it, OverrideMemberChooserObject.BodyType.EMPTY, true) } + .map { OverrideMemberChooserObject.create(project, it, it, OverrideMemberChooserObject.BodyType.FROM_TEMPLATE, true) } } } \ No newline at end of file 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 156b372a402..218808800b6 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 @@ -28,6 +28,7 @@ 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 +import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType.* import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject import org.jetbrains.kotlin.idea.j2k.IdeaDocCommentConverter import org.jetbrains.kotlin.idea.kdoc.KDocElementFactory @@ -45,9 +46,10 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden import org.jetbrains.kotlin.util.findCallableMemberBySignature interface OverrideMemberChooserObject : ClassMember { - sealed class BodyType { + sealed class BodyType(val requiresReturn: Boolean = true) { object NO_BODY : BodyType() - object EMPTY : BodyType() + object EMPTY_OR_TEMPLATE : BodyType(requiresReturn = false) + object FROM_TEMPLATE : BodyType(requiresReturn = false) object SUPER : BodyType() object QUALIFIED_SUPER : BodyType() @@ -60,27 +62,36 @@ interface OverrideMemberChooserObject : ClassMember { val preferConstructorParameter: Boolean companion object { - fun create(project: Project, - descriptor: CallableMemberDescriptor, - immediateSuper: CallableMemberDescriptor, - bodyType: BodyType, - preferConstructorParameter: Boolean = false + fun create( + project: Project, + descriptor: CallableMemberDescriptor, + immediateSuper: CallableMemberDescriptor, + bodyType: BodyType, + preferConstructorParameter: Boolean = false ): OverrideMemberChooserObject { val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) return if (declaration != null) { - WithDeclaration(descriptor, declaration, immediateSuper, bodyType, preferConstructorParameter) - } - else { + create(declaration, descriptor, immediateSuper, bodyType, preferConstructorParameter) + } else { WithoutDeclaration(descriptor, immediateSuper, bodyType, preferConstructorParameter) } } + fun create( + declaration: PsiElement, + descriptor: CallableMemberDescriptor, + immediateSuper: CallableMemberDescriptor, + bodyType: BodyType, + preferConstructorParameter: Boolean = false + ): OverrideMemberChooserObject = + WithDeclaration(descriptor, declaration, immediateSuper, bodyType, preferConstructorParameter) + private class WithDeclaration( - descriptor: CallableMemberDescriptor, - declaration: PsiElement, - override val immediateSuper: CallableMemberDescriptor, - override val bodyType: BodyType, - override val preferConstructorParameter: Boolean + descriptor: CallableMemberDescriptor, + declaration: PsiElement, + override val immediateSuper: CallableMemberDescriptor, + override val bodyType: BodyType, + override val preferConstructorParameter: Boolean ) : DescriptorMemberChooserObject(declaration, descriptor), OverrideMemberChooserObject { override val descriptor: CallableMemberDescriptor @@ -88,40 +99,68 @@ interface OverrideMemberChooserObject : ClassMember { } private class WithoutDeclaration( - override val descriptor: CallableMemberDescriptor, - override val immediateSuper: CallableMemberDescriptor, - override val bodyType: BodyType, - override val preferConstructorParameter: Boolean - ) : MemberChooserObjectBase(DescriptorMemberChooserObject.getText(descriptor), DescriptorMemberChooserObject.getIcon(null, descriptor)), OverrideMemberChooserObject { + override val descriptor: CallableMemberDescriptor, + override val immediateSuper: CallableMemberDescriptor, + override val bodyType: BodyType, + override val preferConstructorParameter: Boolean + ) : MemberChooserObjectBase( + DescriptorMemberChooserObject.getText(descriptor), DescriptorMemberChooserObject.getIcon(null, descriptor) + ), OverrideMemberChooserObject { override fun getParentNodeDelegate(): MemberChooserObject? { val parentClassifier = descriptor.containingDeclaration as? ClassifierDescriptor ?: return null - return MemberChooserObjectBase(DescriptorMemberChooserObject.getText(parentClassifier), DescriptorMemberChooserObject.getIcon(null, parentClassifier)) + return MemberChooserObjectBase( + DescriptorMemberChooserObject.getText(parentClassifier), DescriptorMemberChooserObject.getIcon(null, parentClassifier) + ) } } } } -fun OverrideMemberChooserObject.generateMember(targetClass: KtClassOrObject, copyDoc: Boolean): KtCallableDeclaration { - val project = targetClass.project +fun OverrideMemberChooserObject.generateTopLevelActual( + copyDoc: Boolean, + project: Project +) = generateMember(null, copyDoc, project, forceActual = true) +fun OverrideMemberChooserObject.generateActualMember( + targetClass: KtClassOrObject, + copyDoc: Boolean +) = generateMember(targetClass, copyDoc, targetClass.project, forceActual = true) + +fun OverrideMemberChooserObject.generateMember( + targetClass: KtClassOrObject, + copyDoc: Boolean +) = generateMember(targetClass, copyDoc, targetClass.project, forceActual = false) + +private fun OverrideMemberChooserObject.generateMember( + targetClass: KtClassOrObject?, + copyDoc: Boolean, + project: Project, + forceActual: Boolean +): KtCallableDeclaration { val descriptor = immediateSuper val bodyType = when { - targetClass.hasExpectModifier() -> OverrideMemberChooserObject.BodyType.NO_BODY - descriptor.extensionReceiverParameter != null -> OverrideMemberChooserObject.BodyType.EMPTY + targetClass?.hasExpectModifier() == true -> NO_BODY + descriptor.extensionReceiverParameter != null -> FROM_TEMPLATE else -> bodyType } - if (preferConstructorParameter && descriptor is PropertyDescriptor) return generateConstructorParameter(project, descriptor) + val renderer = if (forceActual) ACTUAL_RENDERER else OVERRIDE_RENDERER + + if (preferConstructorParameter && descriptor is PropertyDescriptor) { + return generateConstructorParameter(project, descriptor, renderer) + } val newMember: KtCallableDeclaration = when (descriptor) { - is SimpleFunctionDescriptor -> generateFunction(project, descriptor, bodyType) - is PropertyDescriptor -> generateProperty(project, descriptor, bodyType) + is FunctionDescriptor -> generateFunction(project, descriptor, renderer, bodyType) + is PropertyDescriptor -> generateProperty(project, descriptor, renderer, bodyType) else -> error("Unknown member to override: $descriptor") } - if (targetClass.hasActualModifier()) { + if (forceActual) { + newMember.addModifier(KtTokens.ACTUAL_KEYWORD) + } else if (targetClass?.hasActualModifier() == true) { val expectClassDescriptors = targetClass.resolveToDescriptorIfAny()?.expectedDescriptors()?.filterIsInstance().orEmpty() if (expectClassDescriptors.any { expectClassDescriptor -> @@ -143,7 +182,7 @@ fun OverrideMemberChooserObject.generateMember(targetClass: KtClassOrObject, cop findDocComment(superDeclaration) is PsiDocCommentOwner -> { val kDocText = superDeclaration.docComment?.let { IdeaDocCommentConverter.convertDocComment(it) } - if (kDocText.isNullOrEmpty()) null else KDocElementFactory(project).createKDocFromText(kDocText!!) + if (kDocText.isNullOrEmpty()) null else KDocElementFactory(project).createKDocFromText(kDocText) } else -> null } @@ -171,6 +210,12 @@ private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions { presentableUnresolvedTypes = true } +private val ACTUAL_RENDERER = OVERRIDE_RENDERER.withOptions { + modifiers = setOf(DescriptorRendererModifier.ANNOTATIONS) + renderConstructorKeyword = true + secondaryConstructorsAsPrimary = false +} + private fun PropertyDescriptor.wrap(): PropertyDescriptor { val delegate = copy(containingDeclaration, Modality.OPEN, visibility, kind, true) as PropertyDescriptor val newDescriptor = object : PropertyDescriptor by delegate { @@ -181,74 +226,112 @@ private fun PropertyDescriptor.wrap(): PropertyDescriptor { } private fun FunctionDescriptor.wrap(): FunctionDescriptor { + if (this is ClassConstructorDescriptor) return this.wrap() return object : FunctionDescriptor by this { override fun isExpect() = false override fun getModality() = Modality.OPEN override fun getReturnType() = this@wrap.returnType?.approximateFlexibleTypes(preferNotNull = true, preferStarForRaw = true) override fun getOverriddenDescriptors() = listOf(this@wrap) - override fun accept(visitor: DeclarationDescriptorVisitor, data: D) = visitor.visitFunctionDescriptor(this, data) + override fun accept(visitor: DeclarationDescriptorVisitor, data: D) = + visitor.visitFunctionDescriptor(this, data) } } -private fun generateProperty(project: Project, descriptor: PropertyDescriptor, bodyType: OverrideMemberChooserObject.BodyType): KtProperty { - val newDescriptor = descriptor.wrap() - val body = - if (bodyType != OverrideMemberChooserObject.BodyType.NO_BODY) { - buildString { - append("\nget()") - append(" = ") - append(generateUnsupportedOrSuperCall(project, descriptor, bodyType)) - if (descriptor.isVar) { - append("\nset(value) {}") - } - } - } else "" - return KtPsiFactory(project).createProperty(OVERRIDE_RENDERER.render(newDescriptor) + body) +private fun ClassConstructorDescriptor.wrap(): ClassConstructorDescriptor { + return object : ClassConstructorDescriptor by this { + override fun isExpect() = false + override fun getModality() = Modality.FINAL + override fun getReturnType() = this@wrap.returnType.approximateFlexibleTypes(preferNotNull = true, preferStarForRaw = true) + override fun getOverriddenDescriptors() = listOf(this@wrap) + override fun accept(visitor: DeclarationDescriptorVisitor, data: D) = + visitor.visitConstructorDescriptor(this, data) + } } -private fun generateConstructorParameter(project: Project, descriptor: PropertyDescriptor): KtParameter { - val newDescriptor = descriptor.wrap() - newDescriptor.setSingleOverridden(descriptor) - return KtPsiFactory(project).createParameter(OVERRIDE_RENDERER.render(newDescriptor)) -} - -private fun generateFunction(project: Project, descriptor: FunctionDescriptor, bodyType: OverrideMemberChooserObject.BodyType): KtNamedFunction { +private fun generateProperty( + project: Project, + descriptor: PropertyDescriptor, + renderer: DescriptorRenderer, + bodyType: OverrideMemberChooserObject.BodyType +): KtProperty { val newDescriptor = descriptor.wrap() val returnType = descriptor.returnType val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType) - val body = if (bodyType != OverrideMemberChooserObject.BodyType.NO_BODY) { - val delegation = generateUnsupportedOrSuperCall(project, descriptor, bodyType) - "{" + (if (returnsNotUnit && bodyType != OverrideMemberChooserObject.BodyType.EMPTY) "return " else "") + delegation + "\n}" - } - else "" + val body = + if (bodyType != NO_BODY) { + buildString { + append("\nget()") + append(" = ") + append(generateUnsupportedOrSuperCall(project, descriptor, bodyType, !returnsNotUnit)) + if (descriptor.isVar) { + append("\nset(value) {}") + } + } + } else "" + return KtPsiFactory(project).createProperty(renderer.render(newDescriptor) + body) +} - return KtPsiFactory(project).createFunction(OVERRIDE_RENDERER.render(newDescriptor) + body) +private fun generateConstructorParameter(project: Project, descriptor: PropertyDescriptor, renderer: DescriptorRenderer): KtParameter { + val newDescriptor = descriptor.wrap() + newDescriptor.setSingleOverridden(descriptor) + return KtPsiFactory(project).createParameter(renderer.render(newDescriptor)) +} + +private fun generateFunction( + project: Project, + descriptor: FunctionDescriptor, + renderer: DescriptorRenderer, + bodyType: OverrideMemberChooserObject.BodyType +): KtFunction { + val newDescriptor = descriptor.wrap() + + val returnType = descriptor.returnType + val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType) + + val body = if (bodyType != NO_BODY) { + val delegation = generateUnsupportedOrSuperCall(project, descriptor, bodyType, !returnsNotUnit) + val returnPrefix = if (returnsNotUnit && bodyType.requiresReturn) "return " else "" + "{$returnPrefix$delegation\n}" + } else "" + + val factory = KtPsiFactory(project) + val functionText = renderer.render(newDescriptor) + body + return when (descriptor) { + is ClassConstructorDescriptor -> factory.createSecondaryConstructor(functionText) + else -> factory.createFunction(functionText) + } } fun generateUnsupportedOrSuperCall( - project: Project, - descriptor: CallableMemberDescriptor, - bodyType: OverrideMemberChooserObject.BodyType + project: Project, + descriptor: CallableMemberDescriptor, + bodyType: OverrideMemberChooserObject.BodyType, + canBeEmpty: Boolean = true ): String { - if (bodyType == OverrideMemberChooserObject.BodyType.EMPTY) { - val templateKind = if (descriptor is FunctionDescriptor) TemplateKind.FUNCTION else TemplateKind.PROPERTY_INITIALIZER - return getFunctionBodyTextFromTemplate(project, - templateKind, - descriptor.name.asString(), - descriptor.returnType?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } ?: "Unit", - null) - } - else { - return buildString { + val effectiveBodyType = if (!canBeEmpty && bodyType == EMPTY_OR_TEMPLATE) FROM_TEMPLATE else bodyType + when (effectiveBodyType) { + EMPTY_OR_TEMPLATE -> return "" + FROM_TEMPLATE -> { + val templateKind = if (descriptor is FunctionDescriptor) TemplateKind.FUNCTION else TemplateKind.PROPERTY_INITIALIZER + return getFunctionBodyTextFromTemplate( + project, + templateKind, + descriptor.name.asString(), + descriptor.returnType?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } ?: "Unit", + null + ) + } + else -> return buildString { if (bodyType is OverrideMemberChooserObject.BodyType.Delegate) { append(bodyType.receiverName) - } - else { + } else { append("super") - if (bodyType == OverrideMemberChooserObject.BodyType.QUALIFIED_SUPER) { - val superClassFqName = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(descriptor.containingDeclaration as ClassifierDescriptor) + if (bodyType == QUALIFIED_SUPER) { + val superClassFqName = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName( + descriptor.containingDeclaration as ClassifierDescriptor + ) append("<").append(superClassFqName).append(">") } } 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 10bc2aac7b9..da993ff9daf 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 @@ -69,7 +69,7 @@ class OverrideMembersHandler(private val preferConstructorParameters: Boolean = descriptor.kind == ClassKind.INTERFACE && realSuper.builtIns.isMemberOfAny(realSuper) -> OverrideMemberChooserObject.BodyType.NO_BODY immediateSuperToUse.modality == Modality.ABSTRACT -> - OverrideMemberChooserObject.BodyType.EMPTY + OverrideMemberChooserObject.BodyType.FROM_TEMPLATE realSupersToUse.size == 1 -> OverrideMemberChooserObject.BodyType.SUPER else -> diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt index aa3d4ba524b..4e496e83e4b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt @@ -184,7 +184,7 @@ abstract class KotlinGenerateTestSupportActionBase( val functionDescriptor = functionInPlace.unsafeResolveToDescriptor() as FunctionDescriptor val overriddenDescriptors = functionDescriptor.overriddenDescriptors val bodyText = when (overriddenDescriptors.size) { - 0 -> generateUnsupportedOrSuperCall(project, functionDescriptor, BodyType.EMPTY) + 0 -> generateUnsupportedOrSuperCall(project, functionDescriptor, BodyType.FROM_TEMPLATE) 1 -> generateUnsupportedOrSuperCall(project, overriddenDescriptors.single(), BodyType.SUPER) else -> generateUnsupportedOrSuperCall(project, overriddenDescriptors.first(), BodyType.QUALIFIED_SUPER) } diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt.181 b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt.181 index 34e7dbebefc..4b260c14500 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt.181 +++ b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateTestSupportActionBase.kt.181 @@ -184,7 +184,7 @@ abstract class KotlinGenerateTestSupportActionBase( val functionDescriptor = functionInPlace.unsafeResolveToDescriptor() as FunctionDescriptor val overriddenDescriptors = functionDescriptor.overriddenDescriptors val bodyText = when (overriddenDescriptors.size) { - 0 -> generateUnsupportedOrSuperCall(project, functionDescriptor, BodyType.EMPTY) + 0 -> generateUnsupportedOrSuperCall(project, functionDescriptor, BodyType.FROM_TEMPLATE) 1 -> generateUnsupportedOrSuperCall(project, overriddenDescriptors.single(), BodyType.SUPER) else -> generateUnsupportedOrSuperCall(project, overriddenDescriptors.first(), BodyType.QUALIFIED_SUPER) } diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/generate/utils.kt b/idea/src/org/jetbrains/kotlin/idea/actions/generate/utils.kt index 1d6949b2c29..7bd580981e5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/generate/utils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/generate/utils.kt @@ -80,6 +80,6 @@ fun confirmMemberRewrite(targetClass: KtClass, vararg descriptors: FunctionDescr fun generateFunctionSkeleton(descriptor: FunctionDescriptor, targetClass: KtClassOrObject): KtNamedFunction { return OverrideMemberChooserObject - .create(targetClass.project, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY) + .create(targetClass.project, descriptor, descriptor, OverrideMemberChooserObject.BodyType.FROM_TEMPLATE) .generateMember(targetClass, false) as KtNamedFunction } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt index 1a8aff86794..9d313534f05 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt @@ -126,7 +126,7 @@ abstract class ImplementAbstractMemberIntentionBase : val chooserObject = OverrideMemberChooserObject.create(member.project, descriptorToImplement, descriptorToImplement, - OverrideMemberChooserObject.BodyType.EMPTY, + OverrideMemberChooserObject.BodyType.FROM_TEMPLATE, preferConstructorParameters) OverrideImplementMembersHandler.generateMembers(editor, targetClass, listOf(chooserObject), false) } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt.181 b/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt.181 index b949ccc1c13..f1f6c059788 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt.181 +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ImplementAbstractMemberIntention.kt.181 @@ -126,7 +126,7 @@ abstract class ImplementAbstractMemberIntentionBase : val chooserObject = OverrideMemberChooserObject.create(member.project, descriptorToImplement, descriptorToImplement, - OverrideMemberChooserObject.BodyType.EMPTY, + OverrideMemberChooserObject.BodyType.FROM_TEMPLATE, preferConstructorParameters) OverrideImplementMembersHandler.generateMembers(editor, targetClass, listOf(chooserObject), false) } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/AddActualFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/AddActualFix.kt index 4fa913889fe..652ade8a564 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/AddActualFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/AddActualFix.kt @@ -19,13 +19,16 @@ package org.jetbrains.kotlin.idea.quickfix.expectactual import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project +import com.intellij.psi.codeStyle.CodeStyleManager import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer @@ -53,7 +56,9 @@ class AddActualFix( listOfNotNull(element.primaryConstructor) ) for (declaration in pureActualClass.declarations) { - element.addDeclaration(declaration) + val actualDeclaration = element.addDeclaration(declaration) + val reformatted = CodeStyleManager.getInstance(project).reformat(actualDeclaration) + ShortenReferences.DEFAULT.process(reformatted as KtElement) } val primaryConstructor = pureActualClass.primaryConstructor if (element.primaryConstructor == null && primaryConstructor != null) { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateActualFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateActualFix.kt index 81ba16420b9..363590f5fe6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateActualFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateActualFix.kt @@ -25,7 +25,6 @@ import com.intellij.openapi.project.Project import com.intellij.psi.JavaDirectoryService import com.intellij.psi.codeStyle.CodeStyleManager import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -36,10 +35,12 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent import org.jetbrains.kotlin.idea.core.* +import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject +import org.jetbrains.kotlin.idea.core.overrideImplement.generateActualMember +import org.jetbrains.kotlin.idea.core.overrideImplement.generateTopLevelActual import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory import org.jetbrains.kotlin.idea.refactoring.createKotlinFile -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.actualsForExpected import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.runWriteAction @@ -192,7 +193,7 @@ class CreateActualPropertyFix( actualPlatform: MultiTargetPlatform.Specific ) : CreateActualFix(property, actualModule, actualPlatform, { project, element -> val descriptor = element.toDescriptor() as? PropertyDescriptor - descriptor?.let { generateProperty(project, element, descriptor, actualNeeded = true) } + descriptor?.let { generateProperty(project, element, descriptor) } }) { override val elementType = "property" @@ -204,7 +205,7 @@ class CreateActualFunctionFix( actualPlatform: MultiTargetPlatform.Specific ) : CreateActualFix(function, actualModule, actualPlatform, { project, element -> val descriptor = element.toDescriptor() as? FunctionDescriptor - descriptor?.let { generateFunction(project, element, descriptor, actualNeeded = true) } + descriptor?.let { generateFunction(project, element, descriptor) } }) { override val elementType = "function" @@ -294,6 +295,7 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass( } } } + actualClass.replaceExpectModifier(actualNeeded) declLoop@ for (expectedDeclaration in expectedClass.declarations.filter { !it.exists() }) { val descriptor = expectedDeclaration.toDescriptor() ?: continue @@ -309,8 +311,8 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass( continue@declLoop } when (expectedDeclaration) { - is KtFunction -> generateFunction(project, expectedDeclaration, descriptor as FunctionDescriptor, actualNeeded = true) - is KtProperty -> generateProperty(project, expectedDeclaration, descriptor as PropertyDescriptor, actualNeeded = true) + is KtFunction -> generateFunction(project, expectedDeclaration, descriptor as FunctionDescriptor, actualClass) + is KtProperty -> generateProperty(project, expectedDeclaration, descriptor as PropertyDescriptor, actualClass) else -> continue@declLoop } } @@ -329,9 +331,7 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass( it.removeParameterDefaultValues() } - return actualClass.apply { - replaceExpectModifier(actualNeeded) - } + return actualClass } private val forbiddenAnnotationFqNames = setOf( @@ -340,41 +340,20 @@ private val forbiddenAnnotationFqNames = setOf( ExperimentalUsageChecker.USE_EXPERIMENTAL_FQ_NAME ) -private fun KtPsiFactory.generateFunction( +private fun generateFunction( project: Project, expectedFunction: KtFunction, descriptor: FunctionDescriptor, - actualNeeded: Boolean + targetClass: KtClassOrObject? = null ): KtFunction { - val returnType = descriptor.returnType - val body = run { - if (expectedFunction.hasBody()) { - "" - } else if (returnType != null && !KotlinBuiltIns.isUnit(returnType)) { - val delegation = getFunctionBodyTextFromTemplate( - project, - TemplateKind.FUNCTION, - descriptor.name.asString(), - IdeDescriptorRenderers.SOURCE_CODE.renderType(returnType) - ) - - "{$delegation\n}" - } else { - "{}" - } - } - - return (if (expectedFunction is KtSecondaryConstructor) { - createSecondaryConstructor(expectedFunction.text + " " + body) + val memberChooserObject = OverrideMemberChooserObject.create( + expectedFunction, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY_OR_TEMPLATE + ) + return if (targetClass != null) { + memberChooserObject.generateActualMember(targetClass = targetClass, copyDoc = true) } else { - createFunction(expectedFunction.text + " " + body) - } as KtFunction).apply { - replaceExpectModifier(actualNeeded) - if (returnType != null && KotlinBuiltIns.isUnit(returnType)) { - typeReference = null - } - removeParameterDefaultValues() - } + memberChooserObject.generateTopLevelActual(copyDoc = true, project = project) + } as KtFunction } private fun KtFunction.removeParameterDefaultValues() { @@ -387,27 +366,20 @@ private fun KtFunction.removeParameterDefaultValues() { } } -private fun KtPsiFactory.generateProperty( +private fun generateProperty( project: Project, expectedProperty: KtProperty, descriptor: PropertyDescriptor, - actualNeeded: Boolean + targetClass: KtClassOrObject? = null ): KtProperty { - val body = buildString { - append("\nget()") - append(" = ") - append(getFunctionBodyTextFromTemplate( - project, - TemplateKind.FUNCTION, - descriptor.name.asString(), - descriptor.returnType?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } ?: "" - )) - if (descriptor.isVar) { - append("\nset(value) {}") - } - } - return createProperty(expectedProperty.text + " " + body).apply { - replaceExpectModifier(actualNeeded) - } + val memberChooserObject = OverrideMemberChooserObject.create( + expectedProperty, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY_OR_TEMPLATE + ) + return if (targetClass != null) { + memberChooserObject.generateActualMember(targetClass = targetClass, copyDoc = true) + } else { + memberChooserObject.generateTopLevelActual(copyDoc = true, project = project) + } as KtProperty + } diff --git a/idea/testData/multiModuleQuickFix/abstract/js/Abstract.kt.after b/idea/testData/multiModuleQuickFix/abstract/js/Abstract.kt.after index e0779b9a554..705e96d98a3 100644 --- a/idea/testData/multiModuleQuickFix/abstract/js/Abstract.kt.after +++ b/idea/testData/multiModuleQuickFix/abstract/js/Abstract.kt.after @@ -9,5 +9,5 @@ actual abstract class Abstract { } actual val isGood: Boolean - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/class/jvm/My.kt.after b/idea/testData/multiModuleQuickFix/class/jvm/My.kt.after index a174aa97122..f7cb4aa5b00 100644 --- a/idea/testData/multiModuleQuickFix/class/jvm/My.kt.after +++ b/idea/testData/multiModuleQuickFix/class/jvm/My.kt.after @@ -8,16 +8,17 @@ actual class My { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } - actual fun baz() {} + actual fun baz() { + } actual constructor(flag: Boolean) { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } actual val isGood: Boolean - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. actual var status: Int - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. set(value) {} } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/classFunctionWithConstructor/jvm/My.kt.after b/idea/testData/multiModuleQuickFix/classFunctionWithConstructor/jvm/My.kt.after index 0da3244bf86..e9f60b7ad53 100644 --- a/idea/testData/multiModuleQuickFix/classFunctionWithConstructor/jvm/My.kt.after +++ b/idea/testData/multiModuleQuickFix/classFunctionWithConstructor/jvm/My.kt.after @@ -4,5 +4,6 @@ actual class My { actual constructor() - actual fun test() {} + actual fun test() { + } } diff --git a/idea/testData/multiModuleQuickFix/classFunctionWithConstructorAndParameters/jvm/My.kt.after b/idea/testData/multiModuleQuickFix/classFunctionWithConstructorAndParameters/jvm/My.kt.after index aea56139b3c..44288272576 100644 --- a/idea/testData/multiModuleQuickFix/classFunctionWithConstructorAndParameters/jvm/My.kt.after +++ b/idea/testData/multiModuleQuickFix/classFunctionWithConstructorAndParameters/jvm/My.kt.after @@ -4,5 +4,6 @@ actual class My { actual constructor(a: Int, b: String) - actual fun test() {} + actual fun test() { + } } diff --git a/idea/testData/multiModuleQuickFix/classFunctionWithIncompatibleConstructor/jvm/My.kt.after b/idea/testData/multiModuleQuickFix/classFunctionWithIncompatibleConstructor/jvm/My.kt.after index 8e2608fa708..ee3e801030a 100644 --- a/idea/testData/multiModuleQuickFix/classFunctionWithIncompatibleConstructor/jvm/My.kt.after +++ b/idea/testData/multiModuleQuickFix/classFunctionWithIncompatibleConstructor/jvm/My.kt.after @@ -4,5 +4,6 @@ actual class My actual constructor(a: Int, b: String) { actual constructor(b: String, a: Int) - actual fun test() {} + actual fun test() { + } } diff --git a/idea/testData/multiModuleQuickFix/classPropertyInConstructor/jvm/My.kt.after b/idea/testData/multiModuleQuickFix/classPropertyInConstructor/jvm/My.kt.after index 7fb6389cb41..bb4b5336584 100644 --- a/idea/testData/multiModuleQuickFix/classPropertyInConstructor/jvm/My.kt.after +++ b/idea/testData/multiModuleQuickFix/classPropertyInConstructor/jvm/My.kt.after @@ -3,5 +3,5 @@ actual class My(actual val name: String) { actual val age: String - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/classSomeProperties/jvm/My.kt.after b/idea/testData/multiModuleQuickFix/classSomeProperties/jvm/My.kt.after index fe0275be13e..30308d7fe17 100644 --- a/idea/testData/multiModuleQuickFix/classSomeProperties/jvm/My.kt.after +++ b/idea/testData/multiModuleQuickFix/classSomeProperties/jvm/My.kt.after @@ -6,7 +6,7 @@ actual class My { actual val correct = true actual val x: String - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. actual val pi: Double - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. } diff --git a/idea/testData/multiModuleQuickFix/classWithIncompilableFunction/jvm/My.kt.after b/idea/testData/multiModuleQuickFix/classWithIncompilableFunction/jvm/My.kt.after index e5f1d63ee4b..0228b941ccf 100644 --- a/idea/testData/multiModuleQuickFix/classWithIncompilableFunction/jvm/My.kt.after +++ b/idea/testData/multiModuleQuickFix/classWithIncompilableFunction/jvm/My.kt.after @@ -2,6 +2,6 @@ // DISABLE-ERRORS actual class My { - // Incompilable function - actual fun foo() {} + actual fun foo() { + } } diff --git a/idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt b/idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt new file mode 100644 index 00000000000..a8bab3e01c7 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt @@ -0,0 +1,7 @@ +// "Create actual class for module proj_JVM (JVM)" "true" + +import kotlin.random.Random + +expect class MyGenerator { + fun generate(): Random +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt.after b/idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt.after new file mode 100644 index 00000000000..7353ab43d12 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/classWithJdk/proj_common_dep(stdlib)/common.kt.after @@ -0,0 +1,7 @@ +// "Create actual class for module proj_JVM (JVM)" "true" + +import kotlin.random.Random + +expect class MyGenerator { + fun generate(): Random +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt b/idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt new file mode 100644 index 00000000000..e0c26053d3e --- /dev/null +++ b/idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt @@ -0,0 +1 @@ +// MyGenerator: to be implemented \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt.after b/idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt.after new file mode 100644 index 00000000000..aa2185d21e1 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/classWithJdk/proj_jvm_dep(stdlib)/MyGenerator.kt.after @@ -0,0 +1,8 @@ +import kotlin.random.Random + +// MyGenerator: to be implemented +actual class MyGenerator { + actual fun generate(): Random { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/companionAbsence/jvm/WithCompanion.kt.after b/idea/testData/multiModuleQuickFix/companionAbsence/jvm/WithCompanion.kt.after index 26e5f6947dc..de73456a7be 100644 --- a/idea/testData/multiModuleQuickFix/companionAbsence/jvm/WithCompanion.kt.after +++ b/idea/testData/multiModuleQuickFix/companionAbsence/jvm/WithCompanion.kt.after @@ -3,7 +3,8 @@ actual class WithCompanion { actual companion object { - actual fun foo() {} + actual fun foo() { + } } } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/defaultParameterInExpectedClass/jvm/C.kt.after b/idea/testData/multiModuleQuickFix/defaultParameterInExpectedClass/jvm/C.kt.after index 5b29bcf3732..d0dbd65e3ed 100644 --- a/idea/testData/multiModuleQuickFix/defaultParameterInExpectedClass/jvm/C.kt.after +++ b/idea/testData/multiModuleQuickFix/defaultParameterInExpectedClass/jvm/C.kt.after @@ -1,4 +1,5 @@ // to be created actual class C { - actual fun f(p: Int) {} + actual fun f(p: Int) { + } } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/enum/js/MyEnum.kt.after b/idea/testData/multiModuleQuickFix/enum/js/MyEnum.kt.after index eb0da17cd76..4fd5693defe 100644 --- a/idea/testData/multiModuleQuickFix/enum/js/MyEnum.kt.after +++ b/idea/testData/multiModuleQuickFix/enum/js/MyEnum.kt.after @@ -5,6 +5,6 @@ actual enum class MyEnum { LAST; actual val num: Int - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/interface/jvm/Interface.kt.after b/idea/testData/multiModuleQuickFix/interface/jvm/Interface.kt.after index 01187eff904..f54cd84c686 100644 --- a/idea/testData/multiModuleQuickFix/interface/jvm/Interface.kt.after +++ b/idea/testData/multiModuleQuickFix/interface/jvm/Interface.kt.after @@ -9,7 +9,8 @@ actual interface Interface { actual var status: Int actual class Nested { - actual fun bar() {} + actual fun bar() { + } } } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/nested/jvm/WithNested.kt.after b/idea/testData/multiModuleQuickFix/nested/jvm/WithNested.kt.after index 772ecd10448..744c503f378 100644 --- a/idea/testData/multiModuleQuickFix/nested/jvm/WithNested.kt.after +++ b/idea/testData/multiModuleQuickFix/nested/jvm/WithNested.kt.after @@ -5,11 +5,13 @@ actual class WithNested { } actual class Nested { - actual fun bar() {} + actual fun bar() { + } } actual inner class Inner { - actual fun baz() {} + actual fun baz() { + } } } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/property/jvm/x.kt.after b/idea/testData/multiModuleQuickFix/property/jvm/x.kt.after index 6c5ef67a03a..56107daf713 100644 --- a/idea/testData/multiModuleQuickFix/property/jvm/x.kt.after +++ b/idea/testData/multiModuleQuickFix/property/jvm/x.kt.after @@ -1,4 +1,4 @@ // x: to be implemented actual var x: Int - get() = TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. set(value) {} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/withTest/a_jvm_test/test/testHelper.kt.after b/idea/testData/multiModuleQuickFix/withTest/a_jvm_test/test/testHelper.kt.after index eb8f1a80fd9..abcee9881ab 100644 --- a/idea/testData/multiModuleQuickFix/withTest/a_jvm_test/test/testHelper.kt.after +++ b/idea/testData/multiModuleQuickFix/withTest/a_jvm_test/test/testHelper.kt.after @@ -3,4 +3,5 @@ package test -actual fun testHelper() {} \ No newline at end of file +actual fun testHelper() { +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/withTestDummy/a_jvm/testHelper.kt.after b/idea/testData/multiModuleQuickFix/withTestDummy/a_jvm/testHelper.kt.after index fcf7f8d277c..72049409943 100644 --- a/idea/testData/multiModuleQuickFix/withTestDummy/a_jvm/testHelper.kt.after +++ b/idea/testData/multiModuleQuickFix/withTestDummy/a_jvm/testHelper.kt.after @@ -1,2 +1,3 @@ // testHelper: to be implemented -actual fun testHelper() {} \ No newline at end of file +actual fun testHelper() { +} \ 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 24ef00eec03..d18419f0f28 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTestGenerated.java @@ -144,6 +144,11 @@ public class QuickFixMultiModuleTestGenerated extends AbstractQuickFixMultiModul runTest("idea/testData/multiModuleQuickFix/classWithIncompilableFunction/"); } + @TestMetadata("classWithJdk") + public void testClassWithJdk() throws Exception { + runTest("idea/testData/multiModuleQuickFix/classWithJdk/"); + } + @TestMetadata("companionAbsence") public void testCompanionAbsence() throws Exception { runTest("idea/testData/multiModuleQuickFix/companionAbsence/");