From 269420a0e0312d3017f603549b603fa32689449d Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Sat, 11 Apr 2020 13:43:16 +0300 Subject: [PATCH] Processing implicit extension receiver usages in outflow processing --- .../kotlin/idea/slicer/OutflowSlicer.kt | 20 +++++++++++++++++-- .../slicer/outflow/implicitReceiver.kt | 13 ++++++++++++ .../outflow/implicitReceiver.results.txt | 7 +++++++ .../idea/slicer/SlicerTreeTestGenerated.java | 5 +++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 idea/testData/slicer/outflow/implicitReceiver.kt create mode 100644 idea/testData/slicer/outflow/implicitReceiver.results.txt diff --git a/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt b/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt index f9413f9f41c..9058bec5033 100644 --- a/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/slicer/OutflowSlicer.kt @@ -153,16 +153,32 @@ class OutflowSlicer( private fun processExtensionReceiver(declaration: KtCallableDeclaration, declarationWithBody: KtDeclarationWithBody) { //TODO: overriders - //TODO: implicit receivers val resolutionFacade = declaration.getResolutionFacade() val callableDescriptor = declaration.resolveToDescriptorIfAny(resolutionFacade) as? CallableDescriptor ?: return val extensionReceiver = callableDescriptor.extensionReceiverParameter ?: return - declarationWithBody.bodyExpression?.forEachDescendantOfType { thisExpression -> + val body = declarationWithBody.bodyExpression ?: return + + body.forEachDescendantOfType { thisExpression -> val receiverDescriptor = thisExpression.resolveToCall(resolutionFacade)?.resultingDescriptor if (receiverDescriptor == extensionReceiver) { thisExpression.passToProcessor() } } + + // process implicit receiver usages + val pseudocode = pseudocodeCache[body] + if (pseudocode != null) { + for (instruction in pseudocode.instructions) { + if (instruction is MagicInstruction && instruction.kind == MagicKind.IMPLICIT_RECEIVER) { + val receiverPseudoValue = instruction.outputValue + pseudocode.getUsages(receiverPseudoValue).forEach { receiverUseInstruction -> + if (receiverUseInstruction is KtElementInstruction) { + processIfReceiverValue(receiverUseInstruction, receiverPseudoValue) + } + } + } + } + } } private fun processExpression(expression: KtExpression) { diff --git a/idea/testData/slicer/outflow/implicitReceiver.kt b/idea/testData/slicer/outflow/implicitReceiver.kt new file mode 100644 index 00000000000..a47eaef831f --- /dev/null +++ b/idea/testData/slicer/outflow/implicitReceiver.kt @@ -0,0 +1,13 @@ +// FLOW: OUT + +fun Any.extensionFun(): Any { + return this +} + +fun String.foo() { + val v = extensionFun() +} + +fun main() { + "A".foo() +} diff --git a/idea/testData/slicer/outflow/implicitReceiver.results.txt b/idea/testData/slicer/outflow/implicitReceiver.results.txt new file mode 100644 index 00000000000..f8b80bc6114 --- /dev/null +++ b/idea/testData/slicer/outflow/implicitReceiver.results.txt @@ -0,0 +1,7 @@ +12 "A".foo() +7 fun String.foo() { +3 fun Any.extensionFun(): Any { +4 return this +3 fun Any.extensionFun(): Any { +8 val v = extensionFun() +8 val v = extensionFun() diff --git a/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTreeTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTreeTestGenerated.java index bde4ff07e78..a7efb332f2a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTreeTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTreeTestGenerated.java @@ -583,6 +583,11 @@ public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest { runTest("idea/testData/slicer/outflow/ifExpression.kt"); } + @TestMetadata("implicitReceiver.kt") + public void testImplicitReceiver() throws Exception { + runTest("idea/testData/slicer/outflow/implicitReceiver.kt"); + } + @TestMetadata("indexingDereferences.kt") public void testIndexingDereferences() throws Exception { runTest("idea/testData/slicer/outflow/indexingDereferences.kt");