From 09266b222b1deaa2cc3489c8fd0f474262d9b8a8 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 24 May 2016 16:34:17 +0300 Subject: [PATCH] Implement 'Surround expression with if' surrounder #KT-3363 Fixed --- .../kotlin/generators/tests/GenerateTests.kt | 2 + .../KotlinExpressionSurroundDescriptor.java | 4 +- .../KotlinWithIfExpressionSurrounder.kt | 60 +++++++++++++++++++ .../withIfElseExpression/complexBoolean.kt | 3 + .../complexBoolean.kt.after | 6 ++ .../withIfElseExpression/variable.kt | 3 + .../withIfElseExpression/variable.kt.after | 6 ++ .../withIfExpression/complexBoolean.kt | 3 + .../withIfExpression/complexBoolean.kt.after | 5 ++ .../surroundWith/withIfExpression/variable.kt | 3 + .../withIfExpression/variable.kt.after | 5 ++ .../AbstractSurroundWithTest.java | 13 ++-- .../SurroundWithTestGenerated.java | 42 +++++++++++++ 13 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinWithIfExpressionSurrounder.kt create mode 100644 idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt create mode 100644 idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt.after create mode 100644 idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt create mode 100644 idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt.after create mode 100644 idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt create mode 100644 idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt.after create mode 100644 idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt create mode 100644 idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt.after diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 5366120cffb..da5b346f885 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -509,6 +509,8 @@ fun main(args: Array) { model("codeInsight/surroundWith/tryCatchFinally", testMethod = "doTestWithTryCatchFinallySurrounder") model("codeInsight/surroundWith/tryFinally", testMethod = "doTestWithTryFinallySurrounder") model("codeInsight/surroundWith/functionLiteral", testMethod = "doTestWithFunctionLiteralSurrounder") + model("codeInsight/surroundWith/withIfExpression", testMethod = "doTestWithSurroundWithIfExpression") + model("codeInsight/surroundWith/withIfElseExpression", testMethod = "doTestWithSurroundWithIfElseExpression") } testClass() { diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java index 8528796a38d..ffcd3c82186 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java @@ -31,7 +31,9 @@ public class KotlinExpressionSurroundDescriptor implements SurroundDescriptor { new KotlinStringTemplateSurrounder(), new KotlinParenthesesSurrounder(), new KotlinWhenSurrounder() , - new KotlinRuntimeTypeCastSurrounder() + new KotlinRuntimeTypeCastSurrounder(), + new KotlinWithIfExpressionSurrounder(/* withElse = */false), + new KotlinWithIfExpressionSurrounder(/* withElse = */true) }; @Override diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinWithIfExpressionSurrounder.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinWithIfExpressionSurrounder.kt new file mode 100644 index 00000000000..99d62e26e96 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinWithIfExpressionSurrounder.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2016 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.codeInsight.surroundWith.expression + +import com.intellij.codeInsight.CodeInsightUtilBase +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.TextRange +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.conversion.copy.range +import org.jetbrains.kotlin.psi.KtBlockExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtIfExpression +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.types.typeUtil.isBoolean +import org.jetbrains.kotlin.utils.sure + +class KotlinWithIfExpressionSurrounder(val withElse: Boolean) : KotlinExpressionSurrounder() { + override fun isApplicable(expression: KtExpression) = + expression.analyze(BodyResolveMode.PARTIAL).getType(expression)?.isBoolean() ?: false + + override fun surroundExpression(project: Project, editor: Editor, expression: KtExpression): TextRange? { + val factory = KtPsiFactory(project) + val ifExpression = + expression.replace( + factory.createIf( + expression, + factory.createBlock("blockStubContentToBeRemovedLater"), + if (withElse) factory.createEmptyBody() else null + ) + ) as KtIfExpression + + CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(ifExpression) + + val firstStatementInThenRange = (ifExpression.then as? KtBlockExpression).sure { + "Then branch should exist and be a block expression" + }.statements.first().range + + editor.document.deleteString(firstStatementInThenRange.startOffset, firstStatementInThenRange.endOffset) + + return TextRange(firstStatementInThenRange.startOffset, firstStatementInThenRange.startOffset) + } + + override fun getTemplateDescription() = "if (expr) { ... }" + (if (withElse) " else { ... }" else "") +} diff --git a/idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt b/idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt new file mode 100644 index 00000000000..5fbcc2978a4 --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt @@ -0,0 +1,3 @@ +fun foo(x: Boolean, y: Boolean) { + x || y && x +} diff --git a/idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt.after b/idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt.after new file mode 100644 index 00000000000..11e60ecfa62 --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt.after @@ -0,0 +1,6 @@ +fun foo(x: Boolean, y: Boolean) { + if (x || y && x) { + + } else { + } +} diff --git a/idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt b/idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt new file mode 100644 index 00000000000..461f89a5b7d --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt @@ -0,0 +1,3 @@ +fun foo(x: Boolean) { + x +} diff --git a/idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt.after b/idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt.after new file mode 100644 index 00000000000..600c6313337 --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt.after @@ -0,0 +1,6 @@ +fun foo(x: Boolean) { + if (x) { + + } else { + } +} diff --git a/idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt b/idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt new file mode 100644 index 00000000000..5fbcc2978a4 --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt @@ -0,0 +1,3 @@ +fun foo(x: Boolean, y: Boolean) { + x || y && x +} diff --git a/idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt.after b/idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt.after new file mode 100644 index 00000000000..7058cc98baf --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt.after @@ -0,0 +1,5 @@ +fun foo(x: Boolean, y: Boolean) { + if (x || y && x) { + + } +} diff --git a/idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt b/idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt new file mode 100644 index 00000000000..461f89a5b7d --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt @@ -0,0 +1,3 @@ +fun foo(x: Boolean) { + x +} diff --git a/idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt.after b/idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt.after new file mode 100644 index 00000000000..3f90f798716 --- /dev/null +++ b/idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt.after @@ -0,0 +1,5 @@ +fun foo(x: Boolean) { + if (x) { + + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/AbstractSurroundWithTest.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/AbstractSurroundWithTest.java index 43e93ed1855..ac8f0e59c98 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/AbstractSurroundWithTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/AbstractSurroundWithTest.java @@ -26,10 +26,7 @@ import com.intellij.psi.PsiElement; import com.intellij.testFramework.LightCodeInsightTestCase; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.idea.codeInsight.surroundWith.expression.KotlinNotSurrounder; -import org.jetbrains.kotlin.idea.codeInsight.surroundWith.expression.KotlinParenthesesSurrounder; -import org.jetbrains.kotlin.idea.codeInsight.surroundWith.expression.KotlinStringTemplateSurrounder; -import org.jetbrains.kotlin.idea.codeInsight.surroundWith.expression.KotlinWhenSurrounder; +import org.jetbrains.kotlin.idea.codeInsight.surroundWith.expression.*; import org.jetbrains.kotlin.idea.codeInsight.surroundWith.statement.*; import org.jetbrains.kotlin.test.InTextDirectivesUtils; @@ -78,6 +75,14 @@ public abstract class AbstractSurroundWithTest extends LightCodeInsightTestCase doTest(path, new KotlinFunctionLiteralSurrounder()); } + public void doTestWithSurroundWithIfExpression(String path) throws Exception { + doTest(path, new KotlinWithIfExpressionSurrounder(false)); + } + + public void doTestWithSurroundWithIfElseExpression(String path) throws Exception { + doTest(path, new KotlinWithIfExpressionSurrounder(true)); + } + private void doTest(String path, Surrounder surrounder) throws Exception { configureByFile(path); diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/SurroundWithTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/SurroundWithTestGenerated.java index d85a7d6fa84..41898413f99 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/SurroundWithTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/surroundWith/SurroundWithTestGenerated.java @@ -613,4 +613,46 @@ public class SurroundWithTestGenerated extends AbstractSurroundWithTest { doTestWithFunctionLiteralSurrounder(fileName); } } + + @TestMetadata("idea/testData/codeInsight/surroundWith/withIfExpression") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class WithIfExpression extends AbstractSurroundWithTest { + public void testAllFilesPresentInWithIfExpression() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/surroundWith/withIfExpression"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("complexBoolean.kt") + public void testComplexBoolean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/surroundWith/withIfExpression/complexBoolean.kt"); + doTestWithSurroundWithIfExpression(fileName); + } + + @TestMetadata("variable.kt") + public void testVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/surroundWith/withIfExpression/variable.kt"); + doTestWithSurroundWithIfExpression(fileName); + } + } + + @TestMetadata("idea/testData/codeInsight/surroundWith/withIfElseExpression") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class WithIfElseExpression extends AbstractSurroundWithTest { + public void testAllFilesPresentInWithIfElseExpression() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/surroundWith/withIfElseExpression"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("complexBoolean.kt") + public void testComplexBoolean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/surroundWith/withIfElseExpression/complexBoolean.kt"); + doTestWithSurroundWithIfElseExpression(fileName); + } + + @TestMetadata("variable.kt") + public void testVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/surroundWith/withIfElseExpression/variable.kt"); + doTestWithSurroundWithIfElseExpression(fileName); + } + } }