Refactoring
This commit is contained in:
+86
-66
@@ -85,7 +85,8 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
// we do not try to convert anything if the initializer is not compile-time constant because of possible side-effects
|
// we do not try to convert anything if the initializer is not compile-time constant because of possible side-effects
|
||||||
if (!initialization.initializer.isConstant()) return null
|
if (!initialization.initializer.isConstant()) return null
|
||||||
|
|
||||||
val generator = buildFindOperationGenerator(right, initialization.initializer, state.inputVariable, state.indexVariable, filterTransformation, findFirst)
|
val generator = buildFindOperationGenerator(state.outerLoop, right, initialization.initializer, state.inputVariable,
|
||||||
|
state.indexVariable, filterTransformation, findFirst)
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
val transformation = FindAndAssignTransformation(state.outerLoop, generator, initialization)
|
val transformation = FindAndAssignTransformation(state.outerLoop, generator, initialization)
|
||||||
@@ -100,7 +101,7 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
val returnValueInLoop = returnInLoop.returnedExpression ?: return null
|
val returnValueInLoop = returnInLoop.returnedExpression ?: return null
|
||||||
val returnValueAfterLoop = returnAfterLoop.returnedExpression ?: return null
|
val returnValueAfterLoop = returnAfterLoop.returnedExpression ?: return null
|
||||||
|
|
||||||
val generator = buildFindOperationGenerator(returnValueInLoop, returnValueAfterLoop,
|
val generator = buildFindOperationGenerator(state.outerLoop, returnValueInLoop, returnValueAfterLoop,
|
||||||
state.inputVariable, state.indexVariable, filterTransformation, findFirst = true)
|
state.inputVariable, state.indexVariable, filterTransformation, findFirst = true)
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
@@ -175,7 +176,37 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
get() = 1
|
get() = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SimpleGenerator(
|
||||||
|
override val functionName: String,
|
||||||
|
private val inputVariable: KtCallableDeclaration,
|
||||||
|
private val filter: KtExpression?,
|
||||||
|
override val shouldUseInputVariable: Boolean
|
||||||
|
) : FindOperationGenerator {
|
||||||
|
override val hasFilter: Boolean
|
||||||
|
get() = filter != null
|
||||||
|
|
||||||
|
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
||||||
|
return generateChainedCall(functionName, chainedCallGenerator, inputVariable, filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateChainedCall(
|
||||||
|
stdlibFunName: String,
|
||||||
|
chainedCallGenerator: ChainedCallGenerator,
|
||||||
|
inputVariable: KtCallableDeclaration,
|
||||||
|
filter: KtExpression?
|
||||||
|
): KtExpression {
|
||||||
|
return if (filter == null) {
|
||||||
|
chainedCallGenerator.generate("$stdlibFunName()")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val lambda = generateLambda(inputVariable, filter)
|
||||||
|
chainedCallGenerator.generate("$stdlibFunName $0:'{}'", lambda)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildFindOperationGenerator(
|
private fun buildFindOperationGenerator(
|
||||||
|
loop: KtForExpression,
|
||||||
valueIfFound: KtExpression,
|
valueIfFound: KtExpression,
|
||||||
valueIfNotFound: KtExpression,
|
valueIfNotFound: KtExpression,
|
||||||
inputVariable: KtCallableDeclaration,
|
inputVariable: KtCallableDeclaration,
|
||||||
@@ -186,29 +217,7 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
assert(valueIfFound.isPhysical)
|
assert(valueIfFound.isPhysical)
|
||||||
assert(valueIfNotFound.isPhysical)
|
assert(valueIfNotFound.isPhysical)
|
||||||
|
|
||||||
val filterCondition = filterTransformation?.effectiveCondition()
|
val filter = filterTransformation?.effectiveCondition()
|
||||||
|
|
||||||
fun generateChainedCall(stdlibFunName: String, chainedCallGenerator: ChainedCallGenerator, filter: KtExpression?): KtExpression {
|
|
||||||
return if (filter == null) {
|
|
||||||
chainedCallGenerator.generate("$stdlibFunName()")
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val lambda = generateLambda(inputVariable, filter)
|
|
||||||
chainedCallGenerator.generate("$stdlibFunName $0:'{}'", lambda)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleGenerator(
|
|
||||||
override val functionName: String,
|
|
||||||
override val shouldUseInputVariable: Boolean
|
|
||||||
) : FindOperationGenerator {
|
|
||||||
override val hasFilter: Boolean
|
|
||||||
get() = filterCondition != null
|
|
||||||
|
|
||||||
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
|
||||||
return generateChainedCall(functionName, chainedCallGenerator, filterCondition)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indexVariable != null) {
|
if (indexVariable != null) {
|
||||||
if (filterTransformation == null) return null // makes no sense, indexVariable must be always 0
|
if (filterTransformation == null) return null // makes no sense, indexVariable must be always 0
|
||||||
@@ -216,7 +225,8 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
|
|
||||||
//TODO: what if value when not found is not "-1"?
|
//TODO: what if value when not found is not "-1"?
|
||||||
if (valueIfFound.isVariableReference(indexVariable) && valueIfNotFound.text == "-1") {
|
if (valueIfFound.isVariableReference(indexVariable) && valueIfNotFound.text == "-1") {
|
||||||
return SimpleGenerator(if (findFirst) "indexOfFirst" else "indexOfLast", shouldUseInputVariable = false)
|
val functionName = if (findFirst) "indexOfFirst" else "indexOfLast"
|
||||||
|
return SimpleGenerator(functionName, inputVariable, filter, shouldUseInputVariable = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
@@ -239,45 +249,20 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildGeneratorForAny(negated: Boolean): FindOperationGenerator {
|
|
||||||
if (filterCondition != null) {
|
|
||||||
val containsArgument = filterCondition.isFilterForContainsOperation(inputVariable, filterTransformation!!.loop)
|
|
||||||
if (containsArgument != null) {
|
|
||||||
return object: FindOperationGenerator {
|
|
||||||
override val functionName: String
|
|
||||||
get() = "contains"
|
|
||||||
|
|
||||||
override val hasFilter: Boolean
|
|
||||||
get() = false
|
|
||||||
|
|
||||||
override val shouldUseInputVariable: Boolean
|
|
||||||
get() = false
|
|
||||||
|
|
||||||
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
|
||||||
val expression = chainedCallGenerator.generate("contains($0)", containsArgument)
|
|
||||||
return if (negated) expression.negate() else expression
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negated) {
|
|
||||||
return SimpleGenerator("none", shouldUseInputVariable = false)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return SimpleGenerator("any", shouldUseInputVariable = false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
when {
|
||||||
valueIfFound.isVariableReference(inputVariable) -> {
|
valueIfFound.isVariableReference(inputVariable) -> {
|
||||||
val generator = SimpleGenerator(if (findFirst) "firstOrNull" else "lastOrNull", shouldUseInputVariable = true)
|
val functionName = if (findFirst) "firstOrNull" else "lastOrNull"
|
||||||
|
val generator = SimpleGenerator(functionName, inputVariable, filter, shouldUseInputVariable = true)
|
||||||
return generator.useElvisOperatorIfNeeded()
|
return generator.useElvisOperatorIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
valueIfFound.isTrueConstant() && valueIfNotFound.isFalseConstant() -> return buildGeneratorForAny(negated = false)
|
valueIfFound.isTrueConstant() && valueIfNotFound.isFalseConstant() -> {
|
||||||
|
return buildFoundFlagGenerator(loop, inputVariable, filter, negated = false)
|
||||||
|
}
|
||||||
|
|
||||||
valueIfFound.isFalseConstant() && valueIfNotFound.isTrueConstant() -> return buildGeneratorForAny(negated = true)
|
valueIfFound.isFalseConstant() && valueIfNotFound.isTrueConstant() -> {
|
||||||
|
return buildFoundFlagGenerator(loop, inputVariable, filter, negated = true)
|
||||||
|
}
|
||||||
|
|
||||||
inputVariable.hasUsages(valueIfFound) -> {
|
inputVariable.hasUsages(valueIfFound) -> {
|
||||||
if (!findFirst) return null // too dangerous because of side effects
|
if (!findFirst) return null // too dangerous because of side effects
|
||||||
@@ -293,7 +278,7 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
get() = "firstOrNull"
|
get() = "firstOrNull"
|
||||||
|
|
||||||
override val hasFilter: Boolean
|
override val hasFilter: Boolean
|
||||||
get() = filterCondition != null
|
get() = filter != null
|
||||||
|
|
||||||
override val shouldUseInputVariable: Boolean
|
override val shouldUseInputVariable: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
@@ -302,7 +287,7 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
get() = 2
|
get() = 2
|
||||||
|
|
||||||
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
||||||
val findFirstCall = generateChainedCall(functionName, chainedCallGenerator, filterCondition)
|
val findFirstCall = generateChainedCall(functionName, chainedCallGenerator, inputVariable, filter)
|
||||||
return chainedCallGenerator.generate("$0", selector, receiver = findFirstCall, safeCall = true)
|
return chainedCallGenerator.generate("$0", selector, receiver = findFirstCall, safeCall = true)
|
||||||
}
|
}
|
||||||
}.useElvisOperatorIfNeeded()
|
}.useElvisOperatorIfNeeded()
|
||||||
@@ -317,7 +302,7 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
get() = "firstOrNull"
|
get() = "firstOrNull"
|
||||||
|
|
||||||
override val hasFilter: Boolean
|
override val hasFilter: Boolean
|
||||||
get() = filterCondition != null
|
get() = filter != null
|
||||||
|
|
||||||
override val shouldUseInputVariable: Boolean
|
override val shouldUseInputVariable: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
@@ -326,7 +311,7 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
get() = 2 // also includes "let"
|
get() = 2 // also includes "let"
|
||||||
|
|
||||||
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
||||||
val findFirstCall = generateChainedCall(functionName, chainedCallGenerator, filterCondition)
|
val findFirstCall = generateChainedCall(functionName, chainedCallGenerator, inputVariable, filter)
|
||||||
val letBody = generateLambda(inputVariable, valueIfFound)
|
val letBody = generateLambda(inputVariable, valueIfFound)
|
||||||
return chainedCallGenerator.generate("let $0:'{}'", letBody, receiver = findFirstCall, safeCall = true)
|
return chainedCallGenerator.generate("let $0:'{}'", letBody, receiver = findFirstCall, safeCall = true)
|
||||||
}
|
}
|
||||||
@@ -334,10 +319,10 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val generatorForAny = buildGeneratorForAny(negated = false)
|
val generator = buildFoundFlagGenerator(loop, inputVariable, filter, negated = false)
|
||||||
return object: FindOperationGenerator by generatorForAny {
|
return object: FindOperationGenerator by generator {
|
||||||
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
||||||
val chainedCall = generatorForAny.generate(chainedCallGenerator)
|
val chainedCall = generator.generate(chainedCallGenerator)
|
||||||
return KtPsiFactory(chainedCall).createExpressionByPattern("if ($0) $1 else $2", chainedCall, valueIfFound, valueIfNotFound)
|
return KtPsiFactory(chainedCall).createExpressionByPattern("if ($0) $1 else $2", chainedCall, valueIfFound, valueIfNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,6 +331,41 @@ object FindTransformationMatcher : TransformationMatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildFoundFlagGenerator(
|
||||||
|
loop: KtForExpression,
|
||||||
|
inputVariable: KtCallableDeclaration,
|
||||||
|
filter: KtExpression?,
|
||||||
|
negated: Boolean
|
||||||
|
): FindOperationGenerator {
|
||||||
|
if (filter != null) {
|
||||||
|
val containsArgument = filter.isFilterForContainsOperation(inputVariable, loop)
|
||||||
|
if (containsArgument != null) {
|
||||||
|
return object: FindOperationGenerator {
|
||||||
|
override val functionName: String
|
||||||
|
get() = "contains"
|
||||||
|
|
||||||
|
override val hasFilter: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
|
override val shouldUseInputVariable: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
|
override fun generate(chainedCallGenerator: ChainedCallGenerator): KtExpression {
|
||||||
|
val expression = chainedCallGenerator.generate("contains($0)", containsArgument)
|
||||||
|
return if (negated) expression.negate() else expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negated) {
|
||||||
|
return SimpleGenerator("none", inputVariable, filter, shouldUseInputVariable = false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return SimpleGenerator("any", inputVariable, filter, shouldUseInputVariable = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun KtExpression.isFilterForContainsOperation(inputVariable: KtCallableDeclaration, loop: KtForExpression): KtExpression? {
|
private fun KtExpression.isFilterForContainsOperation(inputVariable: KtCallableDeclaration, loop: KtForExpression): KtExpression? {
|
||||||
if (this !is KtBinaryExpression) return null
|
if (this !is KtBinaryExpression) return null
|
||||||
if (operationToken != KtTokens.EQEQ) return null
|
if (operationToken != KtTokens.EQEQ) return null
|
||||||
|
|||||||
Reference in New Issue
Block a user