Add constructor parameters quickfix works for multiple constructors

This commit is contained in:
Valentin Kipyatkov
2015-05-08 20:56:59 +03:00
parent 4ac2e29d28
commit 0952e9a63a
18 changed files with 45 additions and 27 deletions
@@ -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)
@@ -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<caret>
@@ -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
@@ -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<caret>
@@ -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<caret>(p1, p2)
@@ -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<caret>
@@ -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<caret>(p1, p2)
@@ -1,4 +1,4 @@
// "Add constructor parameters and use them" "true"
// "Add constructor parameters from Base(p1: T, p2: String, p3: Base<T, String>?)" "true"
trait I
open class Base<T1, T2>(p1: T1, p2: T2, p3: Base<T1, T2>?)
@@ -1,4 +1,4 @@
// "Add constructor parameters and use them" "true"
// "Add constructor parameters from Base(p1: T, p2: String, p3: Base<T, String>?)" "true"
trait I
open class Base<T1, T2>(p1: T1, p2: T2, p3: Base<T1, T2>?)
@@ -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<caret>
@@ -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<caret>(p1, p2)
@@ -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<caret>
@@ -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`)
@@ -0,0 +1,5 @@
// "Add constructor parameters from ArrayList((MutableCollection<out String!>..Collection<String!>?))" "true"
// ACTION: Add constructor parameters from ArrayList(Int)
import java.util.ArrayList
class C : ArrayList<String><caret>
@@ -0,0 +1,5 @@
// "Add constructor parameters from ArrayList((MutableCollection<out String!>..Collection<String!>?))" "true"
// ACTION: Add constructor parameters from ArrayList(Int)
import java.util.ArrayList
class C(p0: MutableCollection<out String>) : ArrayList<String><caret>(p0)
@@ -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)
@@ -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)
@@ -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");