Merging subsequent filtering checks even when index variable is used
This commit is contained in:
@@ -80,10 +80,7 @@ fun match(loop: KtForExpression): MatchResult? {
|
|||||||
|
|
||||||
MatchLoop@
|
MatchLoop@
|
||||||
while (true) {
|
while (true) {
|
||||||
val block = state.statements.singleOrNull() as? KtBlockExpression
|
state = state.unwrapBlock()
|
||||||
if (block != null) {
|
|
||||||
state = state.copy(statements = block.statements)
|
|
||||||
}
|
|
||||||
|
|
||||||
val inputVariableUsed = state.inputVariable.hasUsages(state.statements)
|
val inputVariableUsed = state.inputVariable.hasUsages(state.statements)
|
||||||
|
|
||||||
|
|||||||
+24
-49
@@ -22,7 +22,11 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.*
|
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.*
|
||||||
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.*
|
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.FilterNotNullTransformation
|
||||||
|
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.MapTransformation
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.negate
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -37,11 +41,7 @@ class AddToCollectionTransformation(
|
|||||||
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
||||||
return when (previousTransformation) {
|
return when (previousTransformation) {
|
||||||
is FilterTransformation -> {
|
is FilterTransformation -> {
|
||||||
FilterToTransformation.create(loop, previousTransformation.inputVariable, targetCollection, previousTransformation.condition, previousTransformation.isInverse)
|
FilterToTransformation.create(loop, previousTransformation.inputVariable, previousTransformation.indexVariable, targetCollection, previousTransformation.condition, previousTransformation.isInverse)
|
||||||
}
|
|
||||||
|
|
||||||
is FilterIndexedTransformation -> {
|
|
||||||
FilterIndexedToTransformation.create(loop, previousTransformation.inputVariable, previousTransformation.indexVariable, targetCollection, previousTransformation.condition)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is FilterNotNullTransformation -> {
|
is FilterNotNullTransformation -> {
|
||||||
@@ -189,18 +189,28 @@ class AddToCollectionTransformation(
|
|||||||
class FilterToTransformation private constructor(
|
class FilterToTransformation private constructor(
|
||||||
loop: KtForExpression,
|
loop: KtForExpression,
|
||||||
private val inputVariable: KtCallableDeclaration,
|
private val inputVariable: KtCallableDeclaration,
|
||||||
|
private val indexVariable: KtCallableDeclaration?,
|
||||||
private val targetCollection: KtExpression,
|
private val targetCollection: KtExpression,
|
||||||
private val filter: KtExpression,
|
private val condition: KtExpression,
|
||||||
isInverse: Boolean
|
private val isInverse: Boolean
|
||||||
) : ReplaceLoopResultTransformation(loop) {
|
) : ReplaceLoopResultTransformation(loop) {
|
||||||
|
|
||||||
private val functionName = if (isInverse) "filterNotTo" else "filterTo"
|
private fun effectiveCondition() = if (isInverse) condition.negate() else condition
|
||||||
|
|
||||||
|
private val functionName = when {
|
||||||
|
indexVariable != null -> "filterIndexedTo"
|
||||||
|
isInverse -> "filterNotTo"
|
||||||
|
else -> "filterTo"
|
||||||
|
}
|
||||||
|
|
||||||
override val presentation: String
|
override val presentation: String
|
||||||
get() = "$functionName(){}"
|
get() = "$functionName(){}"
|
||||||
|
|
||||||
override fun generateCode(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
override fun generateCode(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
||||||
val lambda = generateLambda(inputVariable, filter)
|
val lambda = if (indexVariable != null)
|
||||||
|
generateLambda(effectiveCondition(), indexVariable, inputVariable)
|
||||||
|
else
|
||||||
|
generateLambda(inputVariable, condition)
|
||||||
return chainedCallGenerator.generate("$functionName($0) $1:'{}'", targetCollection, lambda)
|
return chainedCallGenerator.generate("$functionName($0) $1:'{}'", targetCollection, lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,53 +218,18 @@ class FilterToTransformation private constructor(
|
|||||||
fun create(
|
fun create(
|
||||||
loop: KtForExpression,
|
loop: KtForExpression,
|
||||||
inputVariable: KtCallableDeclaration,
|
inputVariable: KtCallableDeclaration,
|
||||||
|
indexVariable: KtCallableDeclaration?,
|
||||||
targetCollection: KtExpression,
|
targetCollection: KtExpression,
|
||||||
filter: KtExpression,
|
condition: KtExpression,
|
||||||
isInverse: Boolean
|
isInverse: Boolean
|
||||||
): ResultTransformation {
|
): ResultTransformation {
|
||||||
val initialization = targetCollection.detectInitializationBeforeLoop(loop, checkNoOtherUsagesInLoop = true)
|
val initialization = targetCollection.detectInitializationBeforeLoop(loop, checkNoOtherUsagesInLoop = true)
|
||||||
if (initialization != null && initialization.initializer.hasNoSideEffect()) {
|
if (initialization != null && initialization.initializer.hasNoSideEffect()) {
|
||||||
val transformation = FilterToTransformation(loop, inputVariable, initialization.initializer, filter, isInverse)
|
val transformation = FilterToTransformation(loop, inputVariable, indexVariable, initialization.initializer, condition, isInverse)
|
||||||
return AssignToVariableResultTransformation.createDelegated(transformation, initialization)
|
return AssignToVariableResultTransformation.createDelegated(transformation, initialization)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return FilterToTransformation(loop, inputVariable, targetCollection, filter, isInverse)
|
return FilterToTransformation(loop, inputVariable, indexVariable, targetCollection, condition, isInverse)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -32,6 +32,7 @@ class CountTransformation(
|
|||||||
|
|
||||||
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
||||||
if (previousTransformation !is FilterTransformation) return null
|
if (previousTransformation !is FilterTransformation) return null
|
||||||
|
if (previousTransformation.indexVariable != null) return null
|
||||||
assert(filter == null) { "Should not happen because no 2 consecutive FilterTransformation's possible"}
|
assert(filter == null) { "Should not happen because no 2 consecutive FilterTransformation's possible"}
|
||||||
return CountTransformation(loop, previousTransformation.inputVariable, initialization, previousTransformation.effectiveCondition())
|
return CountTransformation(loop, previousTransformation.inputVariable, initialization, previousTransformation.effectiveCondition())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -33,6 +33,7 @@ class FindAndAssignTransformation(
|
|||||||
|
|
||||||
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
||||||
if (previousTransformation !is FilterTransformation) return null
|
if (previousTransformation !is FilterTransformation) return null
|
||||||
|
if (previousTransformation.indexVariable != null) return null
|
||||||
assert(filter == null) { "Should not happen because no 2 consecutive FilterTransformation's possible"}
|
assert(filter == null) { "Should not happen because no 2 consecutive FilterTransformation's possible"}
|
||||||
return FindAndAssignTransformation(loop, generator, initialization, previousTransformation.effectiveCondition())
|
return FindAndAssignTransformation(loop, generator, initialization, previousTransformation.effectiveCondition())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -32,6 +32,7 @@ class FindAndReturnTransformation(
|
|||||||
|
|
||||||
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): ResultTransformation? {
|
||||||
if (previousTransformation !is FilterTransformation) return null
|
if (previousTransformation !is FilterTransformation) return null
|
||||||
|
if (previousTransformation.indexVariable != null) return null
|
||||||
assert(filter == null) { "Should not happen because no 2 consecutive FilterTransformation's possible"}
|
assert(filter == null) { "Should not happen because no 2 consecutive FilterTransformation's possible"}
|
||||||
return FindAndReturnTransformation(loop, generator, endReturn, previousTransformation.effectiveCondition())
|
return FindAndReturnTransformation(loop, generator, endReturn, previousTransformation.effectiveCondition())
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-42
@@ -26,22 +26,19 @@ import org.jetbrains.kotlin.psi.psiUtil.blockExpressionsOrSingle
|
|||||||
class FilterTransformation(
|
class FilterTransformation(
|
||||||
override val loop: KtForExpression,
|
override val loop: KtForExpression,
|
||||||
val inputVariable: KtCallableDeclaration,
|
val inputVariable: KtCallableDeclaration,
|
||||||
|
val indexVariable: KtCallableDeclaration?,
|
||||||
val condition: KtExpression,
|
val condition: KtExpression,
|
||||||
val isInverse: Boolean
|
val isInverse: Boolean
|
||||||
) : SequenceTransformation {
|
) : SequenceTransformation {
|
||||||
|
|
||||||
fun effectiveCondition() = if (isInverse) condition.negate() else condition
|
fun effectiveCondition() = if (isInverse) condition.negate() else condition
|
||||||
|
|
||||||
override fun mergeWithPrevious(previousTransformation: SequenceTransformation): SequenceTransformation? {
|
private val functionName = when {
|
||||||
if (previousTransformation !is FilterTransformation) return null
|
indexVariable != null -> "filterIndexed"
|
||||||
assert(previousTransformation.inputVariable == inputVariable)
|
isInverse -> "filterNot"
|
||||||
val mergedCondition = KtPsiFactory(condition).createExpressionByPattern(
|
else -> "filter"
|
||||||
"$0 && $1", previousTransformation.effectiveCondition(), effectiveCondition())
|
|
||||||
return FilterTransformation(loop, inputVariable, mergedCondition, isInverse = false) //TODO: build filterNot in some cases?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val functionName = if (isInverse) "filterNot" else "filter"
|
|
||||||
|
|
||||||
override val affectsIndex: Boolean
|
override val affectsIndex: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
|
|
||||||
@@ -49,7 +46,10 @@ class FilterTransformation(
|
|||||||
get() = "$functionName{}"
|
get() = "$functionName{}"
|
||||||
|
|
||||||
override fun generateCode(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
override fun generateCode(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
||||||
val lambda = generateLambda(inputVariable, condition)
|
val lambda = if (indexVariable != null)
|
||||||
|
generateLambda(effectiveCondition(), indexVariable, inputVariable)
|
||||||
|
else
|
||||||
|
generateLambda(inputVariable, condition)
|
||||||
return chainedCallGenerator.generate("$0$1:'{}'", functionName, lambda)
|
return chainedCallGenerator.generate("$0$1:'{}'", functionName, lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,22 +76,29 @@ class FilterTransformation(
|
|||||||
*/
|
*/
|
||||||
object Matcher : SequenceTransformationMatcher {
|
object Matcher : SequenceTransformationMatcher {
|
||||||
override fun match(state: MatchingState): SequenceTransformationMatch? {
|
override fun match(state: MatchingState): SequenceTransformationMatch? {
|
||||||
var (transformation, currentState) = matchOneTransformation(state, takeWhileAllowed = true) ?: return null
|
// we merge filter transformations here instead of FilterTransformation.mergeWithPrevious() because of filterIndexed that won't merge otherwise
|
||||||
|
|
||||||
/*
|
var (transformation, currentState) = matchOneTransformation(state) ?: return null
|
||||||
if (transformation is FilterTransformation || transformation is FilterIndexedTransformation) {
|
|
||||||
|
if (transformation is FilterTransformation) {
|
||||||
while (true) {
|
while (true) {
|
||||||
val (nextTransformation, nextState) = matchOneTransformation(currentState, takeWhileAllowed = false) ?: break
|
currentState = currentState.unwrapBlock()
|
||||||
if (nextTransformation !is FilterTransformation && nextTransformation !is FilterIndexedTransformation) break
|
|
||||||
|
|
||||||
|
val (nextTransformation, nextState) = matchOneTransformation(currentState) ?: break
|
||||||
|
if (nextTransformation !is FilterTransformation) break
|
||||||
|
|
||||||
|
val indexVariable = transformation.indexVariable ?: nextTransformation.indexVariable
|
||||||
|
val mergedCondition = KtPsiFactory(state.outerLoop).createExpressionByPattern(
|
||||||
|
"$0 && $1", transformation.effectiveCondition(), nextTransformation.effectiveCondition())
|
||||||
|
transformation = FilterTransformation(state.outerLoop, transformation.inputVariable, indexVariable, mergedCondition, isInverse = false) //TODO: build filterNot in some cases?
|
||||||
|
currentState = nextState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
return SequenceTransformationMatch(transformation, currentState)
|
return SequenceTransformationMatch(transformation, currentState)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun matchOneTransformation(state: MatchingState, takeWhileAllowed: Boolean): Pair<SequenceTransformation, MatchingState>? {
|
private fun matchOneTransformation(state: MatchingState): Pair<SequenceTransformation, MatchingState>? {
|
||||||
val ifStatement = state.statements.firstOrNull() as? KtIfExpression ?: return null
|
val ifStatement = state.statements.firstOrNull() as? KtIfExpression ?: return null
|
||||||
if (ifStatement.`else` != null) return null
|
if (ifStatement.`else` != null) return null
|
||||||
val condition = ifStatement.condition ?: return null
|
val condition = ifStatement.condition ?: return null
|
||||||
@@ -113,7 +120,6 @@ class FilterTransformation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is KtBreakExpression -> {
|
is KtBreakExpression -> {
|
||||||
if (!takeWhileAllowed) return null
|
|
||||||
if (statement.targetLoop() != state.outerLoop) return null
|
if (statement.targetLoop() != state.outerLoop) return null
|
||||||
val transformation = TakeWhileTransformation(state.outerLoop, state.inputVariable, condition.negate())
|
val transformation = TakeWhileTransformation(state.outerLoop, state.inputVariable, condition.negate())
|
||||||
val newState = state.copy(statements = state.statements.drop(1))
|
val newState = state.copy(statements = state.statements.drop(1))
|
||||||
@@ -125,8 +131,6 @@ class FilterTransformation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun mergeFilterTransformations(transformation1: )
|
|
||||||
|
|
||||||
//TODO: choose filter or filterNot depending on condition
|
//TODO: choose filter or filterNot depending on condition
|
||||||
private fun createFilterTransformation(
|
private fun createFilterTransformation(
|
||||||
loop: KtForExpression,
|
loop: KtForExpression,
|
||||||
@@ -139,7 +143,7 @@ class FilterTransformation(
|
|||||||
val effectiveCondition = if (isInverse) condition.negate() else condition
|
val effectiveCondition = if (isInverse) condition.negate() else condition
|
||||||
|
|
||||||
if (indexVariable != null && indexVariable.hasUsages(condition)) {
|
if (indexVariable != null && indexVariable.hasUsages(condition)) {
|
||||||
return FilterIndexedTransformation(loop, inputVariable, indexVariable, effectiveCondition)
|
return FilterTransformation(loop, inputVariable, indexVariable, effectiveCondition, isInverse = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effectiveCondition is KtIsExpression
|
if (effectiveCondition is KtIsExpression
|
||||||
@@ -160,7 +164,7 @@ class FilterTransformation(
|
|||||||
return FilterNotNullTransformation(loop)
|
return FilterNotNullTransformation(loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
return FilterTransformation(loop, inputVariable, condition, isInverse)
|
return FilterTransformation(loop, inputVariable, null, condition, isInverse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,27 +204,6 @@ class FilterNotNullTransformation(override val loop: KtForExpression) : Sequence
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FilterIndexedTransformation(
|
|
||||||
override val loop: KtForExpression,
|
|
||||||
val inputVariable: KtCallableDeclaration,
|
|
||||||
val indexVariable: KtCallableDeclaration,
|
|
||||||
val condition: KtExpression
|
|
||||||
) : SequenceTransformation {
|
|
||||||
|
|
||||||
//TODO: how to handle multiple if's using index?
|
|
||||||
|
|
||||||
override val affectsIndex: Boolean
|
|
||||||
get() = true
|
|
||||||
|
|
||||||
override val presentation: String
|
|
||||||
get() = "filterIndexed{}"
|
|
||||||
|
|
||||||
override fun generateCode(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
|
||||||
val lambda = generateLambda(condition, indexVariable, inputVariable)
|
|
||||||
return chainedCallGenerator.generate("filterIndexed $0:'{}'", lambda)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TakeWhileTransformation(
|
class TakeWhileTransformation(
|
||||||
override val loop: KtForExpression,
|
override val loop: KtForExpression,
|
||||||
val inputVariable: KtCallableDeclaration,
|
val inputVariable: KtCallableDeclaration,
|
||||||
|
|||||||
@@ -306,4 +306,9 @@ private fun isEmbeddedBreakOrContinue(expression: KtExpressionWithLabel): Boolea
|
|||||||
|
|
||||||
else -> return true
|
else -> return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun MatchingState.unwrapBlock(): MatchingState {
|
||||||
|
val block = statements.singleOrNull() as? KtBlockExpression ?: return this
|
||||||
|
return this.copy(statements = block.statements)
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// INTENTION_TEXT: "Replace with 'filterIndexed{}.firstOrNull()'"
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>for ((index, s) in list.withIndex()) {
|
||||||
|
if (s.length > index * 10) continue
|
||||||
|
if (s.length > index) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// INTENTION_TEXT: "Replace with 'filterIndexed{}.firstOrNull()'"
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>return list
|
||||||
|
.filterIndexed { index, s -> s.length <= index * 10 && s.length > index }
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// INTENTION_TEXT: "Replace with 'filterIndexed{}.firstOrNull()'"
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>for ((index, s) in list.withIndex()) {
|
||||||
|
if (s.isBlank()) continue
|
||||||
|
if (s.length > index) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// INTENTION_TEXT: "Replace with 'filterIndexed{}.firstOrNull()'"
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>return list
|
||||||
|
.filterIndexed { index, s -> !s.isBlank() && s.length > index }
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// INTENTION_TEXT: "Replace with 'filterIndexed{}.firstOrNull()'"
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>for ((index, s) in list.withIndex()) {
|
||||||
|
if (s.length > index) continue
|
||||||
|
if (s.isNotBlank()) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// INTENTION_TEXT: "Replace with 'filterIndexed{}.firstOrNull()'"
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>return list
|
||||||
|
.filterIndexed { index, s -> s.length <= index && s.isNotBlank() }
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user