From 09d27ca61c1f56392b318f41fd8620d8e410726d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 14 Dec 2017 17:37:05 +0100 Subject: [PATCH] Don't generate `.forEach { return }` when converting loop to call chain #KT-17161 Fixed --- .../loopToCallChain/result/ForEachTransformation.kt | 6 ++---- .../firstOrNull/returnNotNullIfNone2.kt | 4 ++-- .../firstOrNull/returnNotNullIfNone2.kt.after | 9 --------- .../firstOrNull/returnNotNullIfNone2.kt.after2 | 10 ---------- .../intentions/loopToCallChain/forEach/KT21083.kt | 10 ++++++++++ .../idea/intentions/IntentionTest2Generated.java | 6 ++++++ .../kotlin/idea/intentions/IntentionTestGenerated.java | 6 ++++++ 7 files changed, 26 insertions(+), 25 deletions(-) delete mode 100644 idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after delete mode 100644 idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after2 create mode 100644 idea/testData/intentions/loopToCallChain/forEach/KT21083.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/ForEachTransformation.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/ForEachTransformation.kt index 29ed640d0ab..62d49a16e71 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/ForEachTransformation.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/ForEachTransformation.kt @@ -20,10 +20,7 @@ import org.jetbrains.kotlin.idea.intentions.loopToCallChain.* import org.jetbrains.kotlin.idea.references.ReferenceAccess import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.readWriteAccess -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtForExpression -import org.jetbrains.kotlin.psi.KtNameReferenceExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector @@ -62,6 +59,7 @@ class ForEachTransformation( if (state.previousTransformations.isEmpty()) return null // do not suggest conversion to just ".forEach{}" or ".forEachIndexed{}" val statement = state.statements.singleOrNull() ?: return null + if (statement is KtReturnExpression) return null if (!state.lazySequence) { // check if it changes any variable that has other usages in the loop - then only lazy sequence is correct diff --git a/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt b/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt index 87036eecfc8..3df09cfa6d7 100644 --- a/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt +++ b/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt @@ -1,6 +1,6 @@ // WITH_RUNTIME -// INTENTION_TEXT: "Replace with 'filter{}.forEach{}'" -// INTENTION_TEXT_2: "Replace with 'asSequence().filter{}.forEach{}'" +// IS_APPLICABLE: false +// IS_APPLICABLE_2: false fun foo(list: List): String? { for (s in list) { if (s == null || s.isNotEmpty()) { diff --git a/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after b/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after deleted file mode 100644 index d1728e669af..00000000000 --- a/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after +++ /dev/null @@ -1,9 +0,0 @@ -// WITH_RUNTIME -// INTENTION_TEXT: "Replace with 'filter{}.forEach{}'" -// INTENTION_TEXT_2: "Replace with 'asSequence().filter{}.forEach{}'" -fun foo(list: List): String? { - list - .filter { it == null || it.isNotEmpty() } - .forEach { return it } - return "" -} \ No newline at end of file diff --git a/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after2 b/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after2 deleted file mode 100644 index ee9a8ecf074..00000000000 --- a/idea/testData/intentions/loopToCallChain/firstOrNull/returnNotNullIfNone2.kt.after2 +++ /dev/null @@ -1,10 +0,0 @@ -// WITH_RUNTIME -// INTENTION_TEXT: "Replace with 'filter{}.forEach{}'" -// INTENTION_TEXT_2: "Replace with 'asSequence().filter{}.forEach{}'" -fun foo(list: List): String? { - list - .asSequence() - .filter { it == null || it.isNotEmpty() } - .forEach { return it } - return "" -} \ No newline at end of file diff --git a/idea/testData/intentions/loopToCallChain/forEach/KT21083.kt b/idea/testData/intentions/loopToCallChain/forEach/KT21083.kt new file mode 100644 index 00000000000..a0cece6c34a --- /dev/null +++ b/idea/testData/intentions/loopToCallChain/forEach/KT21083.kt @@ -0,0 +1,10 @@ +// WITH_RUNTIME +// IS_APPLICABLE: false +// IS_APPLICABLE_2: false +fun foo(l: List<() -> Boolean>) { + for (i in 0 until l.size) { + if (l[i]()) { + return + } + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTest2Generated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTest2Generated.java index bff7605a118..fc5ef837eb3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTest2Generated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTest2Generated.java @@ -860,6 +860,12 @@ public class IntentionTest2Generated extends AbstractIntentionTest2 { doTest(fileName); } + @TestMetadata("KT21083.kt") + public void testKT21083() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/loopToCallChain/forEach/KT21083.kt"); + doTest(fileName); + } + @TestMetadata("notAvailable.kt") public void testNotAvailable() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/loopToCallChain/forEach/notAvailable.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 0d80147e0ac..6fd624057c1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -10771,6 +10771,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("KT21083.kt") + public void testKT21083() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/loopToCallChain/forEach/KT21083.kt"); + doTest(fileName); + } + @TestMetadata("notAvailable.kt") public void testNotAvailable() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/loopToCallChain/forEach/notAvailable.kt");