Analyze Data Flow: Respect member hierarchies

#KT-11994 In Progress
This commit is contained in:
Alexey Sedunov
2017-05-31 21:35:55 +03:00
parent 49da81f681
commit ff5a52b445
32 changed files with 546 additions and 46 deletions
@@ -60,7 +60,7 @@ object KotlinPsiMethodOverridersSearch : HierarchySearch<PsiMethod>(PsiMethodOve
val psiClass = psiMethod.containingClass
if (psiClass == null) return Collections.emptyList()
val classToMethod = HashMap<PsiClass, PsiMethod>()
val classToMethod = LinkedHashMap<PsiClass, PsiMethod>()
val classTraverser = object : HierarchyTraverser<PsiClass> {
override fun nextElements(current: PsiClass): Iterable<PsiClass> =
DirectClassInheritorsSearch.search(
@@ -20,7 +20,7 @@ import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.psi.KtDeclaration
fun KtDeclaration.processAllUsages(
fun KtDeclaration.processAllExactUsages(
options: () -> FindUsagesOptions,
processor: (UsageInfo) -> Unit
) {
@@ -28,7 +28,9 @@ fun KtDeclaration.processAllUsages(
findUsagesHandler.processElementUsages(
this,
{
processor(it)
if (it.reference?.isReferenceTo(this) ?: false) {
processor(it)
}
true
},
options()
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.slicer
import com.intellij.analysis.AnalysisScope
import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector.Access
import com.intellij.psi.PsiElement
import com.intellij.psi.search.LocalSearchScope
@@ -23,6 +24,7 @@ import com.intellij.psi.search.SearchScope
import com.intellij.slicer.SliceUsage
import com.intellij.usageView.UsageInfo
import com.intellij.util.Processor
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
@@ -33,6 +35,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ReturnValueInstruction
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.traverse
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
@@ -41,14 +44,17 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.KotlinPropertyFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.processAllUsages
import org.jetbrains.kotlin.idea.findUsages.processAllExactUsages
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar
import org.jetbrains.kotlin.idea.refactoring.changeSignature.toValVar
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReadWriteAccessDetector
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
@@ -56,8 +62,25 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.source.getPsi
import java.util.*
private fun KtDeclaration.processHierarchyDownward(scope: SearchScope, processor: KtDeclaration.() -> Unit) {
processor()
HierarchySearchRequest(this, scope).searchOverriders().forEach {
(it.namedUnwrappedElement as? KtDeclaration)?.processor()
}
}
private fun KtDeclaration.processHierarchyUpward(scope: AnalysisScope, processor: KtDeclaration.() -> Unit) {
processor()
val descriptor = resolveToDescriptor() as? CallableMemberDescriptor ?: return
DescriptorUtils
.getAllOverriddenDescriptors(descriptor)
.mapNotNull { it.source.getPsi() as? KtDeclaration }
.filter { scope.contains(it) }
.forEach(processor)
}
private fun KtFunction.processCalls(scope: SearchScope, processor: (UsageInfo) -> Unit) {
processAllUsages(
processAllExactUsages(
{
KotlinFunctionFindUsagesOptions(project).apply {
isSearchForTextOccurrences = false
@@ -74,7 +97,7 @@ private fun KtDeclaration.processVariableAccesses(
kind: Access,
processor: (UsageInfo) -> Unit
) {
processAllUsages(
processAllExactUsages(
{
KotlinPropertyFindUsagesOptions(project).apply {
isReadAccess = kind == Access.Read || kind == Access.ReadWrite
@@ -126,6 +149,10 @@ class InflowSlicer(
processor: Processor<SliceUsage>,
parentUsage: KotlinSliceUsage
) : Slicer(element, processor, parentUsage) {
private fun KtDeclaration.processHierarchyDownwardAndPass() {
processHierarchyDownward(parentUsage.scope.toSearchScope()) { passToProcessor() }
}
private fun PsiElement.passToProcessorAsValue(lambdaLevel: Int = parentUsage.lambdaLevel) = passToProcessor(lambdaLevel, true)
private fun KtDeclaration.processAssignments(accessSearchScope: SearchScope) {
@@ -148,7 +175,8 @@ class InflowSlicer(
private fun KtProperty.processPropertyAssignments() {
val analysisScope = parentUsage.scope.toSearchScope()
val accessSearchScope = if (isVar) analysisScope else {
val accessSearchScope = if (isVar) analysisScope
else {
val containerScope = getStrictParentOfType<KtDeclaration>()?.let { LocalSearchScope(it) } ?: return
analysisScope.intersectWith(containerScope)
}
@@ -238,10 +266,10 @@ class InflowSlicer(
private fun KtExpression.processExpression() {
val lambda = when (this) {
is KtLambdaExpression -> functionLiteral
is KtNamedFunction -> if (name == null) this else null
else -> null
}
is KtLambdaExpression -> functionLiteral
is KtNamedFunction -> if (name == null) this else null
else -> null
}
if (lambda != null) {
if (parentUsage.lambdaLevel > 0) {
lambda.passToProcessor(parentUsage.lambdaLevel - 1)
@@ -273,7 +301,7 @@ class InflowSlicer(
}
return
}
accessedDeclaration.passToProcessor()
accessedDeclaration.processHierarchyDownwardAndPass()
}
is MergeInstruction -> createdAt.passInputsToProcessor()
@@ -296,7 +324,7 @@ class InflowSlicer(
(resolvedCall.dispatchReceiver as? ExpressionReceiver)?.expression?.passToProcessorAsValue(parentUsage.lambdaLevel + 1)
}
else {
resultingDescriptor.source.getPsi()?.passToProcessor()
(resultingDescriptor.source.getPsi() as? KtDeclaration)?.processHierarchyDownwardAndPass()
}
}
}
@@ -320,19 +348,18 @@ class OutflowSlicer(
parentUsage: KotlinSliceUsage
) : Slicer(element, processor, parentUsage) {
private fun KtDeclaration.processVariable() {
if (this is KtParameter && !canProcess()) return
processHierarchyUpward(parentUsage.scope) {
if (this is KtParameter && !canProcess()) return@processHierarchyUpward
val withDereferences = parentUsage.params.showInstanceDereferences
processVariableAccesses(
parentUsage.scope.toSearchScope(),
if (withDereferences) Access.ReadWrite else Access.Read
) body@ {
val refExpression = (it.element as? KtExpression)?.let { KtPsiUtil.safeDeparenthesize(it) } ?: return@body
if (withDereferences) {
refExpression.processDereferences()
}
if (!withDereferences || KotlinReadWriteAccessDetector.INSTANCE.getExpressionAccess(refExpression) == Access.Read) {
refExpression.processExpression()
val withDereferences = parentUsage.params.showInstanceDereferences
processVariableAccesses(parentUsage.scope.toSearchScope(), if (withDereferences) Access.ReadWrite else Access.Read) body@ {
val refExpression = (it.element as? KtExpression)?.let { KtPsiUtil.safeDeparenthesize(it) } ?: return@body
if (withDereferences) {
refExpression.processDereferences()
}
if (!withDereferences || KotlinReadWriteAccessDetector.INSTANCE.getExpressionAccess(refExpression) == Access.Read) {
refExpression.processExpression()
}
}
}
}
@@ -357,17 +384,20 @@ class OutflowSlicer(
private fun KtFunction.processFunction() {
if (this is KtConstructor<*> || this is KtNamedFunction && name != null) {
processCalls(parentUsage.scope.toSearchScope()) {
it.element?.getCallElementForExactCallee()?.passToProcessor()
it.element?.getCallableReferenceForExactCallee()?.passToProcessor(parentUsage.lambdaLevel + 1)
processHierarchyUpward(parentUsage.scope) {
(this as? KtFunction)?.processCalls(parentUsage.scope.toSearchScope()) {
it.element?.getCallElementForExactCallee()?.passToProcessor()
it.element?.getCallableReferenceForExactCallee()?.passToProcessor(parentUsage.lambdaLevel + 1)
}
}
return
}
val funExpression = when (this) {
is KtFunctionLiteral -> parent as? KtLambdaExpression
is KtNamedFunction -> this
else -> null
} ?: return
is KtFunctionLiteral -> parent as? KtLambdaExpression
is KtNamedFunction -> this
else -> null
} ?: return
(funExpression as PsiElement).passToProcessor(parentUsage.lambdaLevel + 1, true)
}
@@ -380,10 +410,10 @@ class OutflowSlicer(
val receiver = instr.receiverValues[pseudoValue]
val resolvedCall = when (instr) {
is CallInstruction -> instr.resolvedCall
is ReadValueInstruction -> (instr.target as? AccessTarget.Call)?.resolvedCall
else -> null
} ?: return
is CallInstruction -> instr.resolvedCall
is ReadValueInstruction -> (instr.target as? AccessTarget.Call)?.resolvedCall
else -> null
} ?: return
if (receiver != null && resolvedCall.dispatchReceiver == receiver) {
processor.process(KotlinSliceDereferenceUsage(expression, parentUsage, parentUsage.lambdaLevel))
@@ -420,7 +450,7 @@ class OutflowSlicer(
is ReturnValueInstruction -> instr.subroutine.passToProcessor()
is MagicInstruction -> when (instr.kind) {
MagicKind.NOT_NULL_ASSERTION, MagicKind.CAST -> instr.outputValue.element?.passToProcessor()
else -> {}
else -> { }
}
}
}
@@ -0,0 +1,24 @@
// FLOW: IN
interface A {
fun foo() = 1
}
open class B : A {
override fun foo() = 2
}
interface C : A {
override fun foo() = 3
}
class D : B(), C {
override fun foo() = 4
}
fun test(a: A, b: B, c: C, d: D) {
val x = a.foo()
val <caret>y = b.foo()
val z = c.foo()
val u = d.foo()
}
@@ -0,0 +1,6 @@
21 val <bold>y = b.foo()</bold>
21 val y = <bold>b.foo()</bold>
8 override fun <bold>foo() = 2</bold>
8 override fun foo() = <bold>2</bold>
16 override fun <bold>foo() = 4</bold>
16 override fun foo() = <bold>4</bold>
@@ -0,0 +1,24 @@
// FLOW: IN
interface A {
fun foo() = 1
}
open class B : A {
override fun foo() = 2
}
interface C : A {
override fun foo() = 3
}
class D : B(), C {
override fun foo() = 4
}
fun test(a: A, b: B, c: C, d: D) {
val x = a.foo()
val y = b.foo()
val <caret>z = c.foo()
val u = d.foo()
}
@@ -0,0 +1,6 @@
22 val <bold>z = c.foo()</bold>
22 val z = <bold>c.foo()</bold>
12 override fun <bold>foo() = 3</bold>
12 override fun foo() = <bold>3</bold>
16 override fun <bold>foo() = 4</bold>
16 override fun foo() = <bold>4</bold>
@@ -0,0 +1,24 @@
// FLOW: IN
interface A {
fun foo() = 1
}
open class B : A {
override fun foo() = 2
}
interface C : A {
override fun foo() = 3
}
class D : B(), C {
override fun foo() = 4
}
fun test(a: A, b: B, c: C, d: D) {
val <caret>x = a.foo()
val y = b.foo()
val z = c.foo()
val u = d.foo()
}
@@ -0,0 +1,10 @@
20 val <bold>x = a.foo()</bold>
20 val x = <bold>a.foo()</bold>
4 fun <bold>foo() = 1</bold>
4 fun foo() = <bold>1</bold>
8 override fun <bold>foo() = 2</bold>
8 override fun foo() = <bold>2</bold>
12 override fun <bold>foo() = 3</bold>
12 override fun foo() = <bold>3</bold>
16 override fun <bold>foo() = 4</bold>
16 override fun foo() = <bold>4</bold>
+19
View File
@@ -0,0 +1,19 @@
// FLOW: IN
open class A {
open fun foo() = 1
}
open class B : A() {
override fun foo() = 2
}
class C : B() {
override fun foo() = 3
}
fun test(a: A, b: B, c: C) {
val x = a.foo()
val <caret>y = b.foo()
val z = c.foo()
}
@@ -0,0 +1,6 @@
17 val <bold>y = b.foo()</bold>
17 val y = <bold>b.foo()</bold>
8 override fun <bold>foo() = 2</bold>
8 override fun foo() = <bold>2</bold>
12 override fun <bold>foo() = 3</bold>
12 override fun foo() = <bold>3</bold>
+17
View File
@@ -0,0 +1,17 @@
// FLOW: IN
open class A {
open val foo = 1
}
open class B(override val foo: Int) : A()
class C : B() {
override val foo = 3
}
fun test(a: A, b: B, c: C) {
val x = a.foo
val <caret>y = b.foo
val z = c.foo
}
@@ -0,0 +1,5 @@
15 val <bold>y = b.foo</bold>
15 val y = <bold>b.foo</bold>
7 open class B(override val <bold>foo: Int</bold>) : A()
10 override val <bold>foo = 3</bold>
10 override val foo = <bold>3</bold>
@@ -0,0 +1,22 @@
// FLOW: IN
open class A {
open val foo: Int
get() = 1
}
open class B : A() {
override val foo: Int
get() = 2
}
class C : B() {
override val foo: Int
get() = 3
}
fun test(a: A, b: B, c: C) {
val x = a.foo
val <caret>y = b.foo
val z = c.foo
}
@@ -0,0 +1,6 @@
20 val <bold>y = b.foo</bold>
20 val y = <bold>b.foo</bold>
9 override val <bold>foo: Int</bold>
10 get() = <bold>2</bold>
14 override val <bold>foo: Int</bold>
15 get() = <bold>3</bold>
+19
View File
@@ -0,0 +1,19 @@
// FLOW: IN
open class A {
open val foo = 1
}
open class B : A() {
override val foo = 2
}
class C : B() {
override val foo = 3
}
fun test(a: A, b: B, c: C) {
val x = a.foo
val <caret>y = b.foo
val z = c.foo
}
@@ -0,0 +1,6 @@
17 val <bold>y = b.foo</bold>
17 val y = <bold>b.foo</bold>
8 override val <bold>foo = 2</bold>
8 override val foo = <bold>2</bold>
12 override val <bold>foo = 3</bold>
12 override val foo = <bold>3</bold>
@@ -0,0 +1,24 @@
// FLOW: OUT
interface A {
fun foo() = 1
}
open class B : A {
override fun foo() = 2
}
interface C : A {
override fun foo() = 3
}
class D : B(), C {
override fun foo() = <caret>4
}
fun test(a: A, b: B, c: C, d: D) {
val x = a.foo()
val y = b.foo()
val z = c.foo()
val u = d.foo()
}
@@ -0,0 +1,10 @@
16 override fun foo() = <bold>4</bold>
16 override fun <bold>foo() = 4</bold>
23 val u = d.<bold>foo()</bold>
23 val <bold>u = d.foo()</bold>
20 val x = a.<bold>foo()</bold>
20 val <bold>x = a.foo()</bold>
21 val y = b.<bold>foo()</bold>
21 val <bold>y = b.foo()</bold>
22 val z = c.<bold>foo()</bold>
22 val <bold>z = c.foo()</bold>
@@ -0,0 +1,24 @@
// FLOW: OUT
interface A {
fun foo() = 1
}
open class B : A {
override fun foo() = <caret>2
}
interface C : A {
override fun foo() = 3
}
class D : B(), C {
override fun foo() = 4
}
fun test(a: A, b: B, c: C, d: D) {
val x = a.foo()
val y = b.foo()
val z = c.foo()
val u = d.foo()
}
@@ -0,0 +1,6 @@
8 override fun foo() = <bold>2</bold>
8 override fun <bold>foo() = 2</bold>
21 val y = b.<bold>foo()</bold>
21 val <bold>y = b.foo()</bold>
20 val x = a.<bold>foo()</bold>
20 val <bold>x = a.foo()</bold>
@@ -0,0 +1,24 @@
// FLOW: OUT
interface A {
fun foo() = 1
}
open class B : A {
override fun foo() = 2
}
interface C : A {
override fun foo() = <caret>3
}
class D : B(), C {
override fun foo() = 4
}
fun test(a: A, b: B, c: C, d: D) {
val x = a.foo()
val y = b.foo()
val z = c.foo()
val u = d.foo()
}
@@ -0,0 +1,6 @@
12 override fun foo() = <bold>3</bold>
12 override fun <bold>foo() = 3</bold>
22 val z = c.<bold>foo()</bold>
22 val <bold>z = c.foo()</bold>
20 val x = a.<bold>foo()</bold>
20 val <bold>x = a.foo()</bold>
@@ -0,0 +1,19 @@
// FLOW: OUT
open class A {
open fun foo() = 1
}
open class B : A() {
override fun foo() = <caret>2
}
class C : B() {
override fun foo() = 3
}
fun test(a: A, b: B, c: C) {
val x = a.foo()
val y = b.foo()
val z = c.foo()
}
@@ -0,0 +1,6 @@
8 override fun foo() = <bold>2</bold>
8 override fun <bold>foo() = 2</bold>
17 val y = b.<bold>foo()</bold>
17 val <bold>y = b.foo()</bold>
16 val x = a.<bold>foo()</bold>
16 val <bold>x = a.foo()</bold>
+17
View File
@@ -0,0 +1,17 @@
// FLOW: OUT
open class A() {
open val foo = 1
}
open class B(override val foo: Int) : A()
class C : B() {
override val foo = <caret>3
}
fun test(a: A, b: B, c: C) {
val x = a.foo
val y = b.foo
val z = c.foo
}
@@ -0,0 +1,5 @@
10 override val foo = <bold>3</bold>
10 override val <bold>foo = 3</bold>
16 val <bold>z = c.foo</bold>
14 val <bold>x = a.foo</bold>
15 val <bold>y = b.foo</bold>
@@ -0,0 +1,22 @@
// FLOW: OUT
open class A {
open val foo: Int
get() = 1
}
open class B : A() {
override val foo: Int
get() = <caret>2
}
class C : B() {
override val foo: Int
get() = 3
}
fun test(a: A, b: B, c: C) {
val x = a.foo
val y = b.foo
val z = c.foo
}
@@ -0,0 +1,4 @@
10 get() = <bold>2</bold>
10 <bold>get() = 2</bold>
20 val <bold>y = b.foo</bold>
19 val <bold>x = a.foo</bold>
@@ -0,0 +1,19 @@
// FLOW: OUT
open class A {
open val foo = 1
}
open class B : A() {
override val foo = <caret>2
}
class C : B() {
override val foo = 3
}
fun test(a: A, b: B, c: C) {
val x = a.foo
val y = b.foo
val z = c.foo
}
@@ -0,0 +1,4 @@
8 override val foo = <bold>2</bold>
8 override val <bold>foo = 2</bold>
17 val <bold>y = b.foo</bold>
16 val <bold>x = a.foo</bold>
@@ -66,6 +66,24 @@ public class SlicerTestGenerated extends AbstractSlicerTest {
doTest(fileName);
}
@TestMetadata("inflow/diamondHierarchyMiddleClassFun.kt")
public void testInflow_DiamondHierarchyMiddleClassFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/diamondHierarchyMiddleClassFun.kt");
doTest(fileName);
}
@TestMetadata("inflow/diamondHierarchyMiddleInterfaceFun.kt")
public void testInflow_DiamondHierarchyMiddleInterfaceFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/diamondHierarchyMiddleInterfaceFun.kt");
doTest(fileName);
}
@TestMetadata("inflow/diamondHierarchyRootInterfaceFun.kt")
public void testInflow_DiamondHierarchyRootInterfaceFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/diamondHierarchyRootInterfaceFun.kt");
doTest(fileName);
}
@TestMetadata("inflow/doubleLambdaResult.kt")
public void testInflow_DoubleLambdaResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/doubleLambdaResult.kt");
@@ -216,6 +234,30 @@ public class SlicerTestGenerated extends AbstractSlicerTest {
doTest(fileName);
}
@TestMetadata("inflow/overridingFunctionResult.kt")
public void testInflow_OverridingFunctionResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingFunctionResult.kt");
doTest(fileName);
}
@TestMetadata("inflow/overridingParameter.kt")
public void testInflow_OverridingParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingParameter.kt");
doTest(fileName);
}
@TestMetadata("inflow/overridingPropertyGetterResult.kt")
public void testInflow_OverridingPropertyGetterResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingPropertyGetterResult.kt");
doTest(fileName);
}
@TestMetadata("inflow/overridingPropertyResult.kt")
public void testInflow_OverridingPropertyResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingPropertyResult.kt");
doTest(fileName);
}
@TestMetadata("inflow/primaryConstructorParameter.kt")
public void testInflow_PrimaryConstructorParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/primaryConstructorParameter.kt");
@@ -300,6 +342,24 @@ public class SlicerTestGenerated extends AbstractSlicerTest {
doTest(fileName);
}
@TestMetadata("outflow/diamondHierarchyLeafClassFun.kt")
public void testOutflow_DiamondHierarchyLeafClassFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/diamondHierarchyLeafClassFun.kt");
doTest(fileName);
}
@TestMetadata("outflow/diamondHierarchyMiddleClassFun.kt")
public void testOutflow_DiamondHierarchyMiddleClassFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/diamondHierarchyMiddleClassFun.kt");
doTest(fileName);
}
@TestMetadata("outflow/diamondHierarchyMiddleInterfaceFun.kt")
public void testOutflow_DiamondHierarchyMiddleInterfaceFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/diamondHierarchyMiddleInterfaceFun.kt");
doTest(fileName);
}
@TestMetadata("outflow/doubleLambdaResult.kt")
public void testOutflow_DoubleLambdaResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/doubleLambdaResult.kt");
@@ -360,6 +420,12 @@ public class SlicerTestGenerated extends AbstractSlicerTest {
doTest(fileName);
}
@TestMetadata("outflow/getFunCalls.kt")
public void testOutflow_GetFunCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/getFunCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/getterExpressionBody.kt")
public void testOutflow_GetterExpressionBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/getterExpressionBody.kt");
@@ -372,12 +438,6 @@ public class SlicerTestGenerated extends AbstractSlicerTest {
doTest(fileName);
}
@TestMetadata("outflow/getFunCalls.kt")
public void testOutflow_GetFunCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/getFunCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/ifExpression.kt")
public void testOutflow_IfExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/ifExpression.kt");
@@ -438,15 +498,39 @@ public class SlicerTestGenerated extends AbstractSlicerTest {
doTest(fileName);
}
@TestMetadata("outflow/operatorCallDereferences.kt")
public void testOutflow_OperatorCallDereferences() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/operatorCallDereferences.kt");
doTest(fileName);
}
@TestMetadata("outflow/operatorFunCalls.kt")
public void testOutflow_OperatorFunCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/operatorFunCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/operatorCallDereferences.kt")
public void testOutflow_OperatorCallDereferences() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/operatorCallDereferences.kt");
@TestMetadata("outflow/overridingFunctionResult.kt")
public void testOutflow_OverridingFunctionResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/overridingFunctionResult.kt");
doTest(fileName);
}
@TestMetadata("outflow/overridingParameter.kt")
public void testOutflow_OverridingParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/overridingParameter.kt");
doTest(fileName);
}
@TestMetadata("outflow/overridingPropertyGetterResult.kt")
public void testOutflow_OverridingPropertyGetterResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/overridingPropertyGetterResult.kt");
doTest(fileName);
}
@TestMetadata("outflow/overridingPropertyResult.kt")
public void testOutflow_OverridingPropertyResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/overridingPropertyResult.kt");
doTest(fileName);
}