KT-38003 "Analyze Data Flow from Here" should work on parameter of abstract method

#KT-38003 Fixed
This commit is contained in:
Valentin Kipyatkov
2020-04-08 14:08:24 +03:00
parent 612629f3cb
commit 2b83e3721a
9 changed files with 86 additions and 3 deletions
@@ -153,7 +153,7 @@ private fun forEachKotlinOverride(
fun KtNamedDeclaration.forEachOverridingElement(
scope: SearchScope = runReadAction { useScope },
processor: (PsiElement, PsiElement) -> Boolean
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
): Boolean {
val ktClass = runReadAction { containingClassOrObject as? KtClass } ?: return true
@@ -14,11 +14,13 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ReturnValueInstruction
import org.jetbrains.kotlin.idea.findUsages.handlers.SliceUsageProcessor
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingElement
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReadWriteAccessDetector
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
import org.jetbrains.kotlin.resolve.source.getPsi
class OutflowSlicer(
@@ -40,8 +42,6 @@ class OutflowSlicer(
}
private fun processVariable(variable: KtCallableDeclaration) {
if (variable is KtParameter && !canProcessParameter(variable)) return
val withDereferences = parentUsage.params.showInstanceDereferences
val accessKind = if (withDereferences) AccessKind.READ_OR_WRITE else AccessKind.READ_ONLY
@@ -61,6 +61,24 @@ class OutflowSlicer(
}
}
if (variable is KtParameter) {
if (!canProcessParameter(variable)) return //TODO
//TODO: expect/actual
val callable = variable.ownerFunction as? KtCallableDeclaration
callable?.forEachOverridingElement(scope = analysisScope) { _, overridingMember ->
//TODO: Java overriders
if (overridingMember is KtCallableDeclaration) {
val parameters = overridingMember.valueParameters
check(parameters.size == callable.valueParameters.size)
val overridingParameter = parameters[variable.parameterIndex()]
overridingParameter.passToProcessor()
}
true
}
}
processVariableAccesses(variable, analysisScope, accessKind, ::processVariableAccess)
}
@@ -0,0 +1,11 @@
// FLOW: OUT
interface I {
fun foo(<caret>p: Any)
}
class C : I {
override fun foo(p: Any) {
println(p)
}
}
@@ -0,0 +1,3 @@
4 fun foo(<bold>p: Any</bold>)
8 override fun foo(<bold>p: Any</bold>) {
9 println(<bold>p</bold>)
@@ -0,0 +1,15 @@
// FLOW: OUT
interface I {
fun foo(p: Any)
}
class C : I {
override fun foo(p: Any) {
println(p)
}
}
fun bar(i: I, s: String) {
i.foo(<caret>s)
}
@@ -0,0 +1,4 @@
14 i.foo(<bold>s</bold>)
4 fun foo(<bold>p: Any</bold>)
8 override fun foo(<bold>p: Any</bold>) {
9 println(<bold>p</bold>)
+13
View File
@@ -0,0 +1,13 @@
// FLOW: OUT
open class C {
open fun foo(<caret>p: Any) {
println(p)
}
}
class D : C() {
override fun foo(p: Any) {
println(p + 1)
}
}
@@ -0,0 +1,4 @@
4 open fun foo(<bold>p: Any</bold>) {
5 println(<bold>p</bold>)
10 override fun foo(<bold>p: Any</bold>) {
11 println(<bold>p</bold> + 1)
@@ -348,6 +348,16 @@ public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest {
runTest("idea/testData/slicer/inflow/whenExpression.kt");
}
@TestMetadata("outflow/abstractMethodParameter1.kt")
public void testOutflow_AbstractMethodParameter1() throws Exception {
runTest("idea/testData/slicer/outflow/abstractMethodParameter1.kt");
}
@TestMetadata("outflow/abstractMethodParameter2.kt")
public void testOutflow_AbstractMethodParameter2() throws Exception {
runTest("idea/testData/slicer/outflow/abstractMethodParameter2.kt");
}
@TestMetadata("outflow/anonymousFunBodyExpression.kt")
public void testOutflow_AnonymousFunBodyExpression() throws Exception {
runTest("idea/testData/slicer/outflow/anonymousFunBodyExpression.kt");
@@ -533,6 +543,11 @@ public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest {
runTest("idea/testData/slicer/outflow/notNullAssertion.kt");
}
@TestMetadata("outflow/openMethodParameter.kt")
public void testOutflow_OpenMethodParameter() throws Exception {
runTest("idea/testData/slicer/outflow/openMethodParameter.kt");
}
@TestMetadata("outflow/operatorCallDereferences.kt")
public void testOutflow_OperatorCallDereferences() throws Exception {
runTest("idea/testData/slicer/outflow/operatorCallDereferences.kt");