From 14ef93a79766b11183ca68b967ac9d663912dd21 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 6 Apr 2016 12:42:20 +0300 Subject: [PATCH] More relaxed checks for any() with return --- .../result/FindAndAssignTransformation.kt | 6 ++++++ .../kotlin/idea/intentions/loopToCallChain/utils.kt | 5 +---- .../loopToCallChain/any_ifReturn_nonBooleanResult.kt | 11 +++++++++++ .../any_ifReturn_nonBooleanResult.kt.after | 6 ++++++ 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt create mode 100644 idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/FindAndAssignTransformation.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/FindAndAssignTransformation.kt index 25cbb5c7aeb..f9e79128c4c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/FindAndAssignTransformation.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/FindAndAssignTransformation.kt @@ -18,11 +18,14 @@ package org.jetbrains.kotlin.idea.intentions.loopToCallChain.result import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.ReferencesSearch +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.intentions.loopToCallChain.* import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.FilterTransformation import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange +import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class FindAndAssignTransformation( private val loop: KtForExpression, @@ -101,6 +104,9 @@ class FindAndAssignTransformation( val usageCountInLoop = ReferencesSearch.search(declarationBeforeLoop, LocalSearchScope(state.outerLoop)).count() if (usageCountInLoop != 1) return null // this should be the only usage of this variable inside the loop + // we do not try to convert anything if the initializer is not compile-time constant because of possible side-effects + if (ConstantExpressionEvaluator.getConstant(initializer, initializer.analyze(BodyResolveMode.PARTIAL)) == null) return null + val generator = buildFindOperationGenerator(right, initializer, state.workingVariable, findFirst) ?: return null val transformation = FindAndAssignTransformation(state.outerLoop, state.workingVariable, generator, declarationBeforeLoop) diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt index 6b72827fbb6..dd448aba77c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt @@ -158,16 +158,13 @@ fun buildFindOperationGenerator( } } - // initial value is compile-time constant - ConstantExpressionEvaluator.getConstant(valueIfNotFound, valueIfNotFound.analyze(BodyResolveMode.PARTIAL)) != null -> { + else -> { return { chainedCallGenerator, filter -> val chainedCall = generateChainedCall("any", chainedCallGenerator, filter) KtPsiFactory(chainedCall).createExpressionByPattern("if ($0) $1 else $2", chainedCall, valueIfFound, valueIfNotFound) } } - - else -> return null } return { chainedCallGenerator, filter -> generateChainedCall(stdlibFunName, chainedCallGenerator, filter) } diff --git a/idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt b/idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt new file mode 100644 index 00000000000..3183f3afce8 --- /dev/null +++ b/idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME +fun foo(list: List): Int { + for (s in list) { + if (s.length > 0) { + return -1 + } + } + return takeInt() +} + +fun takeInt(): Int = 0 \ No newline at end of file diff --git a/idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt.after b/idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt.after new file mode 100644 index 00000000000..d09c043b311 --- /dev/null +++ b/idea/testData/intentions/loopToCallChain/any_ifReturn_nonBooleanResult.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +fun foo(list: List): Int { + return if (list.any { it.length > 0 }) -1 else takeInt() +} + +fun takeInt(): Int = 0 \ No newline at end of file