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