From eff57001dcbc4fbfe8237fafcdc6280e5f4a33b7 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Sat, 12 Oct 2019 08:35:21 +0200 Subject: [PATCH] Create secondary constructor: fill 'this()' arguments #KT-11865 Fixed --- .../callableBuilder/CallableBuilder.kt | 18 +++++++++++++++++- .../tooManyArguments.kt | 7 +++++++ .../tooManyArguments.kt.after | 9 +++++++++ .../tooManyArgumentsWithImcompatibleType.kt | 8 ++++++++ ...oManyArgumentsWithImcompatibleType.kt.after | 10 ++++++++++ .../idea/quickfix/QuickFixTestGenerated.java | 10 ++++++++++ 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt create mode 100644 idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt.after create mode 100644 idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt create mode 100644 idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt index 48eeed099bf..f9108b83a57 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt @@ -69,6 +69,7 @@ import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull @@ -582,13 +583,28 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { if (declarationInPlace is KtSecondaryConstructor) { val containingClass = declarationInPlace.containingClassOrObject!! - if (containingClass.primaryConstructorParameters.isNotEmpty()) { + val primaryConstructorParameters = containingClass.primaryConstructorParameters + if (primaryConstructorParameters.isNotEmpty()) { declarationInPlace.replaceImplicitDelegationCallWithExplicit(true) } else if ((receiverClassDescriptor as ClassDescriptor).getSuperClassOrAny().constructors .all { it.valueParameters.isNotEmpty() } ) { declarationInPlace.replaceImplicitDelegationCallWithExplicit(false) } + if (declarationInPlace.valueParameters.size > primaryConstructorParameters.size) { + val hasCompatibleTypes = primaryConstructorParameters.zip(callableInfo.parameterInfos).all { (primary, secondary) -> + val primaryType = currentFileContext[BindingContext.TYPE, primary.typeReference] ?: return@all false + val secondaryType = computeTypeCandidates(secondary.typeInfo).firstOrNull()?.theType ?: return@all false + secondaryType.isSubtypeOf(primaryType) + } + if (hasCompatibleTypes) { + val delegationCallArgumentList = declarationInPlace.getDelegationCall().valueArgumentList + primaryConstructorParameters.forEach { + val name = it.name + if (name != null) delegationCallArgumentList?.addArgument(psiFactory.createArgument(name)) + } + } + } } return declarationInPlace diff --git a/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt new file mode 100644 index 00000000000..8c82ee1aecc --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt @@ -0,0 +1,7 @@ +// "Create secondary constructor" "true" + +class CtorPrimary(val f1: Int, val f2: Int?) + +fun construct() { + val v6 = CtorPrimary(1, 2, 3) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt.after b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt.after new file mode 100644 index 00000000000..ccdb20482a5 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt.after @@ -0,0 +1,9 @@ +// "Create secondary constructor" "true" + +class CtorPrimary(val f1: Int, val f2: Int?) { + constructor(f1: Int, f2: Int, i: Int) : this(f1, f2) +} + +fun construct() { + val v6 = CtorPrimary(1, 2, 3) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt new file mode 100644 index 00000000000..56ec72a58d1 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt @@ -0,0 +1,8 @@ +// "Create secondary constructor" "true" +// DISABLE-ERRORS + +class CtorPrimary(val f1: Int, val f2: String) + +fun construct() { + val v6 = CtorPrimary(1, 2, 3) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt.after b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt.after new file mode 100644 index 00000000000..73fc2a5753f --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt.after @@ -0,0 +1,10 @@ +// "Create secondary constructor" "true" +// DISABLE-ERRORS + +class CtorPrimary(val f1: Int, val f2: String) { + constructor(f1: Int, f2: Int, i: Int) : this() +} + +fun construct() { + val v6 = CtorPrimary(1, 2, 3) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 8cbf86fe271..71d2c928ca2 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -4886,6 +4886,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/createFromUsage/createSecondaryConstructor/thisCall.kt"); } + @TestMetadata("tooManyArguments.kt") + public void testTooManyArguments() throws Exception { + runTest("idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArguments.kt"); + } + + @TestMetadata("tooManyArgumentsWithImcompatibleType.kt") + public void testTooManyArgumentsWithImcompatibleType() throws Exception { + runTest("idea/testData/quickfix/createFromUsage/createSecondaryConstructor/tooManyArgumentsWithImcompatibleType.kt"); + } + @TestMetadata("wrongExpectedType.kt") public void testWrongExpectedType() throws Exception { runTest("idea/testData/quickfix/createFromUsage/createSecondaryConstructor/wrongExpectedType.kt");