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 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
@@ -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)
}
@@ -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)
}
}
@@ -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)
}
}
@@ -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)
}
@@ -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)
}
@@ -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()
}