Tracking inflow of lambda receiver
This commit is contained in:
@@ -179,10 +179,17 @@ class InflowSlicer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is ReceiverParameterDescriptor -> {
|
is ReceiverParameterDescriptor -> {
|
||||||
|
//TODO: handle non-extension receivers?
|
||||||
val callable = accessedDescriptor.containingDeclaration as? CallableDescriptor ?: return
|
val callable = accessedDescriptor.containingDeclaration as? CallableDescriptor ?: return
|
||||||
val callableDeclaration = callable.originalSource.getPsi() as? KtCallableDeclaration ?: return
|
when (val declaration = callable.originalSource.getPsi()) {
|
||||||
//TODO: what about non-extensions?
|
is KtFunctionLiteral -> {
|
||||||
callableDeclaration.receiverTypeReference?.passToProcessor()
|
declaration.passToProcessorAsValue(LambdaCallsBehaviour(ReceiverSliceProducer, behaviour))
|
||||||
|
}
|
||||||
|
|
||||||
|
is KtCallableDeclaration -> {
|
||||||
|
declaration.receiverTypeReference?.passToProcessor()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ValueParameterDescriptor -> {
|
is ValueParameterDescriptor -> {
|
||||||
|
|||||||
@@ -150,17 +150,12 @@ class OutflowSlicer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processFunction(function: KtFunction) {
|
private fun processFunction(function: KtFunction) {
|
||||||
|
//TODO: CallSliceProducer in all cases
|
||||||
if (function is KtConstructor<*> || function is KtNamedFunction && function.name != null) {
|
if (function is KtConstructor<*> || function is KtNamedFunction && function.name != null) {
|
||||||
processCalls(function, includeOverriders = false, sliceProducer = CallSliceProducer)
|
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) {
|
private fun processExtensionReceiver(declaration: KtCallableDeclaration, declarationWithBody: KtDeclarationWithBody) {
|
||||||
@@ -178,7 +173,11 @@ class OutflowSlicer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processExpression(expression: KtExpression) {
|
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) {
|
when (instruction) {
|
||||||
is WriteValueInstruction -> {
|
is WriteValueInstruction -> {
|
||||||
if (!processIfReceiverValue(instruction, pseudoValue)) {
|
if (!processIfReceiverValue(instruction, pseudoValue)) {
|
||||||
|
|||||||
@@ -73,12 +73,7 @@ abstract class Slicer(
|
|||||||
includeOverriders: Boolean,
|
includeOverriders: Boolean,
|
||||||
sliceProducer: SliceProducer
|
sliceProducer: SliceProducer
|
||||||
) {
|
) {
|
||||||
if (callable is KtFunctionLiteral) {
|
if (callable is KtFunctionLiteral || callable is KtFunction && callable.name == null) {
|
||||||
(callable.parent as KtLambdaExpression).passToProcessorAsValue(LambdaCallsBehaviour(sliceProducer, behaviour))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callable is KtFunction && callable.name == null) {
|
|
||||||
callable.passToProcessorAsValue(LambdaCallsBehaviour(sliceProducer, behaviour))
|
callable.passToProcessorAsValue(LambdaCallsBehaviour(sliceProducer, behaviour))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>) {
|
||||||
+5
@@ -118,6 +118,11 @@ public class SlicerLeafGroupingTestGenerated extends AbstractSlicerLeafGroupingT
|
|||||||
runTest("idea/testData/slicer/inflow/extensionLambdaParameter.kt");
|
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")
|
@TestMetadata("funParamerer.kt")
|
||||||
public void testFunParamerer() throws Exception {
|
public void testFunParamerer() throws Exception {
|
||||||
runTest("idea/testData/slicer/inflow/funParamerer.kt");
|
runTest("idea/testData/slicer/inflow/funParamerer.kt");
|
||||||
|
|||||||
+5
@@ -118,6 +118,11 @@ public class SlicerNullnessGroupingTestGenerated extends AbstractSlicerNullnessG
|
|||||||
runTest("idea/testData/slicer/inflow/extensionLambdaParameter.kt");
|
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")
|
@TestMetadata("funParamerer.kt")
|
||||||
public void testFunParamerer() throws Exception {
|
public void testFunParamerer() throws Exception {
|
||||||
runTest("idea/testData/slicer/inflow/funParamerer.kt");
|
runTest("idea/testData/slicer/inflow/funParamerer.kt");
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest {
|
|||||||
runTest("idea/testData/slicer/inflow/extensionLambdaParameter.kt");
|
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")
|
@TestMetadata("funParamerer.kt")
|
||||||
public void testFunParamerer() throws Exception {
|
public void testFunParamerer() throws Exception {
|
||||||
runTest("idea/testData/slicer/inflow/funParamerer.kt");
|
runTest("idea/testData/slicer/inflow/funParamerer.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user