Tracking inflow of lambda receiver

This commit is contained in:
Valentin Kipyatkov
2020-04-11 11:55:46 +03:00
parent 61d4383cb9
commit 7bcd6619cf
10 changed files with 63 additions and 18 deletions
@@ -179,10 +179,17 @@ class InflowSlicer(
}
is ReceiverParameterDescriptor -> {
//TODO: handle non-extension receivers?
val callable = accessedDescriptor.containingDeclaration as? CallableDescriptor ?: return
val callableDeclaration = callable.originalSource.getPsi() as? KtCallableDeclaration ?: return
//TODO: what about non-extensions?
callableDeclaration.receiverTypeReference?.passToProcessor()
when (val declaration = callable.originalSource.getPsi()) {
is KtFunctionLiteral -> {
declaration.passToProcessorAsValue(LambdaCallsBehaviour(ReceiverSliceProducer, behaviour))
}
is KtCallableDeclaration -> {
declaration.receiverTypeReference?.passToProcessor()
}
}
}
is ValueParameterDescriptor -> {
@@ -150,17 +150,12 @@ class OutflowSlicer(
}
private fun processFunction(function: KtFunction) {
//TODO: CallSliceProducer in all cases
if (function is KtConstructor<*> || function is KtNamedFunction && function.name != null) {
processCalls(function, includeOverriders = false, sliceProducer = CallSliceProducer)
return
} else {
processCalls(function, false, SliceProducer.Trivial)
}
val funExpression = when (function) {
is KtFunctionLiteral -> function.parent as? KtLambdaExpression
is KtNamedFunction -> function
else -> null
} ?: return
funExpression.passToProcessor(LambdaCallsBehaviour(SliceProducer.Trivial, behaviour), forcedExpressionMode = true)
}
private fun processExtensionReceiver(declaration: KtCallableDeclaration, declarationWithBody: KtDeclarationWithBody) {
@@ -178,7 +173,11 @@ class OutflowSlicer(
}
private fun processExpression(expression: KtExpression) {
expression.processPseudocodeUsages { pseudoValue, instruction ->
val expressionWithValue = when (expression) {
is KtFunctionLiteral -> expression.parent as KtLambdaExpression
else -> expression
}
expressionWithValue.processPseudocodeUsages { pseudoValue, instruction ->
when (instruction) {
is WriteValueInstruction -> {
if (!processIfReceiverValue(instruction, pseudoValue)) {
@@ -73,12 +73,7 @@ abstract class Slicer(
includeOverriders: Boolean,
sliceProducer: SliceProducer
) {
if (callable is KtFunctionLiteral) {
(callable.parent as KtLambdaExpression).passToProcessorAsValue(LambdaCallsBehaviour(sliceProducer, behaviour))
return
}
if (callable is KtFunction && callable.name == null) {
if (callable is KtFunctionLiteral || callable is KtFunction && callable.name == null) {
callable.passToProcessorAsValue(LambdaCallsBehaviour(sliceProducer, behaviour))
return
}
+11
View File
@@ -0,0 +1,11 @@
// FLOW: IN
fun foo() {
with("A") {
val <caret>v = this
}
}
inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
@@ -0,0 +1,8 @@
4 with(<bold>"A"</bold>) {
5 val <bold>v = this</bold>
5 val v = <bold>this</bold>
4 [LAMBDA OUT] with("A") <bold>{</bold>
9 [LAMBDA OUT] inline fun <T, R> with(receiver: T, <bold>block: T.() -> R</bold>): R {
10 return <bold>receiver</bold>.block()
9 inline fun <T, R> with(<bold>receiver: T</bold>, block: T.() -> R): R {
4 with(<bold>"A"</bold>) {
@@ -0,0 +1,3 @@
[NotNull Values]
5 val <bold>v = this</bold>
5 val <bold>v = this</bold>
@@ -0,0 +1,7 @@
5 val <bold>v = this</bold>
5 val v = <bold>this</bold>
4 [LAMBDA OUT] with("A") <bold>{</bold>
9 [LAMBDA OUT] inline fun <T, R> with(receiver: T, <bold>block: T.() -> R</bold>): R {
10 return <bold>receiver</bold>.block()
9 inline fun <T, R> with(<bold>receiver: T</bold>, block: T.() -> R): R {
4 with(<bold>"A"</bold>) {
@@ -118,6 +118,11 @@ public class SlicerLeafGroupingTestGenerated extends AbstractSlicerLeafGroupingT
runTest("idea/testData/slicer/inflow/extensionLambdaParameter.kt");
}
@TestMetadata("extensionLambdaReceiver.kt")
public void testExtensionLambdaReceiver() throws Exception {
runTest("idea/testData/slicer/inflow/extensionLambdaReceiver.kt");
}
@TestMetadata("funParamerer.kt")
public void testFunParamerer() throws Exception {
runTest("idea/testData/slicer/inflow/funParamerer.kt");
@@ -118,6 +118,11 @@ public class SlicerNullnessGroupingTestGenerated extends AbstractSlicerNullnessG
runTest("idea/testData/slicer/inflow/extensionLambdaParameter.kt");
}
@TestMetadata("extensionLambdaReceiver.kt")
public void testExtensionLambdaReceiver() throws Exception {
runTest("idea/testData/slicer/inflow/extensionLambdaReceiver.kt");
}
@TestMetadata("funParamerer.kt")
public void testFunParamerer() throws Exception {
runTest("idea/testData/slicer/inflow/funParamerer.kt");
@@ -130,6 +130,11 @@ public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest {
runTest("idea/testData/slicer/inflow/extensionLambdaParameter.kt");
}
@TestMetadata("extensionLambdaReceiver.kt")
public void testExtensionLambdaReceiver() throws Exception {
runTest("idea/testData/slicer/inflow/extensionLambdaReceiver.kt");
}
@TestMetadata("funParamerer.kt")
public void testFunParamerer() throws Exception {
runTest("idea/testData/slicer/inflow/funParamerer.kt");