KT-38003 "Analyze Data Flow from Here" should work on parameter of abstract method
#KT-38003 Fixed
This commit is contained in:
+1
-1
@@ -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>)
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user