From 8f7648c60aba87814492e9e4832ad97a41c449e9 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 10 Feb 2020 11:03:13 +0200 Subject: [PATCH] Reordered methods --- .../kotlin/idea/slicer/InflowSlicer.kt | 169 +++++++++--------- .../kotlin/idea/slicer/OutflowSlicer.kt | 108 ++++++----- .../jetbrains/kotlin/idea/slicer/Slicer.kt | 4 +- 3 files changed, 141 insertions(+), 140 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt b/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt index 9182fe73174..6d0ea5db71d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt @@ -44,63 +44,21 @@ class InflowSlicer( processor: Processor, parentUsage: KotlinSliceUsage ) : Slicer(element, processor, parentUsage) { - private fun PsiElement.processHierarchyDownwardAndPass() { - processHierarchyDownward(parentUsage.scope.toSearchScope()) { passToProcessor() } - } - private fun PsiElement.processHierarchyDownward(scope: SearchScope, processor: PsiElement.() -> Unit) { - processor() - HierarchySearchRequest(this, scope).searchOverriders().forEach { - it.namedUnwrappedElement?.processor() + override fun processChildren() { + if (parentUsage.forcedExpressionMode) { + return processExpression(element) } - } - private fun PsiElement.passToProcessorAsValue(lambdaLevel: Int = parentUsage.lambdaLevel) = passToProcessor(lambdaLevel, true) - - private fun processAssignments(variableDeclaration: KtCallableDeclaration, accessSearchScope: SearchScope) { - processVariableAccesses(variableDeclaration, accessSearchScope, AccessKind.WRITE_WITH_OPTIONAL_READ) body@{ - val refElement = it.element ?: return@body - val refParent = refElement.parent - - val rhsValue = when { - refElement is KtExpression -> { - val (accessKind, accessExpression) = refElement.readWriteAccessWithFullExpression(true) - if (accessKind == ReferenceAccess.WRITE && accessExpression is KtBinaryExpression && accessExpression.operationToken == KtTokens.EQ) { - accessExpression.right - } else { - accessExpression - } - } - - refParent is PsiCall -> refParent.argumentList?.expressions?.getOrNull(0) - - else -> null - } - rhsValue?.passToProcessorAsValue() + when (element) { + is KtProperty -> processProperty(element) + // for parameter, we include overriders only when the feature is invoked on parameter itself + is KtParameter -> processParameter(parameter = element, includeOverriders = parentUsage.parent == null) + is KtDeclarationWithBody -> element.processBody() + else -> processExpression(element) } } - private fun KtPropertyAccessor.processBackingFieldAssignments() { - forEachDescendantOfType body@{ - if (it.operationToken != KtTokens.EQ) return@body - val lhs = it.left?.let { expression -> KtPsiUtil.safeDeparenthesize(expression) } ?: return@body - val rhs = it.right ?: return@body - if (!lhs.isBackingFieldReference()) return@body - rhs.passToProcessor() - } - } - - private fun KtProperty.processPropertyAssignments() { - val analysisScope = parentUsage.scope.toSearchScope() - val accessSearchScope = if (isVar) { - analysisScope - } else { - val containerScope = getStrictParentOfType()?.let { LocalSearchScope(it) } ?: return - analysisScope.intersectWith(containerScope) - } - processAssignments(this, accessSearchScope) - } - private fun processProperty(property: KtProperty) { val bindingContext by lazy { property.analyzeWithContent() } @@ -177,30 +135,6 @@ class InflowSlicer( } } - private fun KtDeclarationWithBody.processBody() { - val bodyExpression = bodyExpression ?: return - val pseudocode = pseudocodeCache[bodyExpression] ?: return - pseudocode.traverse(TraversalOrder.FORWARD) { instr -> - if (instr is ReturnValueInstruction && instr.subroutine == this) { - (instr.returnExpressionIfAny?.returnedExpression ?: instr.element as? KtExpression)?.passToProcessorAsValue() - } - } - } - - private fun Instruction.passInputsToProcessor() { - inputValues.forEach { - if (it.createdAt != null) { - it.element?.passToProcessorAsValue() - } - } - } - - private fun KtExpression.isBackingFieldReference(): Boolean { - return this is KtSimpleNameExpression && - getReferencedName() == SyntheticFieldDescriptor.NAME.asString() && - resolveToCall()?.resultingDescriptor is SyntheticFieldDescriptor - } - private fun processExpression(expression: KtExpression) { val lambda = when (expression) { is KtLambdaExpression -> expression.functionLiteral @@ -265,15 +199,84 @@ class InflowSlicer( } } - override fun processChildren() { - if (parentUsage.forcedExpressionMode) return processExpression(element) + private fun KtProperty.processPropertyAssignments() { + val analysisScope = parentUsage.scope.toSearchScope() + val accessSearchScope = if (isVar) { + analysisScope + } else { + val containerScope = getStrictParentOfType()?.let { LocalSearchScope(it) } ?: return + analysisScope.intersectWith(containerScope) + } + processAssignments(this, accessSearchScope) + } - when (element) { - is KtProperty -> processProperty(element) - // for parameter, we include overriders only when the feature is invoked on parameter itself - is KtParameter -> processParameter(parameter = element, includeOverriders = parentUsage.parent == null) - is KtDeclarationWithBody -> element.processBody() - else -> processExpression(element) + private fun processAssignments(variable: KtCallableDeclaration, accessSearchScope: SearchScope) { + processVariableAccesses(variable, accessSearchScope, AccessKind.WRITE_WITH_OPTIONAL_READ) body@{ + val refElement = it.element ?: return@body + val refParent = refElement.parent + + val rhsValue = when { + refElement is KtExpression -> { + val (accessKind, accessExpression) = refElement.readWriteAccessWithFullExpression(true) + if (accessKind == ReferenceAccess.WRITE && accessExpression is KtBinaryExpression && accessExpression.operationToken == KtTokens.EQ) { + accessExpression.right + } else { + accessExpression + } + } + + refParent is PsiCall -> refParent.argumentList?.expressions?.getOrNull(0) + + else -> null + } + rhsValue?.passToProcessorAsValue() + } + } + + private fun KtPropertyAccessor.processBackingFieldAssignments() { + forEachDescendantOfType body@{ + if (it.operationToken != KtTokens.EQ) return@body + val lhs = it.left?.let { expression -> KtPsiUtil.safeDeparenthesize(expression) } ?: return@body + val rhs = it.right ?: return@body + if (!lhs.isBackingFieldReference()) return@body + rhs.passToProcessor() + } + } + + private fun KtExpression.isBackingFieldReference(): Boolean { + return this is KtSimpleNameExpression && + getReferencedName() == SyntheticFieldDescriptor.NAME.asString() && + resolveToCall()?.resultingDescriptor is SyntheticFieldDescriptor + } + + private fun KtDeclarationWithBody.processBody() { + val bodyExpression = bodyExpression ?: return + val pseudocode = pseudocodeCache[bodyExpression] ?: return + pseudocode.traverse(TraversalOrder.FORWARD) { instr -> + if (instr is ReturnValueInstruction && instr.subroutine == this) { + (instr.returnExpressionIfAny?.returnedExpression ?: instr.element as? KtExpression)?.passToProcessorAsValue() + } + } + } + + private fun Instruction.passInputsToProcessor() { + inputValues.forEach { + if (it.createdAt != null) { + it.element?.passToProcessorAsValue() + } + } + } + + private fun PsiElement.passToProcessorAsValue(lambdaLevel: Int = parentUsage.lambdaLevel) = passToProcessor(lambdaLevel, true) + + private fun PsiElement.processHierarchyDownwardAndPass() { + processHierarchyDownward(parentUsage.scope.toSearchScope()) { passToProcessor() } + } + + private fun PsiElement.processHierarchyDownward(scope: SearchScope, processor: PsiElement.() -> Unit) { + processor() + HierarchySearchRequest(this, scope).searchOverriders().forEach { + it.namedUnwrappedElement?.processor() } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt b/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt index b033e491bd3..2214259ab3c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt @@ -21,7 +21,19 @@ class OutflowSlicer( processor: Processor, parentUsage: KotlinSliceUsage ) : Slicer(element, processor, parentUsage) { - + + override fun processChildren() { + if (parentUsage.forcedExpressionMode) return processExpression(element) + + when (element) { + is KtProperty -> processVariable(element) + is KtParameter -> processVariable(element) + is KtFunction -> processFunction(element) + is KtPropertyAccessor -> if (element.isGetter) processVariable(element.property) + else -> processExpression(element) + } + } + private fun processVariable(variable: KtCallableDeclaration) { if (variable is KtParameter && !variable.canProcess()) return @@ -48,25 +60,6 @@ class OutflowSlicer( } } - private fun PsiElement.getCallElementForExactCallee(): PsiElement? { - if (this is KtArrayAccessExpression) return this - - val operationRefExpr = getNonStrictParentOfType() - if (operationRefExpr != null) return operationRefExpr.parent as? KtOperationExpression - - val parentCall = getParentOfTypeAndBranch { calleeExpression } ?: return null - val callee = parentCall.calleeExpression?.let { KtPsiUtil.safeDeparenthesize(it) } - if (callee == this || callee is KtConstructorCalleeExpression && callee.isAncestor(this, true)) return parentCall - - return null - } - - private fun PsiElement.getCallableReferenceForExactCallee(): KtCallableReferenceExpression? { - val callableRef = getParentOfTypeAndBranch { callableReference } ?: return null - val callee = KtPsiUtil.safeDeparenthesize(callableRef.callableReference) - return if (callee == this) callableRef else null - } - private fun processFunction(function: KtFunction) { if (function is KtConstructor<*> || function is KtNamedFunction && function.name != null) { function.processCalls(this.parentUsage.scope.toSearchScope(), includeOverriders = false) { @@ -90,6 +83,46 @@ class OutflowSlicer( (funExpression as PsiElement).passToProcessor(parentUsage.lambdaLevel + 1, true) } + private fun processExpression(expression: KtExpression) { + expression.processPseudocodeUsages { pseudoValue, instr -> + when (instr) { + is WriteValueInstruction -> instr.target.accessedDescriptor?.originalSource?.getPsi()?.passToProcessor() + is CallInstruction -> { + if (this.parentUsage.lambdaLevel > 0 && instr.receiverValues[pseudoValue] != null) { + instr.element.passToProcessor(this.parentUsage.lambdaLevel - 1) + } else { + instr.arguments[pseudoValue]?.originalSource?.getPsi()?.passToProcessor() + } + } + is ReturnValueInstruction -> instr.subroutine.passToProcessor() + is MagicInstruction -> when (instr.kind) { + MagicKind.NOT_NULL_ASSERTION, MagicKind.CAST -> instr.outputValue.element?.passToProcessor() + else -> { + } + } + } + } + } + + private fun PsiElement.getCallElementForExactCallee(): PsiElement? { + if (this is KtArrayAccessExpression) return this + + val operationRefExpr = getNonStrictParentOfType() + if (operationRefExpr != null) return operationRefExpr.parent as? KtOperationExpression + + val parentCall = getParentOfTypeAndBranch { calleeExpression } ?: return null + val callee = parentCall.calleeExpression?.let { KtPsiUtil.safeDeparenthesize(it) } + if (callee == this || callee is KtConstructorCalleeExpression && callee.isAncestor(this, true)) return parentCall + + return null + } + + private fun PsiElement.getCallableReferenceForExactCallee(): KtCallableReferenceExpression? { + val callableRef = getParentOfTypeAndBranch { callableReference } ?: return null + val callee = KtPsiUtil.safeDeparenthesize(callableRef.callableReference) + return if (callee == this) callableRef else null + } + private fun processDereferenceIsNeeded( expression: KtExpression, pseudoValue: PseudoValue, @@ -129,39 +162,4 @@ class OutflowSlicer( } } } - - private fun processExpression(expression: KtExpression) { - expression.processPseudocodeUsages { pseudoValue, instr -> - when (instr) { - is WriteValueInstruction -> instr.target.accessedDescriptor?.originalSource?.getPsi()?.passToProcessor() - is CallInstruction -> { - if (this.parentUsage.lambdaLevel > 0 && instr.receiverValues[pseudoValue] != null) { - instr.element.passToProcessor(this.parentUsage.lambdaLevel - 1) - } else { - instr.arguments[pseudoValue]?.originalSource?.getPsi()?.passToProcessor() - } - } - is ReturnValueInstruction -> instr.subroutine.passToProcessor() - is MagicInstruction -> when (instr.kind) { - MagicKind.NOT_NULL_ASSERTION, MagicKind.CAST -> instr.outputValue.element?.passToProcessor() - else -> { - } - } - } - } - } - - override fun processChildren() { - if (parentUsage.forcedExpressionMode) return processExpression(element) - - when (element) { - is KtProperty -> processVariable(element) - is KtParameter -> processVariable(element) - is KtFunction -> processFunction(element) - is KtPropertyAccessor -> if (element.isGetter) { - processVariable(element.property) - } - else -> processExpression(element) - } - } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt b/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt index aafac3c880e..e169c38f802 100644 --- a/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt @@ -36,6 +36,8 @@ abstract class Slicer( protected val processor: Processor, protected val parentUsage: KotlinSliceUsage ) { + abstract fun processChildren() + protected class PseudocodeCache { private val computedPseudocodes = HashMap() @@ -57,8 +59,6 @@ abstract class Slicer( processor.process(KotlinSliceUsage(this, parentUsage, lambdaLevel, forcedExpressionMode)) } - abstract fun processChildren() - protected fun KtFunction.processCalls(scope: SearchScope, includeOverriders: Boolean, usageProcessor: (UsageInfo) -> Unit) { val options = KotlinFunctionFindUsagesOptions(project).apply { isSearchForTextOccurrences = false