Consistent use of term "input variable" instead of "working variable"

This commit is contained in:
Valentin Kipyatkov
2016-04-06 16:43:19 +03:00
parent df08493337
commit f3c760607b
9 changed files with 32 additions and 32 deletions
@@ -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
@@ -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)
} }
@@ -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)
} }
} }
@@ -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)
} }
} }
@@ -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)
} }
@@ -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)
} }
@@ -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()
} }