Create secondary constructor: fill 'this()' arguments

#KT-11865 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-10-12 08:35:21 +02:00
committed by Vladimir Dolzhenko
parent e271015382
commit eff57001dc
6 changed files with 61 additions and 1 deletions
@@ -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
@@ -0,0 +1,7 @@
// "Create secondary constructor" "true"
class CtorPrimary(val f1: Int, val f2: Int?)
fun construct() {
val v6 = CtorPrimary(1, 2, 3<caret>)
}
@@ -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)
}
@@ -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<caret>)
}
@@ -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)
}
@@ -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");