Check for continue-statement of the inner loop!
This commit is contained in:
@@ -54,10 +54,11 @@ interface ResultTransformation : Transformation {
|
|||||||
data class FilterOrMap(val expression: KtExpression, val workingVariable: KtCallableDeclaration)
|
data class FilterOrMap(val expression: KtExpression, val workingVariable: KtCallableDeclaration)
|
||||||
|
|
||||||
data class MatchingState(
|
data class MatchingState(
|
||||||
|
val outerLoop: KtForExpression,
|
||||||
|
val innerLoop: KtForExpression,
|
||||||
val statements: Collection<KtExpression>,
|
val statements: Collection<KtExpression>,
|
||||||
val workingVariable: KtCallableDeclaration,
|
val workingVariable: KtCallableDeclaration,
|
||||||
val indexVariable: KtCallableDeclaration?,
|
val indexVariable: KtCallableDeclaration?
|
||||||
val loop: KtForExpression
|
|
||||||
)
|
)
|
||||||
|
|
||||||
interface SequenceTransformationMatcher {
|
interface SequenceTransformationMatcher {
|
||||||
|
|||||||
@@ -54,10 +54,11 @@ object MatcherRegistrar {
|
|||||||
fun match(loop: KtForExpression): ResultTransformationMatch? {
|
fun match(loop: KtForExpression): ResultTransformationMatch? {
|
||||||
val sequenceTransformations = ArrayList<SequenceTransformation>()
|
val sequenceTransformations = ArrayList<SequenceTransformation>()
|
||||||
var state = MatchingState(
|
var state = MatchingState(
|
||||||
|
outerLoop = loop,
|
||||||
|
innerLoop = loop,
|
||||||
statements = listOf(loop.body ?: return null),
|
statements = listOf(loop.body ?: return null),
|
||||||
workingVariable = loop.loopParameter ?: return null,
|
workingVariable = loop.loopParameter ?: return null,
|
||||||
indexVariable = null,
|
indexVariable = null
|
||||||
loop = loop
|
|
||||||
)
|
)
|
||||||
|
|
||||||
MatchLoop@
|
MatchLoop@
|
||||||
|
|||||||
+4
-4
@@ -68,7 +68,7 @@ class FindAndAssignTransformation(
|
|||||||
if (state.statements.size != 2) return null
|
if (state.statements.size != 2) return null
|
||||||
|
|
||||||
val breakExpression = state.statements.last() as? KtBreakExpression ?: return null
|
val breakExpression = state.statements.last() as? KtBreakExpression ?: return null
|
||||||
if (!breakExpression.isBreakOrContinueOfLoop(state.loop)) return null
|
if (!breakExpression.isBreakOrContinueOfLoop(state.outerLoop)) return null
|
||||||
|
|
||||||
val binaryExpression = state.statements.first() as? KtBinaryExpression ?: return null
|
val binaryExpression = state.statements.first() as? KtBinaryExpression ?: return null
|
||||||
if (binaryExpression.operationToken != KtTokens.EQ) return null
|
if (binaryExpression.operationToken != KtTokens.EQ) return null
|
||||||
@@ -76,16 +76,16 @@ class FindAndAssignTransformation(
|
|||||||
val right = binaryExpression.right ?: return null
|
val right = binaryExpression.right ?: return null
|
||||||
|
|
||||||
//TODO: support also assignment instead of declaration
|
//TODO: support also assignment instead of declaration
|
||||||
val declarationBeforeLoop = state.loop.previousStatement() as? KtProperty ?: return null
|
val declarationBeforeLoop = state.outerLoop.previousStatement() as? KtProperty ?: return null
|
||||||
val initializer = declarationBeforeLoop.initializer ?: return null
|
val initializer = declarationBeforeLoop.initializer ?: return null
|
||||||
if (!left.isVariableReference(declarationBeforeLoop)) return null
|
if (!left.isVariableReference(declarationBeforeLoop)) return null
|
||||||
|
|
||||||
val usageCountInLoop = ReferencesSearch.search(declarationBeforeLoop, LocalSearchScope(state.loop)).count()
|
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
|
if (usageCountInLoop != 1) return null // this should be the only usage of this variable inside the loop
|
||||||
|
|
||||||
val stdlibFunName = stdlibFunNameForFind(right, initializer, state.workingVariable) ?: return null
|
val stdlibFunName = stdlibFunNameForFind(right, initializer, state.workingVariable) ?: return null
|
||||||
|
|
||||||
val transformation = FindAndAssignTransformation(state.loop, state.workingVariable, stdlibFunName, declarationBeforeLoop)
|
val transformation = FindAndAssignTransformation(state.outerLoop, state.workingVariable, stdlibFunName, declarationBeforeLoop)
|
||||||
return ResultTransformationMatch(transformation)
|
return ResultTransformationMatch(transformation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -62,7 +62,7 @@ class FindAndReturnTransformation(
|
|||||||
if (state.indexVariable != null) return null
|
if (state.indexVariable != null) return null
|
||||||
|
|
||||||
val returnInLoop = state.statements.singleOrNull() as? KtReturnExpression ?: return null
|
val returnInLoop = state.statements.singleOrNull() as? KtReturnExpression ?: return null
|
||||||
val returnAfterLoop = state.loop.nextStatement() as? KtReturnExpression ?: return null
|
val returnAfterLoop = state.outerLoop.nextStatement() as? KtReturnExpression ?: return null
|
||||||
if (returnInLoop.getLabelName() != returnAfterLoop.getLabelName()) return null
|
if (returnInLoop.getLabelName() != returnAfterLoop.getLabelName()) return null
|
||||||
|
|
||||||
val returnValueInLoop = returnInLoop.returnedExpression ?: return null
|
val returnValueInLoop = returnInLoop.returnedExpression ?: return null
|
||||||
@@ -70,7 +70,7 @@ class FindAndReturnTransformation(
|
|||||||
|
|
||||||
val stdlibFunName = stdlibFunNameForFind(returnValueInLoop, returnValueAfterLoop, state.workingVariable) ?: return null
|
val stdlibFunName = stdlibFunNameForFind(returnValueInLoop, returnValueAfterLoop, state.workingVariable) ?: return null
|
||||||
|
|
||||||
val transformation = FindAndReturnTransformation(state.loop, state.workingVariable, stdlibFunName, returnAfterLoop)
|
val transformation = FindAndReturnTransformation(state.outerLoop, state.workingVariable, stdlibFunName, returnAfterLoop)
|
||||||
return ResultTransformationMatch(transformation)
|
return ResultTransformationMatch(transformation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ class FilterTransformation(
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val continueExpression = then.blockExpressionsOrSingle().singleOrNull() as? KtContinueExpression ?: return null
|
val continueExpression = then.blockExpressionsOrSingle().singleOrNull() as? KtContinueExpression ?: return null
|
||||||
if (!continueExpression.isBreakOrContinueOfLoop(state.loop)) return null
|
if (!continueExpression.isBreakOrContinueOfLoop(state.innerLoop)) return null
|
||||||
val transformation = createFilterTransformation(state.workingVariable, condition, isInverse = true)
|
val transformation = createFilterTransformation(state.workingVariable, condition, isInverse = true)
|
||||||
val newState = state.copy(statements = state.statements.drop(1))
|
val newState = state.copy(statements = state.statements.drop(1))
|
||||||
return SequenceTransformationMatch(transformation, newState)
|
return SequenceTransformationMatch(transformation, newState)
|
||||||
|
|||||||
+1
@@ -59,6 +59,7 @@ class FlatMapTransformation(
|
|||||||
val loopBody = nestedLoop.body ?: return null
|
val loopBody = nestedLoop.body ?: return null
|
||||||
val transformation = FlatMapTransformation(state.workingVariable, transform)
|
val transformation = FlatMapTransformation(state.workingVariable, transform)
|
||||||
val newState = state.copy(
|
val newState = state.copy(
|
||||||
|
innerLoop = nestedLoop,
|
||||||
statements = listOf(loopBody),
|
statements = listOf(loopBody),
|
||||||
workingVariable = newWorkingVariable
|
workingVariable = newWorkingVariable
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>for (s in list) {
|
||||||
|
for (line in s.lines()) {
|
||||||
|
if (line.isBlank()) continue
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
<caret>return list
|
||||||
|
.flatMap { it.lines() }
|
||||||
|
.firstOrNull { !it.isBlank() }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// IS_APPLICABLE: false
|
||||||
|
fun foo(list: List<String>): String? {
|
||||||
|
OuterLoop@
|
||||||
|
<caret>for (s in list) {
|
||||||
|
for (line in s.lines()) {
|
||||||
|
if (line.isBlank()) continue@OuterLoop
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user