Consistent use of term "input variable" instead of "working variable"
This commit is contained in:
@@ -72,7 +72,7 @@ data class MatchingState(
|
||||
val outerLoop: KtForExpression,
|
||||
val innerLoop: KtForExpression,
|
||||
val statements: Collection<KtExpression>,
|
||||
val workingVariable: KtCallableDeclaration,
|
||||
val inputVariable: KtCallableDeclaration,
|
||||
val indexVariable: KtCallableDeclaration?
|
||||
)
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ fun match(loop: KtForExpression): ResultTransformationMatch? {
|
||||
outerLoop = loop,
|
||||
innerLoop = loop,
|
||||
statements = listOf(loop.body ?: return null),
|
||||
workingVariable = loop.loopParameter ?: return null,
|
||||
inputVariable = loop.loopParameter ?: return null,
|
||||
indexVariable = null
|
||||
)
|
||||
|
||||
@@ -83,8 +83,8 @@ fun match(loop: KtForExpression): ResultTransformationMatch? {
|
||||
val match = matcher.match(state)
|
||||
if (match != null) {
|
||||
val newState = match.newState
|
||||
// check that old working variable is not needed anymore
|
||||
if (state.workingVariable != newState.workingVariable && state.workingVariable.hasUsages(newState.statements)) return null
|
||||
// check that old input variable is not needed anymore
|
||||
if (state.inputVariable != newState.inputVariable && state.inputVariable.hasUsages(newState.statements)) return null
|
||||
|
||||
sequenceTransformations.addAll(match.transformations)
|
||||
state = newState
|
||||
|
||||
+3
-3
@@ -61,11 +61,11 @@ class AddToCollectionTransformation(
|
||||
|
||||
//TODO: if variable is initialized with new collection than generate toList(), toSet()
|
||||
|
||||
val transformation = if (argumentValue.isVariableReference(state.workingVariable)) {
|
||||
AddToCollectionTransformation(state.outerLoop, state.workingVariable, targetCollection)
|
||||
val transformation = if (argumentValue.isVariableReference(state.inputVariable)) {
|
||||
AddToCollectionTransformation(state.outerLoop, state.inputVariable, targetCollection)
|
||||
}
|
||||
else {
|
||||
MapToTransformation(state.outerLoop, state.workingVariable, targetCollection, argumentValue)
|
||||
MapToTransformation(state.outerLoop, state.inputVariable, targetCollection, argumentValue)
|
||||
}
|
||||
return ResultTransformationMatch(transformation)
|
||||
}
|
||||
|
||||
+2
-2
@@ -109,9 +109,9 @@ class FindAndAssignTransformation(
|
||||
initialization.initializer, initialization.initializer.analyze(BodyResolveMode.PARTIAL)) != null
|
||||
if (!initializerIsConstant) return null
|
||||
|
||||
val generator = buildFindOperationGenerator(right, initialization.initializer, state.workingVariable, findFirst) ?: return null
|
||||
val generator = buildFindOperationGenerator(right, initialization.initializer, state.inputVariable, findFirst) ?: return null
|
||||
|
||||
val transformation = FindAndAssignTransformation(state.outerLoop, state.workingVariable, generator, initialization)
|
||||
val transformation = FindAndAssignTransformation(state.outerLoop, state.inputVariable, generator, initialization)
|
||||
return ResultTransformationMatch(transformation)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -74,9 +74,9 @@ class FindAndReturnTransformation(
|
||||
val returnValueInLoop = returnInLoop.returnedExpression ?: return null
|
||||
val returnValueAfterLoop = returnAfterLoop.returnedExpression ?: return null
|
||||
|
||||
val generator = buildFindOperationGenerator(returnValueInLoop, returnValueAfterLoop, state.workingVariable, findFirst = true) ?: return null
|
||||
val generator = buildFindOperationGenerator(returnValueInLoop, returnValueAfterLoop, state.inputVariable, findFirst = true) ?: return null
|
||||
|
||||
val transformation = FindAndReturnTransformation(state.outerLoop, state.workingVariable, generator, returnAfterLoop)
|
||||
val transformation = FindAndReturnTransformation(state.outerLoop, state.inputVariable, generator, returnAfterLoop)
|
||||
return ResultTransformationMatch(transformation)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -73,14 +73,14 @@ class FilterTransformation(
|
||||
val then = ifStatement.then ?: return null
|
||||
|
||||
if (state.statements.size == 1) {
|
||||
val transformation = createFilterTransformation(state.workingVariable, condition, isInverse = false)
|
||||
val transformation = createFilterTransformation(state.inputVariable, condition, isInverse = false)
|
||||
val newState = state.copy(statements = listOf(then))
|
||||
return SequenceTransformationMatch(transformation, newState)
|
||||
}
|
||||
else {
|
||||
val continueExpression = then.blockExpressionsOrSingle().singleOrNull() as? KtContinueExpression ?: return null
|
||||
if (!continueExpression.isBreakOrContinueOfLoop(state.innerLoop)) return null
|
||||
val transformation = createFilterTransformation(state.workingVariable, condition, isInverse = true)
|
||||
val transformation = createFilterTransformation(state.inputVariable, condition, isInverse = true)
|
||||
val newState = state.copy(statements = state.statements.drop(1))
|
||||
return SequenceTransformationMatch(transformation, newState)
|
||||
}
|
||||
|
||||
+2
-2
@@ -63,11 +63,11 @@ class FlatMapTransformation(
|
||||
val nestedLoopBody = nestedLoop.body ?: return null
|
||||
|
||||
val newWorkingVariable = nestedLoop.loopParameter ?: return null
|
||||
val transformation = FlatMapTransformation(state.workingVariable, transform)
|
||||
val transformation = FlatMapTransformation(state.inputVariable, transform)
|
||||
val newState = state.copy(
|
||||
innerLoop = nestedLoop,
|
||||
statements = listOf(nestedLoopBody),
|
||||
workingVariable = newWorkingVariable
|
||||
inputVariable = newWorkingVariable
|
||||
)
|
||||
return SequenceTransformationMatch(transformation, newState)
|
||||
}
|
||||
|
||||
+2
-2
@@ -50,8 +50,8 @@ class MapTransformation(
|
||||
if (declaration.hasWriteUsages()) return null
|
||||
val restStatements = state.statements.drop(1)
|
||||
|
||||
val transformation = MapTransformation(state.workingVariable, initializer)
|
||||
val newState = state.copy(statements = restStatements, workingVariable = declaration)
|
||||
val transformation = MapTransformation(state.inputVariable, initializer)
|
||||
val newState = state.copy(statements = restStatements, inputVariable = declaration)
|
||||
return SequenceTransformationMatch(transformation, newState)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ import org.jetbrains.kotlin.types.typeUtil.nullability
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
fun generateLambda(workingVariable: KtCallableDeclaration, expression: KtExpression): KtLambdaExpression {
|
||||
fun generateLambda(inputVariable: KtCallableDeclaration, expression: KtExpression): KtLambdaExpression {
|
||||
val psiFactory = KtPsiFactory(expression)
|
||||
|
||||
val lambdaExpression = psiFactory.createExpressionByPattern("{ $0 -> $1 }", workingVariable.nameAsSafeName, expression) as KtLambdaExpression
|
||||
val lambdaExpression = psiFactory.createExpressionByPattern("{ $0 -> $1 }", inputVariable.nameAsSafeName, expression) as KtLambdaExpression
|
||||
|
||||
val isItUsedInside = expression.anyDescendantOfType<KtNameReferenceExpression> {
|
||||
it.getQualifiedExpressionForSelector() == null && it.getReferencedName() == "it"
|
||||
@@ -53,8 +53,8 @@ fun generateLambda(workingVariable: KtCallableDeclaration, expression: KtExpress
|
||||
|
||||
if (isItUsedInside) return lambdaExpression
|
||||
|
||||
val resolutionScope = workingVariable.getResolutionScope(workingVariable.analyze(BodyResolveMode.FULL), workingVariable.getResolutionFacade())
|
||||
val bindingContext = lambdaExpression.analyzeInContext(resolutionScope, contextExpression = workingVariable)
|
||||
val resolutionScope = inputVariable.getResolutionScope(inputVariable.analyze(BodyResolveMode.FULL), inputVariable.getResolutionFacade())
|
||||
val bindingContext = lambdaExpression.analyzeInContext(resolutionScope, contextExpression = inputVariable)
|
||||
val lambdaParam = lambdaExpression.valueParameters.single()
|
||||
val lambdaParamDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, lambdaParam]
|
||||
val usages = lambdaExpression.collectDescendantsOfType<KtNameReferenceExpression> {
|
||||
@@ -106,7 +106,7 @@ fun KtProperty.hasWriteUsages(): Boolean {
|
||||
fun buildFindOperationGenerator(
|
||||
valueIfFound: KtExpression,
|
||||
valueIfNotFound: KtExpression,
|
||||
workingVariable: KtCallableDeclaration,
|
||||
inputVariable: KtCallableDeclaration,
|
||||
findFirst: Boolean
|
||||
): ((chainedCallGenerator: ChainedCallGenerator, filter: KtExpression?) -> KtExpression)? {
|
||||
assert(valueIfFound.isPhysical)
|
||||
@@ -117,18 +117,18 @@ fun buildFindOperationGenerator(
|
||||
chainedCallGenerator.generate("$stdlibFunName()")
|
||||
}
|
||||
else {
|
||||
val lambda = generateLambda(workingVariable, filter)
|
||||
val lambda = generateLambda(inputVariable, filter)
|
||||
chainedCallGenerator.generate("$stdlibFunName $0:'{}'", lambda)
|
||||
}
|
||||
}
|
||||
|
||||
val workingVariableCanHoldNull = (workingVariable.resolveToDescriptor() as VariableDescriptor).type.nullability() != TypeNullability.NOT_NULL
|
||||
val inputVariableCanHoldNull = (inputVariable.resolveToDescriptor() as VariableDescriptor).type.nullability() != TypeNullability.NOT_NULL
|
||||
|
||||
fun ((chainedCallGenerator: ChainedCallGenerator, filter: KtExpression?) -> KtExpression).useElvisOperatorIfNeeded(): ((chainedCallGenerator: ChainedCallGenerator, filter: KtExpression?) -> KtExpression)? {
|
||||
if (valueIfNotFound.isNullExpression()) return this
|
||||
|
||||
// we cannot use ?: if found value can be null
|
||||
if (workingVariableCanHoldNull) return null
|
||||
if (inputVariableCanHoldNull) return null
|
||||
|
||||
return { chainedCallGenerator, filter ->
|
||||
val generated = this(chainedCallGenerator, filter)
|
||||
@@ -137,7 +137,7 @@ fun buildFindOperationGenerator(
|
||||
}
|
||||
|
||||
when {
|
||||
valueIfFound.isVariableReference(workingVariable) -> {
|
||||
valueIfFound.isVariableReference(inputVariable) -> {
|
||||
val stdlibFunName = if (findFirst) "firstOrNull" else "lastOrNull"
|
||||
val generator = { chainedCallGenerator: ChainedCallGenerator, filter: KtExpression? ->
|
||||
generateChainedCall(stdlibFunName, chainedCallGenerator, filter)
|
||||
@@ -153,15 +153,15 @@ fun buildFindOperationGenerator(
|
||||
return { chainedCallGenerator, filter -> generateChainedCall("none", chainedCallGenerator, filter) }
|
||||
}
|
||||
|
||||
workingVariable.hasUsages(valueIfFound) -> {
|
||||
inputVariable.hasUsages(valueIfFound) -> {
|
||||
if (!findFirst) return null // too dangerous because of side effects
|
||||
|
||||
// specially handle the case when the result expression is "<working variable>.<some call>" or "<working variable>?.<some call>"
|
||||
// specially handle the case when the result expression is "<input variable>.<some call>" or "<input variable>?.<some call>"
|
||||
val qualifiedExpression = valueIfFound as? KtQualifiedExpression
|
||||
if (qualifiedExpression != null) {
|
||||
val receiver = qualifiedExpression.receiverExpression
|
||||
val selector = qualifiedExpression.selectorExpression
|
||||
if (receiver.isVariableReference(workingVariable) && selector != null && !workingVariable.hasUsages(selector)) {
|
||||
if (receiver.isVariableReference(inputVariable) && selector != null && !inputVariable.hasUsages(selector)) {
|
||||
return { chainedCallGenerator: ChainedCallGenerator, filter: KtExpression? ->
|
||||
val findFirstCall = generateChainedCall("firstOrNull", chainedCallGenerator, filter)
|
||||
KtPsiFactory(findFirstCall).createExpressionByPattern("$0?.$1", findFirstCall, selector)
|
||||
@@ -169,12 +169,12 @@ fun buildFindOperationGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
// in case of nullable working variable we cannot distinguish by the result of "firstOrNull" whether nothing was found or 'null' was found
|
||||
if (workingVariableCanHoldNull) return null
|
||||
// in case of nullable input variable we cannot distinguish by the result of "firstOrNull" whether nothing was found or 'null' was found
|
||||
if (inputVariableCanHoldNull) return null
|
||||
|
||||
return { chainedCallGenerator: ChainedCallGenerator, filter: KtExpression? ->
|
||||
val findFirstCall = generateChainedCall("firstOrNull", chainedCallGenerator, filter)
|
||||
val letBody = generateLambda(workingVariable, valueIfFound)
|
||||
val letBody = generateLambda(inputVariable, valueIfFound)
|
||||
KtPsiFactory(findFirstCall).createExpressionByPattern("$0?.let $1:'{}'", findFirstCall, letBody)
|
||||
}.useElvisOperatorIfNeeded()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user