diff --git a/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt b/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt index b17a62a84212..eed3cdb855a6 100644 --- a/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt +++ b/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KaRendererAnn import org.jetbrains.kotlin.analysis.api.renderer.base.contextReceivers.KaContextReceiversRenderer import org.jetbrains.kotlin.analysis.api.renderer.base.contextReceivers.renderers.KaContextReceiverLabelRenderer import org.jetbrains.kotlin.analysis.api.renderer.declarations.KaDeclarationRenderer +import org.jetbrains.kotlin.analysis.api.renderer.declarations.bodies.KaFunctionLikeBodyRenderer import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KaDeclarationRendererForSource import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KaRendererKeywordFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KaRendererOtherModifiersProvider @@ -47,11 +48,11 @@ import org.jetbrains.kotlin.types.Variance import javax.swing.Icon @ApiStatus.Internal -data class KtClassMemberInfo internal constructor( +data class KtClassMemberInfo( val symbolPointer: KaSymbolPointer, - @NlsSafe val memberText: String?, + val memberText: @NlsSafe String?, val memberIcon: Icon?, - @NlsContexts.Label val containingSymbolText: String?, + val containingSymbolText: @NlsContexts.Label String?, val containingSymbolIcon: Icon?, val isProperty: Boolean, ) { @@ -61,7 +62,7 @@ data class KtClassMemberInfo internal constructor( symbol: KaCallableSymbol, memberText: @NlsSafe String? = null, memberIcon: Icon? = null, - @NlsContexts.Label containingSymbolText: String? = null, + containingSymbolText: @NlsContexts.Label String? = null, containingSymbolIcon: Icon? = null, ): KtClassMemberInfo = KtClassMemberInfo( symbolPointer = symbol.createPointer(), @@ -229,11 +230,24 @@ context(KaSession) private fun createRenderer( targetClass: KtClassOrObject?, mode: MemberGenerateMode, - symbol: KaDeclarationSymbol + topDeclarationSymbol: KaDeclarationSymbol ): KaDeclarationRenderer { val containingKtFile = targetClass?.containingKtFile val renderer = KaDeclarationRendererForSource.WITH_QUALIFIED_NAMES.with { + functionLikeBodyRenderer = object : KaFunctionLikeBodyRenderer { + override fun renderBody( + analysisSession: KaSession, + symbol: KaFunctionSymbol, + printer: PrettyPrinter + ) { + if (symbol is KaConstructorSymbol && + !symbol.isPrimary && + (symbol.containingSymbol as? KaClassSymbol)?.declaredMemberScope?.constructors?.any { it.isPrimary } == true) { + printer.append(" : this()") + } + } + } if (mode == MemberGenerateMode.OVERRIDE) { annotationRenderer = annotationRenderer.with { annotationFilter = KaRendererAnnotationsFilter { annotation, _ -> keepAnnotation(annotation, containingKtFile) } @@ -251,7 +265,7 @@ private fun createRenderer( } if (mode != MemberGenerateMode.ACTUAL) { - modalityProvider = modalityProvider.onlyIf { s -> s != symbol } + modalityProvider = modalityProvider.onlyIf { s -> s != topDeclarationSymbol } } valueParameterRenderer = object: KaValueParameterSymbolRenderer { @@ -284,13 +298,13 @@ private fun createRenderer( //copy from KaRendererOtherModifiersProvider.ALL with `actual` and `override` specifics override fun getOtherModifiers( analysisSession: KaSession, - s: KaDeclarationSymbol + symbol: KaDeclarationSymbol ): List = buildList { if (mode == MemberGenerateMode.OVERRIDE && containingSymbol?.isActual == true) { //include actual modifier explicitly when containing class has modifier fun shouldHaveActualModifier(): Boolean { - if (s.isActual) return true - val containingInterface = s.containingSymbol + if (symbol.isActual) return true + val containingInterface = symbol.containingSymbol return containingInterface is KaClassSymbol && containingSymbol.getExpectsForActual().any { (it as? KaClassSymbol)?.isSubClassOf(containingInterface) == true } } @@ -299,54 +313,54 @@ private fun createRenderer( } } - if (s is KaNamedFunctionSymbol) { - if (s.isExternal) add(KtTokens.EXTERNAL_KEYWORD) - if (s.isOverride) add(KtTokens.OVERRIDE_KEYWORD) - if (s.isInline) add(KtTokens.INLINE_KEYWORD) - if (s.isInfix) add(KtTokens.INFIX_KEYWORD) - if (s.isOperator) add(KtTokens.OPERATOR_KEYWORD) - if (s.isSuspend) add(KtTokens.SUSPEND_KEYWORD) + if (symbol is KaNamedFunctionSymbol) { + if (symbol.isExternal) add(KtTokens.EXTERNAL_KEYWORD) + if (symbol.isOverride) add(KtTokens.OVERRIDE_KEYWORD) + if (symbol.isInline) add(KtTokens.INLINE_KEYWORD) + if (symbol.isInfix) add(KtTokens.INFIX_KEYWORD) + if (symbol.isOperator) add(KtTokens.OPERATOR_KEYWORD) + if (symbol.isSuspend) add(KtTokens.SUSPEND_KEYWORD) } - if (s is KaPropertySymbol) { - if (s.isOverride) add(KtTokens.OVERRIDE_KEYWORD) + if (symbol is KaPropertySymbol) { + if (symbol.isOverride) add(KtTokens.OVERRIDE_KEYWORD) } - if (s is KaValueParameterSymbol) { - if (s.isVararg) add(KtTokens.VARARG_KEYWORD) - if (s.isCrossinline) add(KtTokens.CROSSINLINE_KEYWORD) - if (s.isNoinline) add(KtTokens.NOINLINE_KEYWORD) + if (symbol is KaValueParameterSymbol) { + if (symbol.isVararg) add(KtTokens.VARARG_KEYWORD) + if (symbol.isCrossinline) add(KtTokens.CROSSINLINE_KEYWORD) + if (symbol.isNoinline) add(KtTokens.NOINLINE_KEYWORD) } - if (s is KaKotlinPropertySymbol) { - if (s.isConst) add(KtTokens.CONST_KEYWORD) - if (s.isLateInit) add(KtTokens.LATEINIT_KEYWORD) + if (symbol is KaKotlinPropertySymbol) { + if (symbol.isConst) add(KtTokens.CONST_KEYWORD) + if (symbol.isLateInit) add(KtTokens.LATEINIT_KEYWORD) } - if (s is KaNamedClassSymbol) { - if (s.isExternal) add(KtTokens.EXTERNAL_KEYWORD) - if (s.isInline) { - if ((s.psi as? KtClassOrObject)?.modifierList?.hasValueModifier() == true) { + if (symbol is KaNamedClassSymbol) { + if (symbol.isExternal) add(KtTokens.EXTERNAL_KEYWORD) + if (symbol.isInline) { + if ((symbol.psi as? KtClassOrObject)?.modifierList?.hasValueModifier() == true) { add(KtTokens.VALUE_KEYWORD) } else { add(KtTokens.INLINE_KEYWORD) } } - if (s.isData) add(KtTokens.DATA_KEYWORD) - if (s.isFun) add(KtTokens.FUN_KEYWORD) - if (s.isInner) add(KtTokens.INNER_KEYWORD) + if (symbol.isData) add(KtTokens.DATA_KEYWORD) + if (symbol.isFun) add(KtTokens.FUN_KEYWORD) + if (symbol.isInner) add(KtTokens.INNER_KEYWORD) } - if (s is KaTypeParameterSymbol) { - if (s.isReified) add(KtTokens.REIFIED_KEYWORD) - when (s.variance) { + if (symbol is KaTypeParameterSymbol) { + if (symbol.isReified) add(KtTokens.REIFIED_KEYWORD) + when (symbol.variance) { Variance.INVARIANT -> {} Variance.IN_VARIANCE -> add(KtTokens.IN_KEYWORD) Variance.OUT_VARIANCE -> add(KtTokens.OUT_KEYWORD) } } - if (s == symbol && mode == MemberGenerateMode.OVERRIDE) { + if (symbol == topDeclarationSymbol && mode == MemberGenerateMode.OVERRIDE) { //include additional override modifier add(KtTokens.OVERRIDE_KEYWORD) } @@ -360,7 +374,7 @@ private fun createRenderer( } @OptIn(KaExperimentalApi::class) -inline fun KaDeclarationRenderer.Builder.withoutLabel() { +fun KaDeclarationRenderer.Builder.withoutLabel() { contextReceiversRenderer = contextReceiversRenderer.with { contextReceiverLabelRenderer = WITHOUT_LABEL } diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt index 45c0f3827c05..69b593b46c5a 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt @@ -1,4 +1,4 @@ // My: to be implemented // DISABLE_ERRORS -// IGNORE_K2 + package my diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt.after index 34d2fbab740c..0af46cabf83e 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt.after +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/jvm/My.testModule_JVM.kt.after @@ -1,6 +1,6 @@ // My: to be implemented // DISABLE_ERRORS -// IGNORE_K2 + package my import other.Another diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt index 541fe19bc4fb..9f796cb8986b 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt @@ -1,5 +1,6 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection expect class Constructors(s: String) { constructor(i: Int) diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt.after index 541fe19bc4fb..87639c4d6101 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt.after +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/common/common.kt.after @@ -1,6 +1,7 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection -expect class Constructors(s: String) { +expect class Constructors(s: String) { constructor(i: Int) } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt index 21c27a0ba5cf..b712110be6d5 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt @@ -1,5 +1,6 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection expect interface I { fun f(p: Int = 1) diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt.after index 775d7ca787f1..641d42878236 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt.after +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/common/common.kt.after @@ -1,6 +1,7 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection -expect interface I { +expect interface I { fun f(p: Int = 1) -} \ No newline at end of file +} diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt index 92e7d380650c..6268fb8ba36c 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt @@ -1,5 +1,6 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection expect class C { fun f(p: Int = 1) diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt.after index 7ee9b595b314..4ad8432c5f51 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt.after +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/common/common.kt.after @@ -1,6 +1,7 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection -expect class C { +expect class C { fun f(p: Int = 1) -} \ No newline at end of file +} diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt index e3a6cf952a30..103773185f41 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt @@ -1,4 +1,5 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection expect class WithConstructor(s: String = "Hello") \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt.after index e3a6cf952a30..f2374a7bccf5 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt.after +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/common/common.kt.after @@ -1,4 +1,5 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection -expect class WithConstructor(s: String = "Hello") \ No newline at end of file +expect class WithConstructor(s: String = "Hello") diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/jvm/common.testModule_JVM.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/jvm/common.testModule_JVM.kt.after similarity index 100% rename from plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/jvm/common.testModule_JVM.after rename to plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/jvm/common.testModule_JVM.kt.after diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt index 1bf1266be570..f16a4d3384db 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt @@ -4,7 +4,7 @@ // ERROR: Unresolved reference: TODO // ERROR: Unresolved reference: TODO // ERROR: Unresolved reference: TODO -// IGNORE_K2 + expect sealed class CommonSealedClass() class SInheritor1 : CommonSealedClass() diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt.after index f8ad5998f2a1..d0f79a1d73a9 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt.after +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt.after @@ -4,7 +4,7 @@ // ERROR: Unresolved reference: TODO // ERROR: Unresolved reference: TODO // ERROR: Unresolved reference: TODO -// IGNORE_K2 + expect sealed class CommonSealedClass() class SInheritor1 : CommonSealedClass() diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt.fir.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt.fir.after new file mode 100644 index 000000000000..3c122bf3d6ec --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/header/header.kt.fir.after @@ -0,0 +1,16 @@ +// "Add remaining branches" "true" +// SHOULD_BE_AVAILABLE_AFTER_EXECUTION +// ERROR: Expected class 'CommonSealedClass' has no actual declaration in module testModule_Common +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO + + +expect sealed class CommonSealedClass() +class SInheritor1 : CommonSealedClass() +class SInheritor2 : CommonSealedClass() + +fun hello(c: CommonSealedClass): Int = when(c) { + is SInheritor1 -> TODO() + is SInheritor2 -> TODO() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt index 22989524373e..107b25cb1b6c 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt @@ -1,4 +1,5 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection expect class WithPrimaryConstructor(x: Int, s: String) \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt.after b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt.after index 76b3b8892625..32c70b950602 100644 --- a/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt.after +++ b/plugins/kotlin/idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/header/header.kt.after @@ -1,4 +1,5 @@ // "Add missing actual declarations" "true" -// IGNORE_K2 +// K2_ACTION: "Create actual in 'testModule_JVM'" "true" +// K2_TOOL: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinNoActualForExpectInspection -expect class WithPrimaryConstructor(x: Int, s: String) \ No newline at end of file +expect class WithPrimaryConstructor(x: Int, s: String) \ No newline at end of file