diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/AddToCollectionTransformation.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/AddToCollectionTransformation.kt index 60852a127f8..f39b7371090 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/AddToCollectionTransformation.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/result/AddToCollectionTransformation.kt @@ -22,10 +22,7 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.intentions.loopToCallChain.* -import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.FilterTransformation -import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.FlatMapTransformation -import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.MapIndexedTransformation -import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.MapTransformation +import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.* import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* @@ -43,6 +40,10 @@ class AddToCollectionTransformation( FilterToTransformation.create(loop, previousTransformation.inputVariable, targetCollection, previousTransformation.effectiveCondition()) //TODO: use filterNotTo? } + is FilterIndexedTransformation -> { + FilterIndexedToTransformation.create(loop, previousTransformation.inputVariable, previousTransformation.indexVariable, targetCollection, previousTransformation.condition) + } + is MapTransformation -> { MapToTransformation.create(loop, previousTransformation.inputVariable, targetCollection, previousTransformation.mapping) } @@ -216,6 +217,42 @@ class FilterToTransformation private constructor( } } +class FilterIndexedToTransformation private constructor( + loop: KtForExpression, + private val inputVariable: KtCallableDeclaration, + private val indexVariable: KtCallableDeclaration, + private val targetCollection: KtExpression, + private val filter: KtExpression +) : ReplaceLoopResultTransformation(loop) { + + override val presentation: String + get() = "filterIndexedTo(){}" + + override fun generateCode(chainedCallGenerator: ChainedCallGenerator): KtExpression { + val lambda = generateLambda(filter, indexVariable, inputVariable) + return chainedCallGenerator.generate("filterIndexedTo($0) $1:'{}'", targetCollection, lambda) + } + + companion object { + fun create( + loop: KtForExpression, + inputVariable: KtCallableDeclaration, + indexVariable: KtCallableDeclaration, + targetCollection: KtExpression, + filter: KtExpression + ): ResultTransformation { + val initialization = targetCollection.detectInitializationBeforeLoop(loop, checkNoOtherUsagesInLoop = true) + if (initialization != null && initialization.initializer.hasNoSideEffect()) { + val transformation = FilterIndexedToTransformation(loop, inputVariable, indexVariable, initialization.initializer, filter) + return AssignToVariableResultTransformation.createDelegated(transformation, initialization) + } + else { + return FilterIndexedToTransformation(loop, inputVariable, indexVariable, targetCollection, filter) + } + } + } +} + class MapToTransformation private constructor( loop: KtForExpression, private val inputVariable: KtCallableDeclaration, diff --git a/idea/testData/intentions/loopToCallChain/filterIndexedTo.kt b/idea/testData/intentions/loopToCallChain/filterIndexedTo.kt new file mode 100644 index 00000000000..535454390df --- /dev/null +++ b/idea/testData/intentions/loopToCallChain/filterIndexedTo.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME +// INTENTION_TEXT: "Replace with 'filterIndexedTo(){}'" +fun foo(list: List, target: MutableList) { + for ((index, s) in list.withIndex()) { + if (s.length > index) + target.add(s) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/loopToCallChain/filterIndexedTo.kt.after b/idea/testData/intentions/loopToCallChain/filterIndexedTo.kt.after new file mode 100644 index 00000000000..c7067763d94 --- /dev/null +++ b/idea/testData/intentions/loopToCallChain/filterIndexedTo.kt.after @@ -0,0 +1,5 @@ +// WITH_RUNTIME +// INTENTION_TEXT: "Replace with 'filterIndexedTo(){}'" +fun foo(list: List, target: MutableList) { + list.filterIndexedTo(target) { index, s -> s.length > index } +} \ No newline at end of file diff --git a/idea/testData/intentions/loopToCallChain/filterIndexedTo2.kt b/idea/testData/intentions/loopToCallChain/filterIndexedTo2.kt new file mode 100644 index 00000000000..53d564f76d5 --- /dev/null +++ b/idea/testData/intentions/loopToCallChain/filterIndexedTo2.kt @@ -0,0 +1,12 @@ +// WITH_RUNTIME +// INTENTION_TEXT: "Replace with 'filterIndexedTo(){}'" +import java.util.ArrayList + +fun foo(list: List): List { + val result = ArrayList(1000) + for ((index, s) in list.withIndex()) { + if (s.length > index) + result.add(s) + } + return result +} \ No newline at end of file diff --git a/idea/testData/intentions/loopToCallChain/filterIndexedTo2.kt.after b/idea/testData/intentions/loopToCallChain/filterIndexedTo2.kt.after new file mode 100644 index 00000000000..bc1b0316ea0 --- /dev/null +++ b/idea/testData/intentions/loopToCallChain/filterIndexedTo2.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME +// INTENTION_TEXT: "Replace with 'filterIndexedTo(){}'" +import java.util.ArrayList + +fun foo(list: List): List { + val result = list.filterIndexedTo(ArrayList(1000)) { index, s -> s.length > index } + return result +} \ No newline at end of file diff --git a/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt b/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt index e9ed644b42e..a80445b5519 100644 --- a/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt +++ b/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt @@ -1,5 +1,5 @@ // WITH_RUNTIME -// INTENTION_TEXT: "Replace with '+= filterIndexed{}.filterIndexed{}'" +// INTENTION_TEXT: "Replace with 'filterIndexed{}.filterIndexedTo(){}'" fun foo(list: List, target: MutableCollection) { var j = 0 for ((i, s) in list.withIndex()) { diff --git a/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt.after b/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt.after index 68043b67178..ed251f71beb 100644 --- a/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt.after +++ b/idea/testData/intentions/loopToCallChain/filterIndexed_twoIndices.kt.after @@ -1,7 +1,7 @@ // WITH_RUNTIME -// INTENTION_TEXT: "Replace with '+= filterIndexed{}.filterIndexed{}'" +// INTENTION_TEXT: "Replace with 'filterIndexed{}.filterIndexedTo(){}'" fun foo(list: List, target: MutableCollection) { - target += list + list .filterIndexed { i, s -> s.length <= i } - .filterIndexed { j, s -> s.length % j == 0 } + .filterIndexedTo(target) { j, s -> s.length % j == 0 } } \ No newline at end of file