From c02f0a7d0475ee7805632ebc7b385aca25a86be1 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 26 Aug 2013 20:27:27 +0400 Subject: [PATCH] Intention to convert a member to an extension --- .../org/jetbrains/jet/lexer/JetTokens.java | 3 + .../jet/generators/tests/GenerateTests.java | 1 + .../after.kt.template | 6 + .../before.kt.template | 5 + .../ConvertMemberToExtension/description.html | 5 + idea/src/META-INF/plugin.xml | 5 + .../jetbrains/jet/plugin/JetBundle.properties | 4 +- .../ConvertMemberToExtension.java | 152 ++++++++++++++++++ .../convertMemberToExtension/abstract.kt | 3 + .../abstract.kt.after | 5 + .../convertMemberToExtension/explicitUnit.kt | 3 + .../explicitUnit.kt.after | 5 + .../convertMemberToExtension/extension.kt | 4 + .../convertMemberToExtension/functionType.kt | 3 + .../functionType.kt.after | 5 + .../convertMemberToExtension/genericClass.kt | 3 + .../genericClass.kt.after | 4 + .../convertMemberToExtension/genericFun.kt | 3 + .../genericFun.kt.after | 4 + .../genericFunInGenericClass.kt | 3 + .../genericFunInGenericClass.kt.after | 4 + ...genericFunInGenericClassWithUpperBounds.kt | 3 + ...cFunInGenericClassWithUpperBounds.kt.after | 4 + .../genericFunParamAfterName.kt | 3 + .../genericFunParamAfterName.kt.after | 4 + .../inFunctionBody.kt | 4 + .../convertMemberToExtension/inObject.kt | 4 + .../convertMemberToExtension/internal.kt | 3 + .../internal.kt.after | 4 + .../convertMemberToExtension/localFunction.kt | 6 + .../nonBlockBodyNoType.kt | 3 + .../nonBlockBodyNoType.kt.after | 4 + .../nonBlockBodyWithType.kt | 3 + .../nonBlockBodyWithType.kt.after | 4 + .../outsideFunction.kt | 4 + .../convertMemberToExtension/private.kt | 3 + .../convertMemberToExtension/private.kt.after | 4 + .../convertMemberToExtension/protected.kt | 3 + .../protected.kt.after | 4 + .../convertMemberToExtension/public.kt | 3 + .../convertMemberToExtension/public.kt.after | 4 + .../convertMemberToExtension/simple.kt | 3 + .../convertMemberToExtension/simple.kt.after | 5 + .../topLevelFunction.kt | 2 + .../convertMemberToExtension/typeFqName.kt | 3 + .../typeFqName.kt.after | 5 + .../convertMemberToExtension/unknownType.kt | 3 + .../unknownType.kt.after | 5 + .../convertMemberToExtension/withType.kt | 3 + .../withType.kt.after | 5 + .../AbstractCodeTransformationTest.java | 6 +- .../CodeTransformationsTestGenerated.java | 131 ++++++++++++++- 52 files changed, 472 insertions(+), 3 deletions(-) create mode 100644 idea/resources/intentionDescriptions/ConvertMemberToExtension/after.kt.template create mode 100644 idea/resources/intentionDescriptions/ConvertMemberToExtension/before.kt.template create mode 100644 idea/resources/intentionDescriptions/ConvertMemberToExtension/description.html create mode 100644 idea/src/org/jetbrains/jet/plugin/intentions/declarations/ConvertMemberToExtension.java create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/extension.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/inFunctionBody.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/inObject.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/internal.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/internal.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/localFunction.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/outsideFunction.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/private.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/private.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/protected.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/protected.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/public.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/public.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/simple.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/simple.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/topLevelFunction.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt.after create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/withType.kt create mode 100644 idea/testData/intentions/declarations/convertMemberToExtension/withType.kt.after diff --git a/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java b/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java index 0477cd27a1d..0093a8ac51c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java +++ b/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java @@ -183,6 +183,9 @@ public interface JetTokens { OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD ); + + TokenSet VISIBILITY_MODIFIERS = TokenSet.create(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD); + TokenSet WHITESPACES = TokenSet.create(TokenType.WHITE_SPACE); /** diff --git a/generators/org/jetbrains/jet/generators/tests/GenerateTests.java b/generators/org/jetbrains/jet/generators/tests/GenerateTests.java index bfff16f79f1..cc704e2856d 100644 --- a/generators/org/jetbrains/jet/generators/tests/GenerateTests.java +++ b/generators/org/jetbrains/jet/generators/tests/GenerateTests.java @@ -371,6 +371,7 @@ public class GenerateTests { testModel("idea/testData/intentions/branched/when/eliminateSubject", "doTestEliminateWhenSubject"), testModel("idea/testData/intentions/declarations/split", "doTestSplitProperty"), testModel("idea/testData/intentions/declarations/join", "doTestJoinProperty"), + testModel("idea/testData/intentions/declarations/convertMemberToExtension", "doTestConvertMemberToExtension"), testModel("idea/testData/intentions/removeUnnecessaryParentheses", "doTestRemoveUnnecessaryParentheses") ); diff --git a/idea/resources/intentionDescriptions/ConvertMemberToExtension/after.kt.template b/idea/resources/intentionDescriptions/ConvertMemberToExtension/after.kt.template new file mode 100644 index 00000000000..71167251bef --- /dev/null +++ b/idea/resources/intentionDescriptions/ConvertMemberToExtension/after.kt.template @@ -0,0 +1,6 @@ +class Foo { +} + +fun Foo.get(): T { + return t +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ConvertMemberToExtension/before.kt.template b/idea/resources/intentionDescriptions/ConvertMemberToExtension/before.kt.template new file mode 100644 index 00000000000..954e1027662 --- /dev/null +++ b/idea/resources/intentionDescriptions/ConvertMemberToExtension/before.kt.template @@ -0,0 +1,5 @@ +class Foo { + fun get(): T { + return t + } +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ConvertMemberToExtension/description.html b/idea/resources/intentionDescriptions/ConvertMemberToExtension/description.html new file mode 100644 index 00000000000..db78e07a917 --- /dev/null +++ b/idea/resources/intentionDescriptions/ConvertMemberToExtension/description.html @@ -0,0 +1,5 @@ + + +This intention converts a member of a class or trait into an extension to this class/trait. + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 08b615972a8..3c958bffa0d 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -405,6 +405,11 @@ Kotlin + + org.jetbrains.jet.plugin.intentions.declarations.ConvertMemberToExtension + Kotlin + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 3d2721e659d..c271c906a59 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -269,4 +269,6 @@ super.methods.action.key.find.usages=find usages of find.what.implementing.methods.checkbox=&Implementing functions find.what.overriding.methods.checkbox=Over&riding functions -find.options.include.overloaded.methods.checkbox=Include o&verloaded functions and extensions \ No newline at end of file +find.options.include.overloaded.methods.checkbox=Include o&verloaded functions and extensions + +convert.to.extension=Convert to extension \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/declarations/ConvertMemberToExtension.java b/idea/src/org/jetbrains/jet/plugin/intentions/declarations/ConvertMemberToExtension.java new file mode 100644 index 00000000000..d372a458ad3 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/intentions/declarations/ConvertMemberToExtension.java @@ -0,0 +1,152 @@ +/* + * 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.intentions.declarations; + +import com.intellij.codeInsight.intention.impl.BaseIntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.jet.lexer.JetTokens; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; + +import java.util.List; + +public class ConvertMemberToExtension extends BaseIntentionAction { + + @NotNull + @Override + public String getText() { + return getFamilyName(); + } + + @NotNull + @Override + public String getFamilyName() { + return JetBundle.message("convert.to.extension"); + } + + @Override + public boolean isAvailable( + @NotNull Project project, Editor editor, PsiFile file + ) { + JetNamedFunction function = getTarget(editor, file); + return function != null + && function.getParent() instanceof JetClassBody + && function.getParent().getParent() instanceof JetClass + && function.getReceiverTypeRef() == null; + } + + private static JetNamedFunction getTarget(Editor editor, PsiFile file) { + PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + return PsiTreeUtil.getParentOfType(element, JetNamedFunction.class, false, JetExpression.class); + } + + @Override + public void invoke( + @NotNull Project project, Editor editor, PsiFile file + ) throws IncorrectOperationException { + JetNamedFunction member = getTarget(editor, file); + assert member != null : "Must be checked by isAvailable"; + + BindingContext bindingContext = KotlinCacheManagerUtil.getDeclarationsBindingContext(member); + SimpleFunctionDescriptor memberDescriptor = bindingContext.get(BindingContext.FUNCTION, member); + + if (memberDescriptor == null) return; + assert memberDescriptor.getReceiverParameter() == null : "Must have checked that there's no receiver earlier\n" + + "Descriptor: " + memberDescriptor + "\n" + + "Declaration: " + member.getText(); + + DeclarationDescriptor containingClass = memberDescriptor.getContainingDeclaration(); + assert containingClass instanceof ClassDescriptor : "Members must be contained in classes: \n" + + "Descriptor: " + memberDescriptor + "\n" + + "Declaration & context: " + member.getParent().getParent().getText(); + + PsiElement outermostParent = JetPsiUtil.getOutermostParent(member, file, false); + + String receiver = ((ClassDescriptor) containingClass).getDefaultType() + "."; + PsiElement identifier = member.getNameIdentifier(); + String name = identifier == null ? "" : identifier.getText(); + + JetParameterList valueParameterList = member.getValueParameterList(); + JetTypeReference returnTypeRef = member.getReturnTypeRef(); + String receiverAndTheRest = receiver + + name + + (valueParameterList == null ? "" : valueParameterList.getText()) + + (returnTypeRef != null ? ": " + returnTypeRef.getText() : "") + + textOfBody(member); + + String extensionText = modifiers(member) + "fun " + typeParameters(member) + receiverAndTheRest; + + JetNamedFunction extension = JetPsiFactory.createFunction(project, extensionText); + + file.addAfter(extension, outermostParent); + file.addAfter(JetPsiFactory.createNewLine(project), outermostParent); + file.addAfter(JetPsiFactory.createNewLine(project), outermostParent); + member.delete(); + } + + private static String modifiers(JetNamedFunction member) { + JetModifierList modifierList = member.getModifierList(); + if (modifierList == null) return ""; + for (IElementType modifierType : JetTokens.VISIBILITY_MODIFIERS.getTypes()) { + PsiElement modifier = modifierList.getModifier((JetToken) modifierType); + if (modifier != null) { + return modifierType == JetTokens.PROTECTED_KEYWORD ? "" : modifier.getText() + " "; + } + } + return ""; + } + + private static String typeParameters(JetNamedFunction member) { + PsiElement classElement = member.getParent().getParent(); + assert classElement instanceof JetClass : "Must be checked in isAvailable: " + classElement.getText(); + + List allTypeParameters = ContainerUtil.concat( + ((JetClass) classElement).getTypeParameters(), + member.getTypeParameters()); + if (allTypeParameters.isEmpty()) return ""; + return "<" + StringUtil.join(allTypeParameters, new Function() { + @Override + public String fun(JetTypeParameter parameter) { + return parameter.getText(); + } + }, ", ") + "> "; + } + + private static String textOfBody(JetNamedFunction member) { + JetExpression bodyExpression = member.getBodyExpression(); + if (bodyExpression == null) return "{}"; + if (!member.hasBlockBody()) return " = " + bodyExpression.getText(); + return bodyExpression.getText(); + } + +} diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt b/idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt new file mode 100644 index 00000000000..d9a5fbc92d7 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt @@ -0,0 +1,3 @@ +abstract class Owner { + abstract fun f() +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt.after new file mode 100644 index 00000000000..8868458bece --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt.after @@ -0,0 +1,5 @@ +abstract class Owner { +} + +fun Owner.f() { +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt b/idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt new file mode 100644 index 00000000000..37f61c6dde6 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt @@ -0,0 +1,3 @@ +class Owner { + fun f(): Unit {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt.after new file mode 100644 index 00000000000..c838f1b1c26 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt.after @@ -0,0 +1,5 @@ +class Owner { +} + +fun Owner.f(): Unit { +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/extension.kt b/idea/testData/intentions/declarations/convertMemberToExtension/extension.kt new file mode 100644 index 00000000000..e46be136c2e --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/extension.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +abstract class Owner { + fun Int.f() {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt b/idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt new file mode 100644 index 00000000000..3e31bf3cd8f --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt @@ -0,0 +1,3 @@ +class Owner { + fun f(p: () -> Unit): (Int) -> String {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt.after new file mode 100644 index 00000000000..881701ac105 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt.after @@ -0,0 +1,5 @@ +class Owner { +} + +fun Owner.f(p: () -> Unit): (Int) -> String { +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt b/idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt new file mode 100644 index 00000000000..27ff17e4aa9 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt @@ -0,0 +1,3 @@ +abstract class Owner { + fun f(t: T): T = t +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt.after new file mode 100644 index 00000000000..968268f2435 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +fun Owner.f(t: T): T = t \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt b/idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt new file mode 100644 index 00000000000..fc870620ca0 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt @@ -0,0 +1,3 @@ +abstract class Owner { + fun f(t: T): T = t +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt.after new file mode 100644 index 00000000000..ac6c26ebb88 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +fun Owner.f(t: T): T = t \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt new file mode 100644 index 00000000000..52e1134e40a --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt @@ -0,0 +1,3 @@ +abstract class Owner { + fun f(t: T, r: R): R = t +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt.after new file mode 100644 index 00000000000..a8497f3a9e1 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +fun Owner.f(t: T, r: R): R = t \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt new file mode 100644 index 00000000000..387c48a1450 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt @@ -0,0 +1,3 @@ +abstract class Owner> { + fun f(t: T, r: R): R = t +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt.after new file mode 100644 index 00000000000..cf29f7304c0 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt.after @@ -0,0 +1,4 @@ +abstract class Owner> { +} + +fun , R : T> Owner.f(t: T, r: R): R = t \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt new file mode 100644 index 00000000000..0cfadfc44db --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt @@ -0,0 +1,3 @@ +abstract class Owner { + fun f(t: T): T = t +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt.after new file mode 100644 index 00000000000..ac6c26ebb88 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +fun Owner.f(t: T): T = t \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/inFunctionBody.kt b/idea/testData/intentions/declarations/convertMemberToExtension/inFunctionBody.kt new file mode 100644 index 00000000000..3118881ec8a --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/inFunctionBody.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +abstract class Owner { + fun f() {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/inObject.kt b/idea/testData/intentions/declarations/convertMemberToExtension/inObject.kt new file mode 100644 index 00000000000..4611fb18dec --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/inObject.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +object Owner { + fun f() {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/internal.kt b/idea/testData/intentions/declarations/convertMemberToExtension/internal.kt new file mode 100644 index 00000000000..da4691c3021 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/internal.kt @@ -0,0 +1,3 @@ +abstract class Owner { + internal fun f() = 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/internal.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/internal.kt.after new file mode 100644 index 00000000000..70e71d75359 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/internal.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +internal fun Owner.f() = 1 \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/localFunction.kt b/idea/testData/intentions/declarations/convertMemberToExtension/localFunction.kt new file mode 100644 index 00000000000..c9cbad26bd0 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/localFunction.kt @@ -0,0 +1,6 @@ +// IS_APPLICABLE: false +class Owner { + fun f() { + fun f() {} + } +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt new file mode 100644 index 00000000000..76ab936fcd7 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt @@ -0,0 +1,3 @@ +class Owner { + fun f() = 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt.after new file mode 100644 index 00000000000..c1fc3b4f47c --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt.after @@ -0,0 +1,4 @@ +class Owner { +} + +fun Owner.f() = 1 \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt new file mode 100644 index 00000000000..7e6dc778935 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt @@ -0,0 +1,3 @@ +class Owner { + fun f(): Int = 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt.after new file mode 100644 index 00000000000..1214f778330 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt.after @@ -0,0 +1,4 @@ +class Owner { +} + +fun Owner.f(): Int = 1 \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/outsideFunction.kt b/idea/testData/intentions/declarations/convertMemberToExtension/outsideFunction.kt new file mode 100644 index 00000000000..5f6333d5f7f --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/outsideFunction.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +abstract class Owner { + abstract fun f() +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/private.kt b/idea/testData/intentions/declarations/convertMemberToExtension/private.kt new file mode 100644 index 00000000000..004eb2ea46a --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/private.kt @@ -0,0 +1,3 @@ +abstract class Owner { + private fun f() = 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/private.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/private.kt.after new file mode 100644 index 00000000000..dca6558532e --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/private.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +private fun Owner.f() = 1 \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/protected.kt b/idea/testData/intentions/declarations/convertMemberToExtension/protected.kt new file mode 100644 index 00000000000..027e44c4936 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/protected.kt @@ -0,0 +1,3 @@ +abstract class Owner { + protected fun f() = 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/protected.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/protected.kt.after new file mode 100644 index 00000000000..ba37da9bae1 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/protected.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +fun Owner.f() = 1 \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/public.kt b/idea/testData/intentions/declarations/convertMemberToExtension/public.kt new file mode 100644 index 00000000000..3f2bd78ad02 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/public.kt @@ -0,0 +1,3 @@ +abstract class Owner { + public fun f() = 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/public.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/public.kt.after new file mode 100644 index 00000000000..85ecb717ac4 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/public.kt.after @@ -0,0 +1,4 @@ +abstract class Owner { +} + +public fun Owner.f() = 1 \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/simple.kt b/idea/testData/intentions/declarations/convertMemberToExtension/simple.kt new file mode 100644 index 00000000000..0a6fd69fce1 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/simple.kt @@ -0,0 +1,3 @@ +class Owner { + fun f() {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/simple.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/simple.kt.after new file mode 100644 index 00000000000..026942eb60e --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/simple.kt.after @@ -0,0 +1,5 @@ +class Owner { +} + +fun Owner.f() { +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/topLevelFunction.kt b/idea/testData/intentions/declarations/convertMemberToExtension/topLevelFunction.kt new file mode 100644 index 00000000000..64404057fce --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/topLevelFunction.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +fun f() {} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt b/idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt new file mode 100644 index 00000000000..e81e2704d6d --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt @@ -0,0 +1,3 @@ +class Owner { + fun f(p: jet.Int): jet.String {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt.after new file mode 100644 index 00000000000..7b466928a21 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt.after @@ -0,0 +1,5 @@ +class Owner { +} + +fun Owner.f(p: jet.Int): jet.String { +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt b/idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt new file mode 100644 index 00000000000..e09668f02de --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt @@ -0,0 +1,3 @@ +class Owner { + fun f(p: Foo): bar.Baz {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt.after new file mode 100644 index 00000000000..7233eed0611 --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt.after @@ -0,0 +1,5 @@ +class Owner { +} + +fun Owner.f(p: Foo): bar.Baz { +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/withType.kt b/idea/testData/intentions/declarations/convertMemberToExtension/withType.kt new file mode 100644 index 00000000000..49ee1bd345e --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/withType.kt @@ -0,0 +1,3 @@ +class Owner { + fun f(): Int {} +} \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/withType.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/withType.kt.after new file mode 100644 index 00000000000..d542a992e3a --- /dev/null +++ b/idea/testData/intentions/declarations/convertMemberToExtension/withType.kt.after @@ -0,0 +1,5 @@ +class Owner { +} + +fun Owner.f(): Int { +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java index 80382dcdef5..dd61009c664 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java @@ -23,8 +23,8 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.testFramework.LightCodeInsightTestCase; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.InTextDirectivesUtils; -import org.jetbrains.jet.plugin.intentions.RemoveUnnecessaryParenthesesIntention; import org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions.*; +import org.jetbrains.jet.plugin.intentions.declarations.ConvertMemberToExtension; import org.jetbrains.jet.plugin.intentions.declarations.SplitPropertyDeclarationIntention; import java.io.File; @@ -106,6 +106,10 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes doTestIntention(path, new RemoveUnnecessaryParenthesesIntention()); } + public void doTestConvertMemberToExtension(@NotNull String path) throws Exception { + doTestIntention(path, new ConvertMemberToExtension()); + } + private void doTestIntention(@NotNull String path, @NotNull IntentionAction intentionAction) throws Exception { configureByFile(path); diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationsTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationsTestGenerated.java index 586744b7b3f..d84a31d84c4 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationsTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationsTestGenerated.java @@ -30,7 +30,7 @@ import org.jetbrains.jet.plugin.intentions.AbstractCodeTransformationTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@InnerTestClasses({CodeTransformationsTestGenerated.IfToAssignment.class, CodeTransformationsTestGenerated.IfToReturn.class, CodeTransformationsTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationsTestGenerated.WhenToAssignment.class, CodeTransformationsTestGenerated.WhenToReturn.class, CodeTransformationsTestGenerated.AssignmentToIf.class, CodeTransformationsTestGenerated.AssignmentToWhen.class, CodeTransformationsTestGenerated.PropertyToIf.class, CodeTransformationsTestGenerated.PropertyToWhen.class, CodeTransformationsTestGenerated.ReturnToIf.class, CodeTransformationsTestGenerated.ReturnToWhen.class, CodeTransformationsTestGenerated.IfToWhen.class, CodeTransformationsTestGenerated.WhenToIf.class, CodeTransformationsTestGenerated.Flatten.class, CodeTransformationsTestGenerated.IntroduceSubject.class, CodeTransformationsTestGenerated.EliminateSubject.class, CodeTransformationsTestGenerated.Split.class, CodeTransformationsTestGenerated.Join.class, CodeTransformationsTestGenerated.RemoveUnnecessaryParentheses.class}) +@InnerTestClasses({CodeTransformationsTestGenerated.IfToAssignment.class, CodeTransformationsTestGenerated.IfToReturn.class, CodeTransformationsTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationsTestGenerated.WhenToAssignment.class, CodeTransformationsTestGenerated.WhenToReturn.class, CodeTransformationsTestGenerated.AssignmentToIf.class, CodeTransformationsTestGenerated.AssignmentToWhen.class, CodeTransformationsTestGenerated.PropertyToIf.class, CodeTransformationsTestGenerated.PropertyToWhen.class, CodeTransformationsTestGenerated.ReturnToIf.class, CodeTransformationsTestGenerated.ReturnToWhen.class, CodeTransformationsTestGenerated.IfToWhen.class, CodeTransformationsTestGenerated.WhenToIf.class, CodeTransformationsTestGenerated.Flatten.class, CodeTransformationsTestGenerated.IntroduceSubject.class, CodeTransformationsTestGenerated.EliminateSubject.class, CodeTransformationsTestGenerated.Split.class, CodeTransformationsTestGenerated.Join.class, CodeTransformationsTestGenerated.ConvertMemberToExtension.class, CodeTransformationsTestGenerated.RemoveUnnecessaryParentheses.class}) public class CodeTransformationsTestGenerated extends AbstractCodeTransformationTest { @TestMetadata("idea/testData/intentions/branched/folding/ifToAssignment") public static class IfToAssignment extends AbstractCodeTransformationTest { @@ -791,6 +791,134 @@ public class CodeTransformationsTestGenerated extends AbstractCodeTransformation } + @TestMetadata("idea/testData/intentions/declarations/convertMemberToExtension") + public static class ConvertMemberToExtension extends AbstractCodeTransformationTest { + @TestMetadata("abstract.kt") + public void testAbstract() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/abstract.kt"); + } + + public void testAllFilesPresentInConvertMemberToExtension() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/intentions/declarations/convertMemberToExtension"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("explicitUnit.kt") + public void testExplicitUnit() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/explicitUnit.kt"); + } + + @TestMetadata("extension.kt") + public void testExtension() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/extension.kt"); + } + + @TestMetadata("functionType.kt") + public void testFunctionType() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/functionType.kt"); + } + + @TestMetadata("genericClass.kt") + public void testGenericClass() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/genericClass.kt"); + } + + @TestMetadata("genericFun.kt") + public void testGenericFun() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/genericFun.kt"); + } + + @TestMetadata("genericFunInGenericClass.kt") + public void testGenericFunInGenericClass() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClass.kt"); + } + + @TestMetadata("genericFunInGenericClassWithUpperBounds.kt") + public void testGenericFunInGenericClassWithUpperBounds() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/genericFunInGenericClassWithUpperBounds.kt"); + } + + @TestMetadata("genericFunParamAfterName.kt") + public void testGenericFunParamAfterName() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/genericFunParamAfterName.kt"); + } + + @TestMetadata("inFunctionBody.kt") + public void testInFunctionBody() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/inFunctionBody.kt"); + } + + @TestMetadata("inObject.kt") + public void testInObject() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/inObject.kt"); + } + + @TestMetadata("internal.kt") + public void testInternal() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/internal.kt"); + } + + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/localFunction.kt"); + } + + @TestMetadata("nonBlockBodyNoType.kt") + public void testNonBlockBodyNoType() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyNoType.kt"); + } + + @TestMetadata("nonBlockBodyWithType.kt") + public void testNonBlockBodyWithType() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/nonBlockBodyWithType.kt"); + } + + @TestMetadata("outsideFunction.kt") + public void testOutsideFunction() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/outsideFunction.kt"); + } + + @TestMetadata("private.kt") + public void testPrivate() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/private.kt"); + } + + @TestMetadata("protected.kt") + public void testProtected() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/protected.kt"); + } + + @TestMetadata("public.kt") + public void testPublic() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/public.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/simple.kt"); + } + + @TestMetadata("topLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/topLevelFunction.kt"); + } + + @TestMetadata("typeFqName.kt") + public void testTypeFqName() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/typeFqName.kt"); + } + + @TestMetadata("unknownType.kt") + public void testUnknownType() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/unknownType.kt"); + } + + @TestMetadata("withType.kt") + public void testWithType() throws Exception { + doTestConvertMemberToExtension("idea/testData/intentions/declarations/convertMemberToExtension/withType.kt"); + } + + } + @TestMetadata("idea/testData/intentions/removeUnnecessaryParentheses") public static class RemoveUnnecessaryParentheses extends AbstractCodeTransformationTest { public void testAllFilesPresentInRemoveUnnecessaryParentheses() throws Exception { @@ -879,6 +1007,7 @@ public class CodeTransformationsTestGenerated extends AbstractCodeTransformation suite.addTestSuite(EliminateSubject.class); suite.addTestSuite(Split.class); suite.addTestSuite(Join.class); + suite.addTestSuite(ConvertMemberToExtension.class); suite.addTestSuite(RemoveUnnecessaryParentheses.class); return suite; }