diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties index 929e4c90ac9..361107ec14d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties @@ -1,6 +1,5 @@ #quick fix messages add.return.type=Add return type declaration -remove.function.body=Remove function body add.init.keyword=Add 'init' keyword add.init.keyword.family=Add 'init' keyword add.init.keyword.in.whole.project=Add 'init' keyword in whole project diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 852998259a3..e9dbfb4b379 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -78,8 +78,7 @@ class QuickFixRegistrar : QuickFixContributor { ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.registerFactory(removeAbstractModifierFactory, addAbstractToClassFactory) - val removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory() - ABSTRACT_FUNCTION_WITH_BODY.registerFactory(removeAbstractModifierFactory, removeFunctionBodyFactory) + ABSTRACT_FUNCTION_WITH_BODY.registerFactory(removeAbstractModifierFactory, RemoveFunctionBodyFix) NON_ABSTRACT_FUNCTION_WITH_NO_BODY.registerFactory(addAbstractModifierFactory, AddFunctionBodyFix) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveFunctionBodyFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveFunctionBodyFix.kt index 44b8ab639af..796663418d6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveFunctionBodyFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveFunctionBodyFix.kt @@ -14,88 +14,44 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.quickfix; +package org.jetbrains.kotlin.idea.quickfix -import com.intellij.extapi.psi.ASTDelegatePsiElement; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.LeafPsiElement; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.diagnostics.Diagnostic; -import org.jetbrains.kotlin.idea.KotlinBundle; -import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil; -import org.jetbrains.kotlin.lexer.KtTokens; -import org.jetbrains.kotlin.psi.KtExpression; -import org.jetbrains.kotlin.psi.KtFile; -import org.jetbrains.kotlin.psi.KtFunction; +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.util.CommentSaver +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType -public class RemoveFunctionBodyFix extends KotlinQuickFixAction { +class RemoveFunctionBodyFix(element: KtFunction) : KotlinQuickFixAction(element) { + override fun getFamilyName() = "Remove function body" - public RemoveFunctionBodyFix(@NotNull KtFunction element) { - super(element); + override fun getText() = familyName + + override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { + return super.isAvailable(project, editor, file) && element.hasBody() } - @NotNull - @Override - public String getText() { - return KotlinBundle.message("remove.function.body"); - } - - @NotNull - @Override - public String getFamilyName() { - return KotlinBundle.message("remove.function.body"); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) { - return super.isAvailable(project, editor, file) && getElement().hasBody(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull KtFile file) throws IncorrectOperationException { - KtFunction function = (KtFunction) getElement().copy(); - assert function instanceof ASTDelegatePsiElement; - ASTDelegatePsiElement functionElementWithAst = (ASTDelegatePsiElement) function; - KtExpression bodyExpression = function.getBodyExpression(); - assert bodyExpression != null; - if (function.hasBlockBody()) { - PsiElement prevElement = bodyExpression.getPrevSibling(); - QuickFixUtil.removePossiblyWhiteSpace(functionElementWithAst, prevElement); - functionElementWithAst.deleteChildInternal(bodyExpression.getNode()); + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + val bodyExpression = element.bodyExpression!! + val equalsToken = element.equalsToken + if (equalsToken != null) { + val commentSaver = CommentSaver(PsiChildRange(equalsToken.nextSibling, bodyExpression.prevSibling), true) + element.deleteChildRange(equalsToken, bodyExpression) + commentSaver.restore(element) } else { - PsiElement prevElement = bodyExpression.getPrevSibling(); - PsiElement prevPrevElement = prevElement.getPrevSibling(); - QuickFixUtil.removePossiblyWhiteSpace(functionElementWithAst, prevElement); - removePossiblyEquationSign(functionElementWithAst, prevElement); - removePossiblyEquationSign(functionElementWithAst, prevPrevElement); - functionElementWithAst.deleteChildInternal(bodyExpression.getNode()); + bodyExpression.delete() } - getElement().replace(function); } - private static boolean removePossiblyEquationSign(@NotNull ASTDelegatePsiElement element, @Nullable PsiElement possiblyEq) { - if (possiblyEq instanceof LeafPsiElement && ((LeafPsiElement)possiblyEq).getElementType() == KtTokens.EQ) { - QuickFixUtil.removePossiblyWhiteSpace(element, possiblyEq.getNextSibling()); - element.deleteChildInternal(possiblyEq.getNode()); - return true; + companion object : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { + val function = diagnostic.psiElement.getNonStrictParentOfType() ?: return null + return RemoveFunctionBodyFix(function) } - return false; - } - - public static KotlinSingleIntentionActionFactory createFactory() { - return new KotlinSingleIntentionActionFactory() { - @Override - public KotlinQuickFixAction createAction(@NotNull Diagnostic diagnostic) { - KtFunction function = QuickFixUtil.getParentElementOfType(diagnostic, KtFunction.class); - if (function == null) return null; - return new RemoveFunctionBodyFix(function); - } - }; } } diff --git a/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt new file mode 100644 index 00000000000..b0c93f60fd5 --- /dev/null +++ b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt @@ -0,0 +1,6 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() /*1*/ { // 2 + // 3 + } +} diff --git a/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt.after b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt.after new file mode 100644 index 00000000000..bd4e0f8f427 --- /dev/null +++ b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt.after @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() /*1*/ +} diff --git a/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt new file mode 100644 index 00000000000..27eb6f12a58 --- /dev/null +++ b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt @@ -0,0 +1,5 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() = /*1*/ + { "" /*2*/ } // 3 +} diff --git a/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt.after b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt.after new file mode 100644 index 00000000000..d847c57383b --- /dev/null +++ b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt.after @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() // 3/*1*/ +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 3c9dbdc5897..93e73e77b80 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -63,6 +63,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("abstractFunctionWithBodyWithComments.kt") + public void testAbstractFunctionWithBodyWithComments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt"); + doTest(fileName); + } + + @TestMetadata("abstractFunctionWithBodyWithComments2.kt") + public void testAbstractFunctionWithBodyWithComments2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt"); + doTest(fileName); + } + @TestMetadata("abstractPropertyInNonAbstractClass1.kt") public void testAbstractPropertyInNonAbstractClass1() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/abstract/abstractPropertyInNonAbstractClass1.kt");