From d4fc814d764bb332d0192e8f42a1b102d0c4d47e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sapalski?= Date: Mon, 22 Apr 2013 15:26:54 +0200 Subject: [PATCH] Quickfix for NOTHING_TO_OVERRIDE: add function to one of supertypes. --- .../jetbrains/jet/plugin/JetBundle.properties | 7 +- .../JetAddFunctionToClassifierAction.java | 184 ++++++++++++++++++ .../DescriptorToDeclarationUtil.java | 7 +- .../quickfix/AddFunctionToSupertypeFix.java | 171 ++++++++++++++++ .../jet/plugin/quickfix/QuickFixes.java | 1 + .../nothingToOverride/afterAddFunction.kt | 8 + .../afterAddFunctionAbstractClass.kt | 7 + .../afterAddFunctionNoBody.kt | 8 + .../afterAddFunctionNonUnitReturnType.kt | 9 + .../afterAddFunctionTrait.kt | 7 + .../afterAddFunctionTwoSuperclasses.kt | 10 + .../afterAddFunctionTwoTraits.kt | 8 + .../afterNoOpenSuperFunction.kt | 11 -- .../nothingToOverride/beforeAddFunction.kt | 6 + .../beforeAddFunctionAbstractClass.kt | 6 + .../beforeAddFunctionNoBody.kt | 5 + .../beforeAddFunctionNonUnitReturnType.kt | 6 + .../beforeAddFunctionTrait.kt | 6 + .../beforeAddFunctionTwoSuperclasses.kt | 8 + .../beforeAddFunctionTwoTraits.kt | 6 + .../beforeNoOpenSuperFunction.kt | 1 + .../quickfix/QuickFixTestGenerated.java | 35 ++++ 22 files changed, 504 insertions(+), 13 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/actions/JetAddFunctionToClassifierAction.java create mode 100644 idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java create mode 100644 idea/testData/quickfix/override/nothingToOverride/afterAddFunction.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/afterAddFunctionAbstractClass.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNoBody.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNonUnitReturnType.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTrait.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoSuperclasses.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoTraits.kt delete mode 100644 idea/testData/quickfix/override/nothingToOverride/afterNoOpenSuperFunction.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/beforeAddFunction.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionAbstractClass.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNoBody.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNonUnitReturnType.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTrait.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoSuperclasses.kt create mode 100644 idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoTraits.kt diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 868da4e6b67..9536b7af1f7 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -209,4 +209,9 @@ property.is.implemented.header=Is implemented in
property.is.overridden.header=Is overridden in
navigation.title.overriding.property=Choose Implementation of {0} -navigation.findUsages.title.overriding.property=Overriding properties of {0} \ No newline at end of file +navigation.findUsages.title.overriding.property=Overriding properties of {0} +add.function.to.supertype.family=Add Function to Supertype +add.function.to.supertype.action.multiple=Add function to supertype... +add.function.to.type.action.single=Add ''{0}'' to ''{1}'' +add.function.to.type.action=Add function to type +add.function.to.type.action.type.chooser=Choose type... diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JetAddFunctionToClassifierAction.java b/idea/src/org/jetbrains/jet/plugin/actions/JetAddFunctionToClassifierAction.java new file mode 100644 index 00000000000..f9f7ff26f13 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/actions/JetAddFunctionToClassifierAction.java @@ -0,0 +1,184 @@ +/* + * Copyright 2010-2013 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.jet.plugin.actions; + +import com.intellij.codeInsight.hint.QuestionAction; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopupStep; +import com.intellij.openapi.ui.popup.PopupStep; +import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.util.PlatformIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.Modality; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetClassBody; +import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.psi.JetPsiFactory; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils; +import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil; +import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Changes method signature to one of provided signatures. + * Based on {@link JetAddImportAction} + */ +public class JetAddFunctionToClassifierAction implements QuestionAction { + private final List functionsToAdd; + private final Project project; + private final Editor editor; + private final BindingContext bindingContext; + + /** + * @param project Project where action takes place. + * @param editor Editor where modification should be done. + * @param bindingContext BindingContext to be used for finding type declarations. + * @param functionsToAdd List of possible functions to add. + */ + public JetAddFunctionToClassifierAction( + @NotNull Project project, + @NotNull Editor editor, + @NotNull BindingContext bindingContext, + @NotNull List functionsToAdd + ) { + this.project = project; + this.editor = editor; + this.bindingContext = bindingContext; + this.functionsToAdd = new ArrayList(functionsToAdd); + } + + private static void addFunction( + @NotNull final Project project, + @NotNull final ClassDescriptor typeDescriptor, + @NotNull final FunctionDescriptor functionDescriptor, + @NotNull BindingContext bindingContext + ) { + final String signatureString = CodeInsightUtils.createFunctionSignatureStringFromDescriptor( + functionDescriptor, + /* shortTypeNames = */ false); + + PsiDocumentManager.getInstance(project).commitAllDocuments(); + + final JetClass classifierDeclaration = (JetClass) DescriptorToDeclarationUtil.getDeclaration(project, typeDescriptor, bindingContext); + CommandProcessor.getInstance().executeCommand(project, new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + JetClassBody body = classifierDeclaration.getBody(); + if (body == null) { + PsiElement whitespaceBefore = classifierDeclaration.add(JetPsiFactory.createWhiteSpace(project)); + body = (JetClassBody) classifierDeclaration.addAfter(JetPsiFactory.createEmptyClassBody(project), whitespaceBefore); + classifierDeclaration.addAfter(JetPsiFactory.createNewLine(project), body); + } + + String functionBody = ""; + if (typeDescriptor.getKind() != ClassKind.TRAIT && functionDescriptor.getModality() != Modality.ABSTRACT) { + functionBody = "{}"; + JetType returnType = functionDescriptor.getReturnType(); + if (returnType == null || !KotlinBuiltIns.getInstance().isUnit(returnType)) { + functionBody = "{ throw UnsupportedOperationException() }"; + } + } + JetNamedFunction functionElement = JetPsiFactory.createFunction(project, signatureString + functionBody); + PsiElement anchor = body.getRBrace(); + JetNamedFunction insertedFunctionElement = (JetNamedFunction) body.addBefore(functionElement, anchor); + + ReferenceToClassesShortening.compactReferenceToClasses(Collections.singletonList(insertedFunctionElement)); + } + }); + } + }, JetBundle.message("add.function.to.type.action"), null); + } + + @Override + public boolean execute() { + if (functionsToAdd.isEmpty()) { + return false; + } + + if (functionsToAdd.size() == 1 || !editor.getComponent().isShowing()) { + addFunction(functionsToAdd.get(0)); + } + else { + chooseFunctionAndAdd(); + } + + return true; + } + + private void chooseFunctionAndAdd() { + JBPopupFactory.getInstance().createListPopup(getFunctionPopup()).showInBestPositionFor(editor); + } + + private ListPopupStep getFunctionPopup() { + return new BaseListPopupStep( + JetBundle.message("add.function.to.type.action.type.chooser"), functionsToAdd) { + @Override + public boolean isAutoSelectionEnabled() { + return false; + } + + @Override + public PopupStep onChosen(FunctionDescriptor selectedValue, boolean finalChoice) { + if (finalChoice) { + addFunction(selectedValue); + } + return FINAL_CHOICE; + } + + @Override + public Icon getIconFor(FunctionDescriptor aValue) { + return PlatformIcons.FUNCTION_ICON; + } + + @NotNull + @Override + public String getTextFor(FunctionDescriptor functionDescriptor) { + ClassDescriptor type = (ClassDescriptor) functionDescriptor.getContainingDeclaration(); + return JetBundle.message("add.function.to.type.action.single", + CodeInsightUtils.createFunctionSignatureStringFromDescriptor( + functionDescriptor, + /* shortTypeNames = */ true), + type.getName().toString()); + } + }; + } + + private void addFunction(FunctionDescriptor functionToAdd) { + addFunction(project, (ClassDescriptor) functionToAdd.getContainingDeclaration(), + functionToAdd, bindingContext); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorToDeclarationUtil.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorToDeclarationUtil.java index ca707dba1e4..d914eba74f2 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorToDeclarationUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorToDeclarationUtil.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.plugin.codeInsight; +import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetFile; @@ -30,11 +31,15 @@ public final class DescriptorToDeclarationUtil { } public static PsiElement getDeclaration(JetFile file, DeclarationDescriptor descriptor, BindingContext bindingContext) { + return getDeclaration(file.getProject(), descriptor, bindingContext); + } + + public static PsiElement getDeclaration(Project project, DeclarationDescriptor descriptor, BindingContext bindingContext) { Collection elements = BindingContextUtils.descriptorToDeclarations(bindingContext, descriptor); if (elements.isEmpty()) { BuiltInsReferenceResolver libraryReferenceResolver = - file.getProject().getComponent(BuiltInsReferenceResolver.class); + project.getComponent(BuiltInsReferenceResolver.class); elements = libraryReferenceResolver.resolveStandardLibrarySymbol(descriptor); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java new file mode 100644 index 00000000000..05844b5f937 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java @@ -0,0 +1,171 @@ +/* + * Copyright 2010-2013 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.jet.plugin.quickfix; + +import com.google.common.collect.Lists; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.actions.JetAddFunctionToClassifierAction; +import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; +import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class AddFunctionToSupertypeFix extends JetHintAction { + private final List functionsToAdd; + + public AddFunctionToSupertypeFix(JetNamedFunction element) { + super(element); + functionsToAdd = generateFunctionsToAdd(element); + } + + private static List generateFunctionsToAdd(JetNamedFunction functionElement) { + BindingContext context = KotlinCacheManagerUtil.getDeclarationsFromProject(functionElement).getBindingContext(); + + FunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, functionElement); + if (functionDescriptor == null) return Collections.emptyList(); + + DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); + if (!(containingDeclaration instanceof ClassDescriptor)) return Collections.emptyList(); + + List functions = Lists.newArrayList(); + ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; + // TODO: filter out impossible supertypes (for example when argument's type isn't visible in a superclass). + for (ClassDescriptor supertypeDescriptor : getSupertypes(classDescriptor)) { + if (KotlinBuiltIns.getInstance().isAny(supertypeDescriptor.getDefaultType())) continue; + functions.add(generateFunctionSignatureForType(functionDescriptor, supertypeDescriptor)); + } + return functions; + } + + private static List getSupertypes(ClassDescriptor classDescriptor) { + List supertypes = Lists.newArrayList(TypeUtils.getAllSupertypes(classDescriptor.getDefaultType())); + Collections.sort(supertypes, new Comparator() { + @Override + public int compare(JetType o1, JetType o2) { + if (o1.equals(o2)) { + return 0; + } + if (JetTypeChecker.INSTANCE.isSubtypeOf(o1, o2)) { + return -1; + } + if (JetTypeChecker.INSTANCE.isSubtypeOf(o2, o1)) { + return 1; + } + return o1.toString().compareTo(o2.toString()); + } + }); + List supertypesDescriptors = Lists.newArrayList(); + for (JetType supertype : supertypes) { + supertypesDescriptors.add(DescriptorUtils.getClassDescriptorForType(supertype)); + } + return supertypesDescriptors; + } + + private static FunctionDescriptor generateFunctionSignatureForType( + FunctionDescriptor functionDescriptor, + ClassDescriptor typeDescriptor + ) { + // TODO: support for generics. + Modality modality = typeDescriptor.getModality(); + if (typeDescriptor.getKind() == ClassKind.TRAIT) { + modality = Modality.OPEN; + } + return functionDescriptor.copy( + typeDescriptor, + modality, + functionDescriptor.getVisibility(), + CallableMemberDescriptor.Kind.DECLARATION, + /* copyOverrides = */ false); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return super.isAvailable(project, editor, file) && !functionsToAdd.isEmpty(); + } + + @Override + public boolean showHint(Editor editor) { + return false; + } + + @NotNull + @Override + public String getText() { + if (functionsToAdd.size() == 1) { + FunctionDescriptor newFunction = functionsToAdd.get(0); + ClassDescriptor supertype = (ClassDescriptor) newFunction.getContainingDeclaration(); + return JetBundle.message("add.function.to.type.action.single", + CodeInsightUtils.createFunctionSignatureStringFromDescriptor(newFunction, /* shortTypeNames */ true), + supertype.getName().toString()); + } + else { + return JetBundle.message("add.function.to.supertype.action.multiple"); + } + } + + @NotNull + @Override + public String getFamilyName() { + return JetBundle.message("add.function.to.supertype.family"); + } + + @Override + protected void invoke(@NotNull final Project project, final Editor editor, JetFile file) { + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + @Override + public void run() { + createAction(project, editor).execute(); + } + }); + } + + @NotNull + private JetAddFunctionToClassifierAction createAction(Project project, Editor editor) { + BindingContext bindingContext = KotlinCacheManagerUtil.getDeclarationsFromProject(element).getBindingContext(); + return new JetAddFunctionToClassifierAction(project, editor, bindingContext, functionsToAdd); + } + + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { + @Nullable + @Override + public IntentionAction createAction(Diagnostic diagnostic) { + JetNamedFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction.class); + return function == null ? null : new AddFunctionToSupertypeFix(function); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 9369f5b330b..be8f7fb5b30 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -91,6 +91,7 @@ public class QuickFixes { factories.put(NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OVERRIDE_KEYWORD)); factories.put(NOTHING_TO_OVERRIDE, ChangeMemberFunctionSignatureFix.createFactory()); + factories.put(NOTHING_TO_OVERRIDE, AddFunctionToSupertypeFix.createFactory()); factories.put(VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(OVERRIDE_KEYWORD)); factories.put(USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory()); diff --git a/idea/testData/quickfix/override/nothingToOverride/afterAddFunction.kt b/idea/testData/quickfix/override/nothingToOverride/afterAddFunction.kt new file mode 100644 index 00000000000..63779357b90 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/afterAddFunction.kt @@ -0,0 +1,8 @@ +// "Add 'open fun f()' to 'A'" "true" +open class A { + open fun f() { + } +} +class B : A() { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionAbstractClass.kt b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionAbstractClass.kt new file mode 100644 index 00000000000..49ccd13b9be --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionAbstractClass.kt @@ -0,0 +1,7 @@ +// "Add 'abstract fun f()' to 'A'" "true" +abstract class A { + abstract fun f() +} +class B : A() { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNoBody.kt b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNoBody.kt new file mode 100644 index 00000000000..dfa3a7dee99 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNoBody.kt @@ -0,0 +1,8 @@ +// "Add 'open fun f()' to 'A'" "true" +trait A +{ + open fun f() +} +class B : A { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNonUnitReturnType.kt b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNonUnitReturnType.kt new file mode 100644 index 00000000000..cda0f209598 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionNonUnitReturnType.kt @@ -0,0 +1,9 @@ +// "Add 'open fun f(): Int' to 'A'" "true" +open class A { + open fun f(): Int { + throw UnsupportedOperationException() + } +} +class B : A() { + override fun f(): Int = 5 +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTrait.kt b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTrait.kt new file mode 100644 index 00000000000..92dda9599a1 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTrait.kt @@ -0,0 +1,7 @@ +// "Add 'open fun f()' to 'A'" "true" +trait A { + open fun f() +} +class B : A { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoSuperclasses.kt b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoSuperclasses.kt new file mode 100644 index 00000000000..d151ba2fd15 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoSuperclasses.kt @@ -0,0 +1,10 @@ +// "Add function to supertype..." "true" +open class A { +} +open class B : A() { + open fun f() { + } +} +class C : B() { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoTraits.kt b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoTraits.kt new file mode 100644 index 00000000000..32dcc19553a --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/afterAddFunctionTwoTraits.kt @@ -0,0 +1,8 @@ +// "Add function to supertype..." "true" +trait A { + open fun foo() +} +trait B {} +class C: A, B { + override fun foo() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/afterNoOpenSuperFunction.kt b/idea/testData/quickfix/override/nothingToOverride/afterNoOpenSuperFunction.kt deleted file mode 100644 index b42fbdf5f47..00000000000 --- a/idea/testData/quickfix/override/nothingToOverride/afterNoOpenSuperFunction.kt +++ /dev/null @@ -1,11 +0,0 @@ -// "Change function signature to 'override fun f(a: Int)'" "false" -// ERROR: 'f' overrides nothing -// ACTION: Remove 'override' modifier -open class A { - open fun foo() {} - fun f(a: Int) {} -} - -class B : A(){ - override fun f(a: String) {} -} diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeAddFunction.kt b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunction.kt new file mode 100644 index 00000000000..3136907d089 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunction.kt @@ -0,0 +1,6 @@ +// "Add 'open fun f()' to 'A'" "true" +open class A { +} +class B : A() { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionAbstractClass.kt b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionAbstractClass.kt new file mode 100644 index 00000000000..f6b022c0513 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionAbstractClass.kt @@ -0,0 +1,6 @@ +// "Add 'abstract fun f()' to 'A'" "true" +abstract class A { +} +class B : A() { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNoBody.kt b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNoBody.kt new file mode 100644 index 00000000000..705d1af6ec4 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNoBody.kt @@ -0,0 +1,5 @@ +// "Add 'open fun f()' to 'A'" "true" +trait A +class B : A { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNonUnitReturnType.kt b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNonUnitReturnType.kt new file mode 100644 index 00000000000..8f76628cbb3 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNonUnitReturnType.kt @@ -0,0 +1,6 @@ +// "Add 'open fun f(): Int' to 'A'" "true" +open class A { +} +class B : A() { + override fun f(): Int = 5 +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTrait.kt b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTrait.kt new file mode 100644 index 00000000000..3d2c4024c5b --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTrait.kt @@ -0,0 +1,6 @@ +// "Add 'open fun f()' to 'A'" "true" +trait A { +} +class B : A { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoSuperclasses.kt b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoSuperclasses.kt new file mode 100644 index 00000000000..d717c14cf3f --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoSuperclasses.kt @@ -0,0 +1,8 @@ +// "Add function to supertype..." "true" +open class A { +} +open class B : A() { +} +class C : B() { + override fun f() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoTraits.kt b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoTraits.kt new file mode 100644 index 00000000000..48498de2050 --- /dev/null +++ b/idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoTraits.kt @@ -0,0 +1,6 @@ +// "Add function to supertype..." "true" +trait A {} +trait B {} +class C: A, B { + override fun foo() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/nothingToOverride/beforeNoOpenSuperFunction.kt b/idea/testData/quickfix/override/nothingToOverride/beforeNoOpenSuperFunction.kt index b42fbdf5f47..1ae08772709 100644 --- a/idea/testData/quickfix/override/nothingToOverride/beforeNoOpenSuperFunction.kt +++ b/idea/testData/quickfix/override/nothingToOverride/beforeNoOpenSuperFunction.kt @@ -1,5 +1,6 @@ // "Change function signature to 'override fun f(a: Int)'" "false" // ERROR: 'f' overrides nothing +// ACTION: Add 'open fun f(a: String)' to 'A' // ACTION: Remove 'override' modifier open class A { open fun foo() {} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java index d35d22f475b..d5fc32546e1 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -866,6 +866,41 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { @TestMetadata("idea/testData/quickfix/override/nothingToOverride") public static class NothingToOverride extends AbstractQuickFixTest { + @TestMetadata("beforeAddFunction.kt") + public void testAddFunction() throws Exception { + doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddFunction.kt"); + } + + @TestMetadata("beforeAddFunctionAbstractClass.kt") + public void testAddFunctionAbstractClass() throws Exception { + doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionAbstractClass.kt"); + } + + @TestMetadata("beforeAddFunctionNoBody.kt") + public void testAddFunctionNoBody() throws Exception { + doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNoBody.kt"); + } + + @TestMetadata("beforeAddFunctionNonUnitReturnType.kt") + public void testAddFunctionNonUnitReturnType() throws Exception { + doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionNonUnitReturnType.kt"); + } + + @TestMetadata("beforeAddFunctionTrait.kt") + public void testAddFunctionTrait() throws Exception { + doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTrait.kt"); + } + + @TestMetadata("beforeAddFunctionTwoSuperclasses.kt") + public void testAddFunctionTwoSuperclasses() throws Exception { + doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoSuperclasses.kt"); + } + + @TestMetadata("beforeAddFunctionTwoTraits.kt") + public void testAddFunctionTwoTraits() throws Exception { + doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddFunctionTwoTraits.kt"); + } + @TestMetadata("beforeAddParameter.kt") public void testAddParameter() throws Exception { doTest("idea/testData/quickfix/override/nothingToOverride/beforeAddParameter.kt");