diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt index 3e89009b430..290bfa4b239 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt @@ -19,12 +19,9 @@ package org.jetbrains.kotlin.idea.quickfix import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project -import com.intellij.psi.PsiFile -import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.idea.JetBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.isVisible @@ -32,6 +29,7 @@ import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.ShortenReferences import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.replaced +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.TypeUtils import java.util.ArrayList @@ -55,15 +53,15 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() { fixes.add(AddParenthesisFix(delegator, putCaretIntoParenthesis = constructors.singleOrNull()?.getValueParameters()?.isNotEmpty() ?: true)) if (classOrObjectDeclaration is JetClass) { - val constructorToUse = constructors.singleOrNull() - ?: constructors.singleOrNull { it.isPrimary() } //TODO: should we select it automatically in this case? - //TODO: multiple - if (constructorToUse != null && constructorToUse.getValueParameters().isNotEmpty() && constructorToUse.getValueParameters().none { it.getType().isError() }) { - val superType = classDescriptor.getTypeConstructor().getSupertypes().first { it.getConstructor().getDeclarationDescriptor() == superClass } - val typeArgsMap = superClass.getTypeConstructor().getParameters().zip(superType.getArguments()).toMap() - val substitutor = TypeUtils.makeSubstitutorForTypeParametersMap(typeArgsMap) - val substitutedConstructor = constructorToUse.substitute(substitutor) as ConstructorDescriptor - fixes.add(AddParametersFix(delegator, classOrObjectDeclaration, substitutedConstructor)) + val superType = classDescriptor.getTypeConstructor().getSupertypes().first { it.getConstructor().getDeclarationDescriptor() == superClass } + val typeArgsMap = superClass.getTypeConstructor().getParameters().zip(superType.getArguments()).toMap() + val substitutor = TypeUtils.makeSubstitutorForTypeParametersMap(typeArgsMap) + + for (constructor in constructors) { + if (constructor.getValueParameters().isNotEmpty() && constructor.getValueParameters().none { it.getType().isError() }) { + val substitutedConstructor = constructor.substitute(substitutor) as ConstructorDescriptor + fixes.add(AddParametersFix(delegator, classOrObjectDeclaration, substitutedConstructor)) + } } } @@ -96,7 +94,11 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() { override fun getFamilyName() = "Add constructor parameters from superclass" - override fun getText() = "Add constructor parameters and use them" + override fun getText(): String { + return "Add constructor parameters from " + + superConstructor.getContainingDeclaration().getName().asString() + + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(superConstructor) + } override fun invoke(project: Project, editor: Editor?, file: JetFile) { val factory = JetPsiFactory(project) diff --git a/idea/testData/quickfix/supertypeInitialization/addImport.kt b/idea/testData/quickfix/supertypeInitialization/addImport.kt index cbc3e3f519c..be4ea0fd541 100644 --- a/idea/testData/quickfix/supertypeInitialization/addImport.kt +++ b/idea/testData/quickfix/supertypeInitialization/addImport.kt @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from DataInputStream(InputStream!)" "true" import java.io.DataInputStream class C : DataInputStream diff --git a/idea/testData/quickfix/supertypeInitialization/addImport.kt.after b/idea/testData/quickfix/supertypeInitialization/addImport.kt.after index 55d34354309..dffc36ab1c8 100644 --- a/idea/testData/quickfix/supertypeInitialization/addImport.kt.after +++ b/idea/testData/quickfix/supertypeInitialization/addImport.kt.after @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from DataInputStream(InputStream!)" "true" import java.io.DataInputStream import java.io.InputStream diff --git a/idea/testData/quickfix/supertypeInitialization/addParameters.kt b/idea/testData/quickfix/supertypeInitialization/addParameters.kt index afdbf3d8e59..e25f40a2bbb 100644 --- a/idea/testData/quickfix/supertypeInitialization/addParameters.kt +++ b/idea/testData/quickfix/supertypeInitialization/addParameters.kt @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: Int, p2: Int)" "true" open class Base(p1: Int, val p2: Int) class C(p: Int) : Base diff --git a/idea/testData/quickfix/supertypeInitialization/addParameters.kt.after b/idea/testData/quickfix/supertypeInitialization/addParameters.kt.after index 7011ae95d54..d335f5ee72a 100644 --- a/idea/testData/quickfix/supertypeInitialization/addParameters.kt.after +++ b/idea/testData/quickfix/supertypeInitialization/addParameters.kt.after @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: Int, p2: Int)" "true" open class Base(p1: Int, val p2: Int) class C(p: Int, p1: Int, p2: Int) : Base(p1, p2) diff --git a/idea/testData/quickfix/supertypeInitialization/createConstructor.kt b/idea/testData/quickfix/supertypeInitialization/createConstructor.kt index 564905f47fe..0f700ef178b 100644 --- a/idea/testData/quickfix/supertypeInitialization/createConstructor.kt +++ b/idea/testData/quickfix/supertypeInitialization/createConstructor.kt @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: Int, p2: Int)" "true" open class Base(p1: Int, val p2: Int) class C : Base \ No newline at end of file diff --git a/idea/testData/quickfix/supertypeInitialization/createConstructor.kt.after b/idea/testData/quickfix/supertypeInitialization/createConstructor.kt.after index 48e69f7fc36..84c15a4f3b3 100644 --- a/idea/testData/quickfix/supertypeInitialization/createConstructor.kt.after +++ b/idea/testData/quickfix/supertypeInitialization/createConstructor.kt.after @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: Int, p2: Int)" "true" open class Base(p1: Int, val p2: Int) class C(p1: Int, p2: Int) : Base(p1, p2) \ No newline at end of file diff --git a/idea/testData/quickfix/supertypeInitialization/genericClass.kt b/idea/testData/quickfix/supertypeInitialization/genericClass.kt index 07a5a61300a..b1021ba5dbc 100644 --- a/idea/testData/quickfix/supertypeInitialization/genericClass.kt +++ b/idea/testData/quickfix/supertypeInitialization/genericClass.kt @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: T, p2: String, p3: Base?)" "true" trait I open class Base(p1: T1, p2: T2, p3: Base?) diff --git a/idea/testData/quickfix/supertypeInitialization/genericClass.kt.after b/idea/testData/quickfix/supertypeInitialization/genericClass.kt.after index 12bb6cad65a..23f0137d07e 100644 --- a/idea/testData/quickfix/supertypeInitialization/genericClass.kt.after +++ b/idea/testData/quickfix/supertypeInitialization/genericClass.kt.after @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: T, p2: String, p3: Base?)" "true" trait I open class Base(p1: T1, p2: T2, p3: Base?) diff --git a/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt b/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt index 56dd6664bee..24ad93ac30d 100644 --- a/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt +++ b/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: Int, p2: Int)" "true" open class Base(p1: Int, val p2: Int) class C private : Base \ No newline at end of file diff --git a/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt.after b/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt.after index b18771729f0..42e08c14466 100644 --- a/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt.after +++ b/idea/testData/quickfix/supertypeInitialization/incompleteConstructor.kt.after @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(p1: Int, p2: Int)" "true" open class Base(p1: Int, val p2: Int) class C private (p1: Int, p2: Int) : Base(p1, p2) \ No newline at end of file diff --git a/idea/testData/quickfix/supertypeInitialization/keywordName.kt b/idea/testData/quickfix/supertypeInitialization/keywordName.kt index e704607c1cd..ca6ea1beb63 100644 --- a/idea/testData/quickfix/supertypeInitialization/keywordName.kt +++ b/idea/testData/quickfix/supertypeInitialization/keywordName.kt @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(`fun`: Int, `class`: Int)" "true" open class Base(`fun`: Int, val `class`: Int) class C : Base \ No newline at end of file diff --git a/idea/testData/quickfix/supertypeInitialization/keywordName.kt.after b/idea/testData/quickfix/supertypeInitialization/keywordName.kt.after index 7c2129b92a4..8ff145748c7 100644 --- a/idea/testData/quickfix/supertypeInitialization/keywordName.kt.after +++ b/idea/testData/quickfix/supertypeInitialization/keywordName.kt.after @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(`fun`: Int, `class`: Int)" "true" open class Base(`fun`: Int, val `class`: Int) class C(`fun`: Int, `class`: Int) : Base(`fun`, `class`) \ No newline at end of file diff --git a/idea/testData/quickfix/supertypeInitialization/multipleConstructors.kt b/idea/testData/quickfix/supertypeInitialization/multipleConstructors.kt new file mode 100644 index 00000000000..592674ec218 --- /dev/null +++ b/idea/testData/quickfix/supertypeInitialization/multipleConstructors.kt @@ -0,0 +1,5 @@ +// "Add constructor parameters from ArrayList((MutableCollection..Collection?))" "true" +// ACTION: Add constructor parameters from ArrayList(Int) +import java.util.ArrayList + +class C : ArrayList diff --git a/idea/testData/quickfix/supertypeInitialization/multipleConstructors.kt.after b/idea/testData/quickfix/supertypeInitialization/multipleConstructors.kt.after new file mode 100644 index 00000000000..f1d974efc09 --- /dev/null +++ b/idea/testData/quickfix/supertypeInitialization/multipleConstructors.kt.after @@ -0,0 +1,5 @@ +// "Add constructor parameters from ArrayList((MutableCollection..Collection?))" "true" +// ACTION: Add constructor parameters from ArrayList(Int) +import java.util.ArrayList + +class C(p0: MutableCollection) : ArrayList(p0) diff --git a/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt b/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt index 48a881ce786..56709f1a093 100644 --- a/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt +++ b/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(s: String)" "true" open class Base private(p1: Int, val p2: Int) { private constructor() : this(0, 1) protected constructor(s: String) : this(s.length(), 1) diff --git a/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt.after b/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt.after index 4c0cf5b5934..52653b22e61 100644 --- a/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt.after +++ b/idea/testData/quickfix/supertypeInitialization/primaryConstructorInaccessible.kt.after @@ -1,4 +1,4 @@ -// "Add constructor parameters and use them" "true" +// "Add constructor parameters from Base(s: String)" "true" open class Base private(p1: Int, val p2: Int) { private constructor() : this(0, 1) protected constructor(s: String) : this(s.length(), 1) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 177ea353aa2..b7ed90fdbdc 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -4023,6 +4023,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("multipleConstructors.kt") + public void testMultipleConstructors() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/supertypeInitialization/multipleConstructors.kt"); + doTest(fileName); + } + @TestMetadata("noAccessibleConstructors.kt") public void testNoAccessibleConstructors() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/supertypeInitialization/noAccessibleConstructors.kt");