Supported forEach

This commit is contained in:
Valentin Kipyatkov
2016-05-11 22:43:00 +03:00
parent 394cce8e10
commit f28dca1fd5
10 changed files with 104 additions and 5 deletions
@@ -101,7 +101,8 @@ data class MatchingState(
* Matchers can assume that indexVariable is null if it's not used in the rest of the loop
*/
val indexVariable: KtCallableDeclaration?,
val initializationStatementsToDelete: Collection<KtExpression> = emptyList()
val initializationStatementsToDelete: Collection<KtExpression> = emptyList(),
val previousTransformations: List<SequenceTransformation>
)
interface TransformationMatcher {
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.result.AddToCollectionTransformation
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.result.CountTransformation
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.result.FindTransformationMatcher
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.result.ForEachTransformation
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.IntroduceIndexMatcher
@@ -52,7 +53,8 @@ object MatcherRegistrar {
IntroduceIndexMatcher,
FilterTransformation.Matcher,
MapTransformation.Matcher,
FlatMapTransformation.Matcher
FlatMapTransformation.Matcher,
ForEachTransformation.Matcher
)
}
@@ -74,7 +76,8 @@ fun match(loop: KtForExpression): MatchResult? {
innerLoop = loop,
statements = listOf(loop.body ?: return null),
inputVariable = inputVariable,
indexVariable = indexVariable
indexVariable = indexVariable,
previousTransformations = sequenceTransformations
)
MatchLoop@
@@ -0,0 +1,57 @@
/*
* 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.intentions.loopToCallChain.result
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.*
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
class ForEachTransformation(
loop: KtForExpression,
private val inputVariable: KtCallableDeclaration,
private val statement: KtExpression
) : ReplaceLoopResultTransformation(loop) {
override val presentation: String
get() = "forEach{}"
override fun generateCode(chainedCallGenerator: ChainedCallGenerator): KtExpression {
val lambda = generateLambda(inputVariable, statement)
return chainedCallGenerator.generate("forEach $0:'{}'", lambda)
}
/**
* Matches:
* for (...) {
* ...
* <statement>
* }
*/
object Matcher : TransformationMatcher {
override val indexVariableAllowed: Boolean
get() = false //TODO: support forEachIndexed
override fun match(state: MatchingState): TransformationMatch.Result? {
if (state.previousTransformations.isEmpty()) return null // do not suggest conversion to just ".forEach{}"
val statement = state.statements.singleOrNull() ?: return null
val transformation = ForEachTransformation(state.outerLoop, state.inputVariable, statement)
return TransformationMatch.Result(transformation)
}
}
}
@@ -1,5 +1,4 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
fun foo(list: List<String?>): String? {
<caret>for (s in list) {
if (s == null || s.isNotEmpty()) {
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo(list: List<String?>): String? {
list
.filter { it == null || it.isNotEmpty() }
.forEach { return it }
return ""
}
+9
View File
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// INTENTION_TEXT: "Replace with 'filter{}.forEach{}'"
fun foo(list: List<String>) {
<caret>for (s in list) {
if (s.isNotBlank()) {
println(s)
}
}
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
// INTENTION_TEXT: "Replace with 'filter{}.forEach{}'"
fun foo(list: List<String>) {
list
.filter { it.isNotBlank() }
.forEach { println(it) }
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
fun foo(list: List<String>) {
<caret>for (s in list) {
println(s)
}
}
@@ -1,5 +1,4 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
import java.util.ArrayList
fun foo(list: List<String>): List<Int> {
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import java.util.ArrayList
fun foo(list: List<String>): List<Int> {
val result = ArrayList<Int>()
list
.filter { it.length > result.size }
.forEach { result.add(it.hashCode()) }
return result
}