Track anonymous function parameters in inbound data flow analysis as well

This commit is contained in:
Valentin Kipyatkov
2020-04-10 20:48:10 +03:00
parent f0d4d7bb86
commit b5b0fd62a9
13 changed files with 81 additions and 11 deletions
@@ -131,12 +131,20 @@ class InflowSlicer(
if (function is KtFunction) {
val sliceTransformer = ArgumentExpressionTransformer(parameterDescriptor)
if (function is KtFunctionLiteral) {
processFunctionLiteralCalls(function, sliceTransformer)
} else {
processCalls(function, analysisScope, includeOverriders) { usageInfo ->
usageInfo.element?.let {
sliceTransformer.extractArgumentExpression(it)?.passToProcessorAsValue()
when {
function is KtFunctionLiteral -> {
processFunctionLiteralCalls(function, sliceTransformer)
}
function is KtNamedFunction && function.name == null -> {
processAnonymousFunctionCalls(function, sliceTransformer)
}
else -> {
processCalls(function, analysisScope, includeOverriders) { usageInfo ->
usageInfo.element?.let {
sliceTransformer.extractArgumentExpression(it)?.passToProcessorAsValue()
}
}
}
}
@@ -9,7 +9,6 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.search.SearchScope
import com.intellij.slicer.JavaSliceUsage
import com.intellij.slicer.SliceUsage
import com.intellij.usageView.UsageInfo
import com.intellij.util.containers.addIfNotNull
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
@@ -70,10 +69,18 @@ abstract class Slicer(
}
protected fun processFunctionLiteralCalls(
callable: KtFunctionLiteral,
functionLiteral: KtFunctionLiteral,
sliceTransformer: KotlinSliceUsageTransformer,
) {
(callable.parent as KtLambdaExpression).passToProcessorAsValue(LambdaCallsBehaviour(sliceTransformer, behaviour))
(functionLiteral.parent as KtLambdaExpression).passToProcessorAsValue(LambdaCallsBehaviour(sliceTransformer, behaviour))
}
protected fun processAnonymousFunctionCalls(
function: KtNamedFunction,
sliceTransformer: KotlinSliceUsageTransformer,
) {
require(function.name == null)
function.passToProcessorAsValue(LambdaCallsBehaviour(sliceTransformer, behaviour))
}
protected fun processCalls(
@@ -1,4 +1,4 @@
8 val x = foo(fun(<bold>n: Int</bold>) = n)
4 return f(<bold>1</bold>)
8 val <bold>x = foo(fun(n: Int) = n)</bold>
8 val x = <bold>foo(fun(n: Int) = n)</bold>
3 fun <bold>foo(f: (Int) -> Int): Int {</bold>
@@ -9,4 +9,7 @@
8 val x = foo(<bold>fun(n: Int) = n</bold>)
8 val x = foo(fun(n: Int) = <bold>n</bold>)
8 val x = foo(fun(<bold>n: Int</bold>) = n)
8 [LAMBDA CALLS] val x = foo(<bold>fun(n: Int) = n</bold>)
3 [LAMBDA CALLS] fun foo(<bold>f: (Int) -> Int</bold>): Int {
4 return f(<bold>1</bold>)
@@ -8,3 +8,6 @@
8 val x = foo(<bold>fun(n: Int) = n</bold>)
8 val x = foo(fun(n: Int) = <bold>n</bold>)
8 val x = foo(fun(<bold>n: Int</bold>) = n)
8 [LAMBDA CALLS] val x = foo(<bold>fun(n: Int) = n</bold>)
3 [LAMBDA CALLS] fun foo(<bold>f: (Int) -> Int</bold>): Int {
4 return f(<bold>1</bold>)
@@ -1,4 +1,4 @@
8 val x = foo(fun(<bold>n: Int</bold>): Int { return n })
4 return f(<bold>1</bold>)
8 val <bold>x = foo(fun(n: Int): Int { return n })</bold>
8 val x = <bold>foo(fun(n: Int): Int { return n })</bold>
3 fun <bold>foo(f: (Int) -> Int): Int {</bold>
@@ -9,4 +9,7 @@
8 val x = foo(<bold>fun(n: Int): Int { return n }</bold>)
8 val x = foo(fun(n: Int): Int { return <bold>n</bold> })
8 val x = foo(fun(<bold>n: Int</bold>): Int { return n })
8 [LAMBDA CALLS] val x = foo(<bold>fun(n: Int): Int { return n }</bold>)
3 [LAMBDA CALLS] fun foo(<bold>f: (Int) -> Int</bold>): Int {
4 return f(<bold>1</bold>)
@@ -8,3 +8,6 @@
8 val x = foo(<bold>fun(n: Int): Int { return n }</bold>)
8 val x = foo(fun(n: Int): Int { return <bold>n</bold> })
8 val x = foo(fun(<bold>n: Int</bold>): Int { return n })
8 [LAMBDA CALLS] val x = foo(<bold>fun(n: Int): Int { return n }</bold>)
3 [LAMBDA CALLS] fun foo(<bold>f: (Int) -> Int</bold>): Int {
4 return f(<bold>1</bold>)
@@ -0,0 +1,11 @@
// FLOW: IN
fun foo(f: (Int) -> Unit) {
f(1)
}
fun test() {
foo(fun(value: Int) {
val <caret>v = value
})
}
@@ -0,0 +1,8 @@
4 f(<bold>1</bold>)
9 val <bold>v = value</bold>
9 val v = <bold>value</bold>
8 foo(fun(<bold>value: Int</bold>) {
8 [LAMBDA CALLS] foo(<bold>fun(value: Int) {</bold>
3 [LAMBDA CALLS] fun foo(<bold>f: (Int) -> Unit</bold>) {
4 f(<bold>1</bold>)
@@ -0,0 +1,3 @@
[NotNull Values]
9 val <bold>v = value</bold>
9 val <bold>v = value</bold>
@@ -0,0 +1,6 @@
9 val <bold>v = value</bold>
9 val v = <bold>value</bold>
8 foo(fun(<bold>value: Int</bold>) {
8 [LAMBDA CALLS] foo(<bold>fun(value: Int) {</bold>
3 [LAMBDA CALLS] fun foo(<bold>f: (Int) -> Unit</bold>) {
4 f(<bold>1</bold>)
@@ -38,6 +38,11 @@ public class SlicerLeafGroupingTestGenerated extends AbstractSlicerLeafGroupingT
runTest("idea/testData/slicer/inflow/anonymousFunBodyExpression.kt");
}
@TestMetadata("anonymousFunctionParameter.kt")
public void testAnonymousFunctionParameter() throws Exception {
runTest("idea/testData/slicer/inflow/anonymousFunctionParameter.kt");
}
@TestMetadata("anonymousFunReturnExpression.kt")
public void testAnonymousFunReturnExpression() throws Exception {
runTest("idea/testData/slicer/inflow/anonymousFunReturnExpression.kt");
@@ -38,6 +38,11 @@ public class SlicerNullnessGroupingTestGenerated extends AbstractSlicerNullnessG
runTest("idea/testData/slicer/inflow/anonymousFunBodyExpression.kt");
}
@TestMetadata("anonymousFunctionParameter.kt")
public void testAnonymousFunctionParameter() throws Exception {
runTest("idea/testData/slicer/inflow/anonymousFunctionParameter.kt");
}
@TestMetadata("anonymousFunReturnExpression.kt")
public void testAnonymousFunReturnExpression() throws Exception {
runTest("idea/testData/slicer/inflow/anonymousFunReturnExpression.kt");
@@ -55,6 +55,11 @@ public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest {
runTest("idea/testData/slicer/inflow/anonymousFunReturnExpression.kt");
}
@TestMetadata("anonymousFunctionParameter.kt")
public void testAnonymousFunctionParameter() throws Exception {
runTest("idea/testData/slicer/inflow/anonymousFunctionParameter.kt");
}
@TestMetadata("cast.kt")
public void testCast() throws Exception {
runTest("idea/testData/slicer/inflow/cast.kt");