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(
|
fun KtNamedDeclaration.forEachOverridingElement(
|
||||||
scope: SearchScope = runReadAction { useScope },
|
scope: SearchScope = runReadAction { useScope },
|
||||||
processor: (PsiElement, PsiElement) -> Boolean
|
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val ktClass = runReadAction { containingClassOrObject as? KtClass } ?: return true
|
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.eval.*
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ReturnValueInstruction
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ReturnValueInstruction
|
||||||
import org.jetbrains.kotlin.idea.findUsages.handlers.SliceUsageProcessor
|
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.idea.search.ideaExtensions.KotlinReadWriteAccessDetector
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
|
||||||
class OutflowSlicer(
|
class OutflowSlicer(
|
||||||
@@ -40,8 +42,6 @@ class OutflowSlicer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processVariable(variable: KtCallableDeclaration) {
|
private fun processVariable(variable: KtCallableDeclaration) {
|
||||||
if (variable is KtParameter && !canProcessParameter(variable)) return
|
|
||||||
|
|
||||||
val withDereferences = parentUsage.params.showInstanceDereferences
|
val withDereferences = parentUsage.params.showInstanceDereferences
|
||||||
val accessKind = if (withDereferences) AccessKind.READ_OR_WRITE else AccessKind.READ_ONLY
|
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)
|
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");
|
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")
|
@TestMetadata("outflow/anonymousFunBodyExpression.kt")
|
||||||
public void testOutflow_AnonymousFunBodyExpression() throws Exception {
|
public void testOutflow_AnonymousFunBodyExpression() throws Exception {
|
||||||
runTest("idea/testData/slicer/outflow/anonymousFunBodyExpression.kt");
|
runTest("idea/testData/slicer/outflow/anonymousFunBodyExpression.kt");
|
||||||
@@ -533,6 +543,11 @@ public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest {
|
|||||||
runTest("idea/testData/slicer/outflow/notNullAssertion.kt");
|
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")
|
@TestMetadata("outflow/operatorCallDereferences.kt")
|
||||||
public void testOutflow_OperatorCallDereferences() throws Exception {
|
public void testOutflow_OperatorCallDereferences() throws Exception {
|
||||||
runTest("idea/testData/slicer/outflow/operatorCallDereferences.kt");
|
runTest("idea/testData/slicer/outflow/operatorCallDereferences.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user