From 00dcbd4d936f69994797243efe7a70eb7eb80545 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 8 May 2015 19:49:40 +0300 Subject: [PATCH] Initial implementation of KT-4046 Support 'Create constructor matching superclass' #KT-4046 Fixed --- .idea/dictionaries/valentin.xml | 1 + .../codeInsight/intention/annotations.xml | 8 +- .../org/jetbrains/kotlin/psi/JetClass.java | 18 ++++ .../kotlin/psi/JetParameterList.java | 52 ++++++++++ .../idea/completion/HeuristicSignatures.kt | 3 +- .../AddConstructorParametersFromSuperFix.kt | 97 +++++++++++++++++++ .../idea/quickfix/JetIntentionAction.java | 6 +- .../idea/quickfix/QuickFixRegistrar.java | 2 + .../KotlinIntroduceParameterHandler.kt | 25 +---- .../addImport.kt | 4 + .../addImport.kt.after | 5 + .../addParameters.kt | 4 + .../addParameters.kt.after | 4 + .../createConstructor.kt | 4 + .../createConstructor.kt.after | 4 + .../genericClass.kt | 6 ++ .../genericClass.kt.after | 6 ++ .../incompleteConstructor.kt | 4 + .../incompleteConstructor.kt.after | 4 + .../keywordName.kt | 4 + .../keywordName.kt.after | 4 + .../noParameters.kt | 6 ++ .../primaryConstructorInaccessible.kt | 7 ++ .../primaryConstructorInaccessible.kt.after | 7 ++ .../idea/quickfix/QuickFixTestGenerated.java | 57 +++++++++++ 25 files changed, 308 insertions(+), 34 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/AddConstructorParametersFromSuperFix.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt.after create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt.after create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt.after create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt.after create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt.after create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt.after create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/noParameters.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt create mode 100644 idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt.after diff --git a/.idea/dictionaries/valentin.xml b/.idea/dictionaries/valentin.xml index 45c154aad82..167ab570a67 100644 --- a/.idea/dictionaries/valentin.xml +++ b/.idea/dictionaries/valentin.xml @@ -1,6 +1,7 @@ + delegator funs initializers inserter diff --git a/annotations/com/intellij/codeInsight/intention/annotations.xml b/annotations/com/intellij/codeInsight/intention/annotations.xml index 38d7e6786b1..e715e9e8785 100644 --- a/annotations/com/intellij/codeInsight/intention/annotations.xml +++ b/annotations/com/intellij/codeInsight/intention/annotations.xml @@ -5,13 +5,7 @@ - - - - - - diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClass.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClass.java index 9faf13b7eb8..e3f6e23ec28 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClass.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClass.java @@ -78,6 +78,24 @@ public class JetClass extends JetTypeParameterListOwnerStub imp return list.getParameters(); } + @NotNull + public JetPrimaryConstructor getOrCreatePrimaryConstructor() { + JetPrimaryConstructor constructor = getPrimaryConstructor(); + if (constructor != null) return constructor; + PsiElement anchor = getTypeParameterList(); + if (anchor == null) anchor = getNameIdentifier(); + if (anchor == null) anchor = getLastChild(); + return (JetPrimaryConstructor) addAfter(new JetPsiFactory(getProject()).createPrimaryConstructor(), anchor); + } + + @NotNull + public JetParameterList getOrCreatePrimaryConstructorParameterList() { + JetPrimaryConstructor constructor = getOrCreatePrimaryConstructor(); + JetParameterList parameterList = constructor.getValueParameterList(); + if (parameterList != null) return parameterList; + return (JetParameterList) constructor.add(new JetPsiFactory(getProject()).createParameterList("()")); + } + @Override @Nullable public JetDelegationSpecifierList getDelegationSpecifierList() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetParameterList.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetParameterList.java index 8a94cb60619..59763231799 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetParameterList.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetParameterList.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub; import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes; @@ -44,6 +45,57 @@ public class JetParameterList extends JetElementImplStub parameters = getParameters(); + if (parameters.isEmpty()) { + if (getFirstChild().getNode().getElementType() == JetTokens.LPAR) { + return (JetParameter) addAfter(parameter, getFirstChild()); + } + else { + return (JetParameter) add(parameter); + } + } + else { + PsiElement comma = new JetPsiFactory(getProject()).createComma(); + if (anchor != null) { + comma = addAfter(comma, anchor); + return (JetParameter) addAfter(parameter, comma); + } + else { + comma = addBefore(comma, parameters.get(0)); + return (JetParameter) addBefore(parameter, comma); + } + } + } + + @NotNull + public JetParameter addParameterBefore(@NotNull JetParameter parameter, @Nullable JetParameter anchor) { + List parameters = getParameters(); + JetParameter anchorAfter; + if (parameters.isEmpty()) { + assert anchor == null; + anchorAfter = null; + } + else { + if (anchor != null) { + int index = parameters.indexOf(anchor); + assert index >= 0; + anchorAfter = index > 0 ? parameters.get(index - 1) : null; + } + else { + anchorAfter = parameters.get(parameters.size() - 1); + } + } + return addParameterAfter(parameter, anchorAfter); + } + // this method needed only for migrate lambda syntax @Deprecated public boolean isParenthesized() { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt index eac52944480..3e7a265d848 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt @@ -82,8 +82,7 @@ public object HeuristicSignatures { val type = typeFromText(typeStr, typeParameters, moduleDescriptor, project) // now substitute type parameters with actual arguments - val typeArgs = ownerType.getArguments() - val typeArgsMap = typeParameters.indices.map { typeParameters[it] to typeArgs[it] }.toMap() + val typeArgsMap = typeParameters.zip(ownerType.getArguments()).toMap() val substitutor = TypeUtils.makeSubstitutorForTypeParametersMap(typeArgsMap) return substitutor.substitute(type, Variance.INVARIANT) } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddConstructorParametersFromSuperFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddConstructorParametersFromSuperFix.kt new file mode 100644 index 00000000000..8b03caff767 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddConstructorParametersFromSuperFix.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.quickfix + +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.core.isVisible +import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.idea.util.ShortenReferences +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.TypeUtils +import java.util.ArrayList + +public class AddConstructorParametersFromSuperFix private( + element: JetDelegatorToSuperClass, + val classDeclaration: JetClass, + val superConstructor: ConstructorDescriptor +) : JetIntentionAction(element) { + + override fun getFamilyName() = "Add constructor parameters from superclass" + + override fun getText() = "Add constructor parameters and use them" + + override fun invoke(project: Project, editor: Editor?, file: JetFile) { + val factory = JetPsiFactory(project) + val renderer = IdeDescriptorRenderers.SOURCE_CODE + + val superParameters = superConstructor.getValueParameters() + val parameterNames = ArrayList() + val typeRefsToShorten = ArrayList() + if (!superParameters.isEmpty()) { + val parameterList = classDeclaration.getOrCreatePrimaryConstructorParameterList() + for (parameter in superParameters) { + //TODO: what if type is error? + val name = renderer.renderName(parameter.getName()) + val parameterText = name + ":" + renderer.renderType(parameter.getType()) + val newParameter = parameterList.addParameter(factory.createParameter(parameterText)) + typeRefsToShorten.add(newParameter.getTypeReference()) + parameterNames.add(name) + } + } + + val delegatorCall = factory.createDelegatorToSuperCall(element.getText() + "(" + parameterNames.joinToString(",") + ")") + element.replace(delegatorCall) + + ShortenReferences.DEFAULT.process(typeRefsToShorten) + } + + companion object : JetSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): JetIntentionAction? { + val delegator = diagnostic.getPsiElement() as JetDelegatorToSuperClass + val classDeclaration = delegator.getParent().getParent() as? JetClass ?: return null + + val typeRef = delegator.getTypeReference() ?: return null + val type = typeRef.analyze()[BindingContext.TYPE, typeRef] ?: return null + if (type.isError()) return null + + val superClass = (type.getConstructor().getDeclarationDescriptor() as? ClassDescriptor) ?: return null + val classDescriptor = delegator.getResolutionFacade().resolveToDescriptor(classDeclaration) as ClassDescriptor + val constructors = superClass.getConstructors().filter { it.isVisible(classDescriptor) } + val constructorToUse = constructors.singleOrNull() + ?: constructors.singleOrNull { it.isPrimary() } //TODO: should we select it automatically in this case? + ?: return null + //TODO: choose among multiple + if (constructorToUse.getValueParameters().isEmpty()) return null + + 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 + + return AddConstructorParametersFromSuperFix(delegator, classDeclaration, substitutedConstructor) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/JetIntentionAction.java b/idea/src/org/jetbrains/kotlin/idea/quickfix/JetIntentionAction.java index 244987948b5..14561fb490d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/JetIntentionAction.java +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/JetIntentionAction.java @@ -24,6 +24,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.psi.JetCodeFragment; import org.jetbrains.kotlin.psi.JetFile; @@ -42,7 +43,7 @@ public abstract class JetIntentionAction implements Intent //Don't override this method. Use the method with JetFile instead. @Deprecated @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + public void invoke(@NotNull Project project, @Nullable Editor editor, @NotNull PsiFile file) throws IncorrectOperationException { if (file instanceof JetFile) { if (FileModificationService.getInstance().prepareFileForWrite(element.getContainingFile())) { invoke(project, editor, (JetFile) file); @@ -50,8 +51,7 @@ public abstract class JetIntentionAction implements Intent } } - protected void invoke(@NotNull Project project, Editor editor, JetFile file) throws IncorrectOperationException { - } + protected abstract void invoke(@NotNull Project project, @Nullable Editor editor, @NotNull JetFile file) throws IncorrectOperationException; @Override public boolean startInWriteAction() { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java index a5b89a333e0..439fb67906b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java @@ -325,5 +325,7 @@ public class QuickFixRegistrar { QuickFixes.factories.put(DEPRECATED_ANNOTATION_SYNTAX, DeprecatedAnnotationSyntaxFix.Companion); QuickFixes.factories.put(DEPRECATED_ANNOTATION_SYNTAX, DeprecatedAnnotationSyntaxFix.Companion.createWholeProjectFixFactory()); + + QuickFixes.factories.put(SUPERTYPE_NOT_INITIALIZED, AddConstructorParametersFromSuperFix.Companion); } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt index 983b5ca8760..c05fdd36b80 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt @@ -192,8 +192,6 @@ public open class KotlinIntroduceParameterHandler( return } - val parameterList = targetParent.getValueParameterList() - val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, targetParent] val functionDescriptor: FunctionDescriptor = when (descriptor) { @@ -250,26 +248,9 @@ public open class KotlinIntroduceParameterHandler( val addedParameter = if (inplaceIsAvailable) { runWriteAction { - val newParameterList = - if (parameterList == null) { - val klass = targetParent as? JetClass - val anchor = klass?.getTypeParameterList() ?: klass?.getNameIdentifier() - assert(anchor != null) { "Invalid declaration: ${targetParent.getElementTextWithContext()}" } - - val constructor = targetParent.addAfter(psiFactory.createPrimaryConstructor(), anchor) as JetPrimaryConstructor - constructor.getValueParameterList()!! - } - else parameterList - - val lastParameter = newParameterList.getChildren().lastOrNull { it is JetParameter } as? JetParameter - if (lastParameter != null) { - val comma = newParameterList.addAfter(psiFactory.createComma(), lastParameter) - newParameterList.addAfter(newParameter, comma) as JetParameter - } - else { - val singleParameterList = psiFactory.createParameterList("(${newParameter.getText()})") - (newParameterList.replace(singleParameterList) as JetParameterList).getParameters().first() - } + val parameterList = targetParent.getValueParameterList() + ?: (targetParent as JetClass).getOrCreatePrimaryConstructorParameterList() + parameterList.addParameter(newParameter) } } else newParameter diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt new file mode 100644 index 00000000000..cbc3e3f519c --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "true" +import java.io.DataInputStream + +class C : DataInputStream diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt.after b/idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt.after new file mode 100644 index 00000000000..55d34354309 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt.after @@ -0,0 +1,5 @@ +// "Add constructor parameters and use them" "true" +import java.io.DataInputStream +import java.io.InputStream + +class C(p0: InputStream) : DataInputStream(p0) diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt new file mode 100644 index 00000000000..afdbf3d8e59 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "true" +open class Base(p1: Int, val p2: Int) + +class C(p: Int) : Base diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt.after b/idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt.after new file mode 100644 index 00000000000..7011ae95d54 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt.after @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "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/addConstructorParametersFromSuper/createConstructor.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt new file mode 100644 index 00000000000..564905f47fe --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "true" +open class Base(p1: Int, val p2: Int) + +class C : Base \ No newline at end of file diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt.after b/idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt.after new file mode 100644 index 00000000000..48e69f7fc36 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt.after @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "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/addConstructorParametersFromSuper/genericClass.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt new file mode 100644 index 00000000000..07a5a61300a --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt @@ -0,0 +1,6 @@ +// "Add constructor parameters and use them" "true" +trait I + +open class Base(p1: T1, p2: T2, p3: Base?) + +class C : I, Base \ No newline at end of file diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt.after b/idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt.after new file mode 100644 index 00000000000..12bb6cad65a --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt.after @@ -0,0 +1,6 @@ +// "Add constructor parameters and use them" "true" +trait I + +open class Base(p1: T1, p2: T2, p3: Base?) + +class C(p1: T, p2: String, p3: Base?) : I, Base(p1, p2, p3) \ No newline at end of file diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt new file mode 100644 index 00000000000..56dd6664bee --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "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/addConstructorParametersFromSuper/incompleteConstructor.kt.after b/idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt.after new file mode 100644 index 00000000000..b18771729f0 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt.after @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "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/addConstructorParametersFromSuper/keywordName.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt new file mode 100644 index 00000000000..e704607c1cd --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "true" +open class Base(`fun`: Int, val `class`: Int) + +class C : Base \ No newline at end of file diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt.after b/idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt.after new file mode 100644 index 00000000000..7c2129b92a4 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt.after @@ -0,0 +1,4 @@ +// "Add constructor parameters and use them" "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/addConstructorParametersFromSuper/noParameters.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/noParameters.kt new file mode 100644 index 00000000000..28231c5956e --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/noParameters.kt @@ -0,0 +1,6 @@ +// "Add constructor parameters and use them" "false" +// ACTION: Change to constructor invocation +// ERROR: This type has a constructor, and thus must be initialized here +open class Base + +class C : Base \ No newline at end of file diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt b/idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt new file mode 100644 index 00000000000..48a881ce786 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt @@ -0,0 +1,7 @@ +// "Add constructor parameters and use them" "true" +open class Base private(p1: Int, val p2: Int) { + private constructor() : this(0, 1) + protected constructor(s: String) : this(s.length(), 1) +} + +class C : Base diff --git a/idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt.after b/idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt.after new file mode 100644 index 00000000000..4c0cf5b5934 --- /dev/null +++ b/idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt.after @@ -0,0 +1,7 @@ +// "Add constructor parameters and use them" "true" +open class Base private(p1: Int, val p2: Int) { + private constructor() : this(0, 1) + protected constructor(s: String) : this(s.length(), 1) +} + +class C(s: String) : Base(s) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index b20e7339fe8..951b97fbc0e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -176,6 +176,63 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/addConstructorParametersFromSuper") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AddConstructorParametersFromSuper extends AbstractQuickFixTest { + @TestMetadata("addImport.kt") + public void testAddImport() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/addImport.kt"); + doTest(fileName); + } + + @TestMetadata("addParameters.kt") + public void testAddParameters() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/addParameters.kt"); + doTest(fileName); + } + + public void testAllFilesPresentInAddConstructorParametersFromSuper() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addConstructorParametersFromSuper"), Pattern.compile("^(\\w+)\\.kt$"), true); + } + + @TestMetadata("createConstructor.kt") + public void testCreateConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/createConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("genericClass.kt") + public void testGenericClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/genericClass.kt"); + doTest(fileName); + } + + @TestMetadata("incompleteConstructor.kt") + public void testIncompleteConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/incompleteConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("keywordName.kt") + public void testKeywordName() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/keywordName.kt"); + doTest(fileName); + } + + @TestMetadata("noParameters.kt") + public void testNoParameters() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/noParameters.kt"); + doTest(fileName); + } + + @TestMetadata("primaryConstructorInaccessible.kt") + public void testPrimaryConstructorInaccessible() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/addConstructorParametersFromSuper/primaryConstructorInaccessible.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/addStarProjections") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)