Data Inflow: Support grouping by leaf expressions
This commit is contained in:
committed by
Nikolay Krasko
parent
b46784ab86
commit
683bbe396d
@@ -132,7 +132,8 @@ import org.jetbrains.kotlin.idea.resolve.*
|
||||
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationCompletionTest
|
||||
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationHighlightingTest
|
||||
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationNavigationTest
|
||||
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerTest
|
||||
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerLeafGroupingTest
|
||||
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerTreeTest
|
||||
import org.jetbrains.kotlin.idea.structureView.AbstractKotlinFileStructureTest
|
||||
import org.jetbrains.kotlin.idea.stubs.AbstractMultiFileHighlightingTest
|
||||
import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest
|
||||
@@ -719,9 +720,13 @@ fun main(args: Array<String>) {
|
||||
model("refactoring/nameSuggestionProvider")
|
||||
}
|
||||
|
||||
testClass<AbstractSlicerTest> {
|
||||
testClass<AbstractSlicerTreeTest> {
|
||||
model("slicer", singleClass = true)
|
||||
}
|
||||
|
||||
testClass<AbstractSlicerLeafGroupingTest> {
|
||||
model("slicer/inflow", singleClass = true)
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/idea-maven/test", "idea/idea-maven/testData") {
|
||||
|
||||
@@ -19,15 +19,22 @@ package org.jetbrains.kotlin.idea.slicer
|
||||
import com.intellij.ide.util.treeView.AbstractTreeStructure
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.slicer.SliceAnalysisParams
|
||||
import com.intellij.slicer.SliceLanguageSupportProvider
|
||||
import com.intellij.slicer.SliceTreeBuilder
|
||||
import com.intellij.slicer.*
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPlainWithEscapes
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
|
||||
class KotlinSliceProvider : SliceLanguageSupportProvider {
|
||||
companion object {
|
||||
val LEAF_ELEMENT_EQUALITY = object : SliceLeafEquality() {
|
||||
override fun substituteElement(element: PsiElement) = (element as? KtReference)?.resolve() ?: element
|
||||
}
|
||||
}
|
||||
|
||||
val leafAnalyzer by lazy { SliceLeafAnalyzer(LEAF_ELEMENT_EQUALITY, this) }
|
||||
|
||||
override fun createRootUsage(element: PsiElement, params: SliceAnalysisParams) = KotlinSliceUsage(element, params)
|
||||
|
||||
override fun getExpressionAtCaret(atCaret: PsiElement?, dataFlowToThis: Boolean): KtExpression? {
|
||||
@@ -56,7 +63,7 @@ class KotlinSliceProvider : SliceLanguageSupportProvider {
|
||||
override fun getRenderer() = KotlinSliceUsageCellRenderer
|
||||
|
||||
override fun startAnalyzeLeafValues(structure: AbstractTreeStructure, finalRunnable: Runnable) {
|
||||
|
||||
leafAnalyzer.startAnalyzeValues(structure, finalRunnable)
|
||||
}
|
||||
|
||||
override fun startAnalyzeNullness(structure: AbstractTreeStructure, finalRunnable: Runnable) {
|
||||
@@ -64,6 +71,8 @@ class KotlinSliceProvider : SliceLanguageSupportProvider {
|
||||
}
|
||||
|
||||
override fun registerExtraPanelActions(group: DefaultActionGroup, builder: SliceTreeBuilder) {
|
||||
|
||||
if (builder.dataFlowToThis) {
|
||||
group.add(GroupByLeavesAction(builder))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,13 @@ package org.jetbrains.kotlin.idea.slicer
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.slicer.SliceAnalysisParams
|
||||
import com.intellij.slicer.SliceUsage
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
|
||||
open class KotlinSliceUsage : SliceUsage {
|
||||
class UsageInfoLambdaWrapper(element: PsiElement) : UsageInfo(element)
|
||||
|
||||
val lambdaLevel: Int
|
||||
val forcedExpressionMode: Boolean
|
||||
|
||||
@@ -42,6 +45,18 @@ open class KotlinSliceUsage : SliceUsage {
|
||||
return KotlinSliceUsage(element, parent, lambdaLevel, forcedExpressionMode)
|
||||
}
|
||||
|
||||
override fun getUsageInfo(): UsageInfo {
|
||||
val originalInfo = super.getUsageInfo()
|
||||
if (lambdaLevel > 0 && forcedExpressionMode) {
|
||||
val element = originalInfo.element ?: return originalInfo
|
||||
// Do not let IDEA consider usages of the same anonymous function as duplicates when their levels differ
|
||||
return UsageInfoLambdaWrapper(element)
|
||||
}
|
||||
return originalInfo
|
||||
}
|
||||
|
||||
override fun canBeLeaf() = element != null && lambdaLevel == 0
|
||||
|
||||
public override fun processUsagesFlownDownTo(element: PsiElement, uniqueProcessor: Processor<SliceUsage>) {
|
||||
InflowSlicer(element as? KtExpression ?: return, uniqueProcessor, this).processChildren()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
8 val x = foo(fun(<bold>n: Int</bold>) = n)
|
||||
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>
|
||||
4 return <bold>f(1)</bold>
|
||||
4 [LAMBDA] return <bold>f</bold>(1)
|
||||
3 [LAMBDA] fun foo(<bold>f: (Int) -> Int</bold>): Int {
|
||||
8 [LAMBDA] val x = foo(<bold>fun(n: Int) = n</bold>)
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
8 val x = foo(fun(<bold>n: Int</bold>): Int { return n })
|
||||
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>
|
||||
4 return <bold>f(1)</bold>
|
||||
4 [LAMBDA] return <bold>f</bold>(1)
|
||||
3 [LAMBDA] fun foo(<bold>f: (Int) -> Int</bold>): Int {
|
||||
8 [LAMBDA] val x = foo(<bold>fun(n: Int): Int { return n }</bold>)
|
||||
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 })
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
3 fun test(<bold>o: Any</bold>) {
|
||||
4 val <bold>x = o as String</bold>
|
||||
4 val x = <bold>o as String</bold>
|
||||
4 val x = <bold>o</bold> as String
|
||||
3 fun test(<bold>o: Any</bold>) {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
7 <bold>--result</bold>
|
||||
3 fun <bold>assignmentWithSum(n: Int): Int {</bold>
|
||||
8 return <bold>result</bold>
|
||||
4 var <bold>result = 0</bold>
|
||||
7 <bold>--result</bold>
|
||||
|
||||
4 var result = <bold>0</bold>
|
||||
3 fun <bold>assignmentWithSum(n: Int): Int {</bold>
|
||||
8 return <bold>result</bold>
|
||||
4 var <bold>result = 0</bold>
|
||||
4 var result = <bold>0</bold>
|
||||
|
||||
5 <bold>result += n</bold>
|
||||
3 fun <bold>assignmentWithSum(n: Int): Int {</bold>
|
||||
8 return <bold>result</bold>
|
||||
4 var <bold>result = 0</bold>
|
||||
5 <bold>result += n</bold>
|
||||
@@ -0,0 +1,14 @@
|
||||
6 field = if (b) value else <bold>0</bold>
|
||||
10 val x = <bold>foo</bold>
|
||||
4 var <bold>foo: Int</bold>
|
||||
6 field = <bold>if (b) value else 0</bold>
|
||||
6 field = if (b) value else <bold>0</bold>
|
||||
|
||||
11 foo = <bold>1</bold>
|
||||
10 val x = <bold>foo</bold>
|
||||
4 var <bold>foo: Int</bold>
|
||||
6 field = <bold>if (b) value else 0</bold>
|
||||
6 field = if (b) <bold>value</bold> else 0
|
||||
5 set(<bold>value</bold>) {
|
||||
11 foo = <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
6 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>1</bold>
|
||||
12 val <bold>x = foo</bold>
|
||||
12 val x = <bold>foo</bold>
|
||||
9 val <bold>foo: Int by D</bold>
|
||||
6 operator fun <bold>getValue(thisRef: Any?, property: KProperty<*>) = 1</bold>
|
||||
6 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
8 override fun foo() = <bold>2</bold>
|
||||
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 foo() = <bold>4</bold>
|
||||
21 val <bold>y = b.foo()</bold>
|
||||
21 val y = <bold>b.foo()</bold>
|
||||
16 override fun <bold>foo() = 4</bold>
|
||||
16 override fun foo() = <bold>4</bold>
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
12 override fun foo() = <bold>3</bold>
|
||||
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 foo() = <bold>4</bold>
|
||||
22 val <bold>z = c.foo()</bold>
|
||||
22 val z = <bold>c.foo()</bold>
|
||||
16 override fun <bold>foo() = 4</bold>
|
||||
16 override fun foo() = <bold>4</bold>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
4 fun foo() = <bold>1</bold>
|
||||
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 foo() = <bold>2</bold>
|
||||
20 val <bold>x = a.foo()</bold>
|
||||
20 val x = <bold>a.foo()</bold>
|
||||
8 override fun <bold>foo() = 2</bold>
|
||||
8 override fun foo() = <bold>2</bold>
|
||||
|
||||
12 override fun foo() = <bold>3</bold>
|
||||
20 val <bold>x = a.foo()</bold>
|
||||
20 val x = <bold>a.foo()</bold>
|
||||
12 override fun <bold>foo() = 3</bold>
|
||||
12 override fun foo() = <bold>3</bold>
|
||||
|
||||
16 override fun foo() = <bold>4</bold>
|
||||
20 val <bold>x = a.foo()</bold>
|
||||
20 val x = <bold>a.foo()</bold>
|
||||
16 override fun <bold>foo() = 4</bold>
|
||||
16 override fun foo() = <bold>4</bold>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
8 val x = foo(1, 2) { { <bold>it</bold> } }
|
||||
8 val <bold>x = foo(1, 2) { { it } }</bold>
|
||||
8 val x = <bold>foo(1, 2) { { it } }</bold>
|
||||
3 fun <bold>foo(a: Int, b: Int, f: (Int) -> (Int) -> Int): Int {</bold>
|
||||
4 return <bold>f(a)(b)</bold>
|
||||
4 [LAMBDA] return <bold>f(a)</bold>(b)
|
||||
4 [LAMBDA] [LAMBDA] return <bold>f</bold>(a)(b)
|
||||
3 [LAMBDA] [LAMBDA] fun foo(a: Int, b: Int, <bold>f: (Int) -> (Int) -> Int</bold>): Int {
|
||||
8 [LAMBDA] [LAMBDA] val x = foo(1, 2) <bold>{ { it } }</bold>
|
||||
8 [LAMBDA] val x = foo(1, 2) <bold>{ { it } }</bold>
|
||||
8 [LAMBDA] val x = foo(1, 2) { <bold>{ it }</bold> }
|
||||
8 val x = foo(1, 2) { <bold>{ it }</bold> }
|
||||
8 val x = foo(1, 2) { { <bold>it</bold> } }
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
8 foo(<bold>1</bold>)
|
||||
3 fun foo(<bold>n: Int</bold>, s: String = "???") {
|
||||
8 foo(<bold>1</bold>)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
9 foo(1, <bold>"2"</bold>)
|
||||
3 fun foo(n: Int, <bold>s: String = "???"</bold>) {
|
||||
9 foo(1, <bold>"2"</bold>)
|
||||
|
||||
3 fun foo(n: Int, s: String = <bold>"???"</bold>) {
|
||||
3 fun foo(n: Int, <bold>s: String = "???"</bold>) {
|
||||
3 fun foo(n: Int, s: String = <bold>"???"</bold>) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
8 fun bar(<bold>n: Int</bold>) = n
|
||||
9 val <bold>x = foo(::bar)</bold>
|
||||
9 val x = <bold>foo(::bar)</bold>
|
||||
3 fun <bold>foo(f: (Int) -> Int): Int {</bold>
|
||||
4 return <bold>f(1)</bold>
|
||||
4 [LAMBDA] return <bold>f</bold>(1)
|
||||
3 [LAMBDA] fun foo(<bold>f: (Int) -> Int</bold>): Int {
|
||||
9 [LAMBDA] val x = foo(<bold>::bar</bold>)
|
||||
8 fun <bold>bar(n: Int) = n</bold>
|
||||
8 fun bar(n: Int) = <bold>n</bold>
|
||||
8 fun bar(<bold>n: Int</bold>) = n
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
8 fun bar(<bold>n: Int</bold>) = n
|
||||
10 val <bold>x = foo(f)</bold>
|
||||
10 val x = <bold>foo(f)</bold>
|
||||
3 fun <bold>foo(f: (Int) -> Int): Int {</bold>
|
||||
4 return <bold>f(1)</bold>
|
||||
4 [LAMBDA] return <bold>f</bold>(1)
|
||||
3 [LAMBDA] fun foo(<bold>f: (Int) -> Int</bold>): Int {
|
||||
10 [LAMBDA] val x = foo(<bold>f</bold>)
|
||||
9 [LAMBDA] val <bold>f = ::bar</bold>
|
||||
9 [LAMBDA] val f = <bold>::bar</bold>
|
||||
8 fun <bold>bar(n: Int) = n</bold>
|
||||
8 fun bar(n: Int) = <bold>n</bold>
|
||||
8 fun bar(<bold>n: Int</bold>) = n
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
4 fun bar(<bold>n: Int</bold>) = n
|
||||
5 val <bold>x = (::bar)(1)</bold>
|
||||
5 val x = <bold>(::bar)(1)</bold>
|
||||
5 [LAMBDA] val x = <bold>(::bar)</bold>(1)
|
||||
4 fun <bold>bar(n: Int) = n</bold>
|
||||
4 fun bar(n: Int) = <bold>n</bold>
|
||||
4 fun bar(<bold>n: Int</bold>) = n
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
3 fun foo(n: Int) = <bold>n + 1</bold>
|
||||
3 fun <bold>foo(n: Int) = n + 1</bold>
|
||||
3 fun foo(n: Int) = <bold>n + 1</bold>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
5 return <bold>-n</bold>
|
||||
3 fun <bold>foo(n: Int): Int {</bold>
|
||||
5 return <bold>-n</bold>
|
||||
|
||||
3 fun foo(<bold>n: Int</bold>): Int {
|
||||
3 fun <bold>foo(n: Int): Int {</bold>
|
||||
4 if (n > 0) return <bold>n</bold>
|
||||
3 fun foo(<bold>n: Int</bold>): Int {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
7 field = if (b) value else <bold>0</bold>
|
||||
11 val x = <bold>foo</bold>
|
||||
4 var <bold>foo: Int</bold>
|
||||
5 get() = <bold>if (b) field else 0</bold>
|
||||
5 get() = if (b) <bold>field</bold> else 0
|
||||
7 field = <bold>if (b) value else 0</bold>
|
||||
7 field = if (b) value else <bold>0</bold>
|
||||
|
||||
12 foo = <bold>1</bold>
|
||||
11 val x = <bold>foo</bold>
|
||||
4 var <bold>foo: Int</bold>
|
||||
5 get() = <bold>if (b) field else 0</bold>
|
||||
5 get() = if (b) <bold>field</bold> else 0
|
||||
7 field = <bold>if (b) value else 0</bold>
|
||||
7 field = if (b) <bold>value</bold> else 0
|
||||
6 set(<bold>value</bold>) {
|
||||
12 foo = <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
4 get() = <bold>0</bold>
|
||||
7 val <bold>x = foo</bold>
|
||||
7 val x = <bold>foo</bold>
|
||||
3 val <bold>foo: Int</bold>
|
||||
4 get() = <bold>0</bold>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
5 return <bold>0</bold>
|
||||
9 val <bold>x = foo</bold>
|
||||
9 val x = <bold>foo</bold>
|
||||
3 val <bold>foo: Int</bold>
|
||||
5 return <bold>0</bold>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
3 fun test(m: Int, <bold>n: Int</bold>) {
|
||||
4 val <bold>x = if (m > 1) n else 1</bold>
|
||||
4 val x = <bold>if (m > 1) n else 1</bold>
|
||||
4 val x = if (m > 1) <bold>n</bold> else 1
|
||||
3 fun test(m: Int, <bold>n: Int</bold>) {
|
||||
|
||||
4 val x = if (m > 1) n else <bold>1</bold>
|
||||
4 val <bold>x = if (m > 1) n else 1</bold>
|
||||
4 val x = <bold>if (m > 1) n else 1</bold>
|
||||
4 val x = if (m > 1) n else <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
8 val x = foo { <bold>it</bold> }
|
||||
8 val <bold>x = foo { it }</bold>
|
||||
8 val x = <bold>foo { it }</bold>
|
||||
3 fun <bold>foo(f: (Int) -> Int): Int {</bold>
|
||||
4 return <bold>f(1)</bold>
|
||||
4 [LAMBDA] return <bold>f</bold>(1)
|
||||
3 [LAMBDA] fun foo(<bold>f: (Int) -> Int</bold>): Int {
|
||||
8 [LAMBDA] val x = foo <bold>{ it }</bold>
|
||||
8 val x = foo <bold>{ it }</bold>
|
||||
8 val x = foo { <bold>it</bold> }
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
9 val y = foo { <bold>it</bold> }
|
||||
9 val <bold>y = foo { it }</bold>
|
||||
9 val y = <bold>foo { it }</bold>
|
||||
3 fun <bold>foo(f: (Int) -> Int): Int {</bold>
|
||||
5 return <bold>x(1)</bold>
|
||||
5 [LAMBDA] return <bold>x</bold>(1)
|
||||
4 [LAMBDA] val <bold>x = f</bold>
|
||||
4 [LAMBDA] val x = <bold>f</bold>
|
||||
3 [LAMBDA] fun foo(<bold>f: (Int) -> Int</bold>): Int {
|
||||
9 [LAMBDA] val y = foo <bold>{ it }</bold>
|
||||
9 val y = foo <bold>{ it }</bold>
|
||||
9 val y = foo { <bold>it</bold> }
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
4 val x = { <bold>1</bold> }()
|
||||
4 val <bold>x = { 1 }()</bold>
|
||||
4 val x = <bold>{ 1 }()</bold>
|
||||
4 [LAMBDA] val x = <bold>{ 1 }</bold>()
|
||||
4 val x = <bold>{ 1 }</bold>()
|
||||
4 val x = { <bold>1</bold> }()
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
4 val f = { <bold>1</bold> }
|
||||
5 val <bold>x = f()</bold>
|
||||
5 val x = <bold>f()</bold>
|
||||
5 [LAMBDA] val x = <bold>f</bold>()
|
||||
4 [LAMBDA] val <bold>f = { 1 }</bold>
|
||||
4 [LAMBDA] val f = <bold>{ 1 }</bold>
|
||||
4 val f = <bold>{ 1 }</bold>
|
||||
4 val f = { <bold>1</bold> }
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
3 fun test(<bold>n: Int</bold>) {
|
||||
4 val <bold>x = n</bold>
|
||||
4 val x = <bold>n</bold>
|
||||
3 fun test(<bold>n: Int</bold>) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
3 fun test(<bold>n: Int</bold>) {
|
||||
4 var <bold>x = n</bold>
|
||||
4 var x = <bold>n</bold>
|
||||
3 fun test(<bold>n: Int</bold>) {
|
||||
|
||||
6 x = <bold>0</bold>
|
||||
4 var <bold>x = n</bold>
|
||||
6 x = <bold>0</bold>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
4 val x: Int = <bold>1</bold>
|
||||
4 val <bold>x: Int = 1</bold>
|
||||
4 val x: Int = <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
7 x = <bold>1</bold>
|
||||
4 val <bold>x: Int</bold>
|
||||
7 x = <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
4 var x: Int = <bold>1</bold>
|
||||
4 var <bold>x: Int = 1</bold>
|
||||
4 var x: Int = <bold>1</bold>
|
||||
|
||||
9 x = <bold>2</bold>
|
||||
4 var <bold>x: Int = 1</bold>
|
||||
9 x = <bold>2</bold>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
7 x = <bold>1</bold>
|
||||
4 var <bold>x: Int</bold>
|
||||
7 x = <bold>1</bold>
|
||||
|
||||
14 x = <bold>2</bold>
|
||||
4 var <bold>x: Int</bold>
|
||||
14 x = <bold>2</bold>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
5 get() = <bold>1</bold>
|
||||
11 val x = <bold>foo</bold>
|
||||
4 var <bold>foo: Int</bold>
|
||||
5 get() = <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
5 fun bar(a: Int): Int = foo(a) { if (it > 0) <bold>it</bold> else return 0 }
|
||||
5 fun <bold>bar(a: Int): Int = foo(a) { if (it > 0) it else return 0 }</bold>
|
||||
5 fun bar(a: Int): Int = <bold>foo(a) { if (it > 0) it else return 0 }</bold>
|
||||
3 inline fun <bold>foo(a: Int, f: (Int) -> Int) = f(a)</bold>
|
||||
3 inline fun foo(a: Int, f: (Int) -> Int) = <bold>f(a)</bold>
|
||||
3 [LAMBDA] inline fun foo(a: Int, f: (Int) -> Int) = <bold>f</bold>(a)
|
||||
3 [LAMBDA] inline fun foo(a: Int, <bold>f: (Int) -> Int</bold>) = f(a)
|
||||
5 [LAMBDA] fun bar(a: Int): Int = foo(a) <bold>{ if (it > 0) it else return 0 }</bold>
|
||||
5 fun bar(a: Int): Int = foo(a) <bold>{ if (it > 0) it else return 0 }</bold>
|
||||
5 fun bar(a: Int): Int = foo(a) { <bold>if (it > 0) it else return 0</bold> }
|
||||
5 fun bar(a: Int): Int = foo(a) { if (it > 0) <bold>it</bold> else return 0 }
|
||||
|
||||
5 fun bar(a: Int): Int = foo(a) { if (it > 0) it else return <bold>0</bold> }
|
||||
5 fun <bold>bar(a: Int): Int = foo(a) { if (it > 0) it else return 0 }</bold>
|
||||
5 fun bar(a: Int): Int = foo(a) { if (it > 0) it else return <bold>0</bold> }
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
3 fun test(<bold>s: String?</bold>) {
|
||||
4 val <bold>x = s!!</bold>
|
||||
4 val x = <bold>s!!</bold>
|
||||
4 val x = <bold>s</bold>!!
|
||||
3 fun test(<bold>s: String?</bold>) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
8 override fun foo() = <bold>2</bold>
|
||||
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 foo() = <bold>3</bold>
|
||||
17 val <bold>y = b.foo()</bold>
|
||||
17 val y = <bold>b.foo()</bold>
|
||||
12 override fun <bold>foo() = 3</bold>
|
||||
12 override fun foo() = <bold>3</bold>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
7 open class B(override val <bold>foo: Int</bold>) : A()
|
||||
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 foo = <bold>3</bold>
|
||||
15 val <bold>y = b.foo</bold>
|
||||
15 val y = <bold>b.foo</bold>
|
||||
10 override val <bold>foo = 3</bold>
|
||||
10 override val foo = <bold>3</bold>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
10 get() = <bold>2</bold>
|
||||
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>
|
||||
|
||||
15 get() = <bold>3</bold>
|
||||
20 val <bold>y = b.foo</bold>
|
||||
20 val y = <bold>b.foo</bold>
|
||||
14 override val <bold>foo: Int</bold>
|
||||
15 get() = <bold>3</bold>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
8 override val foo = <bold>2</bold>
|
||||
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 foo = <bold>3</bold>
|
||||
17 val <bold>y = b.foo</bold>
|
||||
17 val y = <bold>b.foo</bold>
|
||||
12 override val <bold>foo = 3</bold>
|
||||
12 override val foo = <bold>3</bold>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
5 class B1: A(<bold>1</bold>)
|
||||
3 open class A(<bold>n: Int</bold>, s: String = "???")
|
||||
5 class B1: A(<bold>1</bold>)
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
6 class B2: A(1, <bold>"2"</bold>)
|
||||
3 open class A(n: Int, <bold>s: String = "???"</bold>)
|
||||
6 class B2: A(1, <bold>"2"</bold>)
|
||||
|
||||
3 open class A(n: Int, s: String = <bold>"???"</bold>)
|
||||
3 open class A(n: Int, <bold>s: String = "???"</bold>)
|
||||
3 open class A(n: Int, s: String = <bold>"???"</bold>)
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
13 val a = AClass(<bold>"main: hello"</bold>)
|
||||
15 println("Now my name is '${a.<bold>name</bold>}'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
4 var name : String = <bold>name1</bold>
|
||||
3 class AClass(<bold>name1: String</bold>){
|
||||
13 val a = AClass(<bold>"main: hello"</bold>)
|
||||
|
||||
14 a.name = <bold>"main: bye"</bold>
|
||||
15 println("Now my name is '${a.<bold>name</bold>}'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
14 a.name = <bold>"main: bye"</bold>
|
||||
|
||||
6 name = <bold>"uses: bye"</bold>
|
||||
15 println("Now my name is '${a.<bold>name</bold>}'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
6 name = <bold>"uses: bye"</bold>
|
||||
|
||||
7 this.name = <bold>"uses: after this"</bold>
|
||||
15 println("Now my name is '${a.<bold>name</bold>}'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
7 this.name = <bold>"uses: after this"</bold>
|
||||
@@ -0,0 +1,21 @@
|
||||
13 val a = AClass(<bold>"main: hello"</bold>)
|
||||
8 println("And now my name is '$<bold>name</bold>'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
4 var name : String = <bold>name1</bold>
|
||||
3 class AClass(<bold>name1: String</bold>){
|
||||
13 val a = AClass(<bold>"main: hello"</bold>)
|
||||
|
||||
14 a.name = <bold>"main: bye"</bold>
|
||||
8 println("And now my name is '$<bold>name</bold>'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
14 a.name = <bold>"main: bye"</bold>
|
||||
|
||||
6 name = <bold>"uses: bye"</bold>
|
||||
8 println("And now my name is '$<bold>name</bold>'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
6 name = <bold>"uses: bye"</bold>
|
||||
|
||||
7 this.name = <bold>"uses: after this"</bold>
|
||||
8 println("And now my name is '$<bold>name</bold>'")
|
||||
4 var <bold>name : String = name1</bold>
|
||||
7 this.name = <bold>"uses: after this"</bold>
|
||||
@@ -0,0 +1,6 @@
|
||||
3 fun test(<bold>o: Any</bold>) {
|
||||
4 val <bold>x = o as? String</bold>
|
||||
4 val x = <bold>o as? String</bold>
|
||||
4 val x = <bold>o</bold> as? String
|
||||
3 fun test(<bold>o: Any</bold>) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
7 class B1: A(<bold>1</bold>)
|
||||
4 constructor(<bold>n: Int</bold>, s: String = "???")
|
||||
7 class B1: A(<bold>1</bold>)
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
8 class B2: A(1, <bold>"2"</bold>)
|
||||
4 constructor(n: Int, <bold>s: String = "???"</bold>)
|
||||
8 class B2: A(1, <bold>"2"</bold>)
|
||||
|
||||
4 constructor(n: Int, s: String = <bold>"???"</bold>)
|
||||
4 constructor(n: Int, <bold>s: String = "???"</bold>)
|
||||
4 constructor(n: Int, s: String = <bold>"???"</bold>)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
4 private var _value: String = <bold>""</bold>
|
||||
25 println("My name is '${a.<bold>name</bold>}'")
|
||||
12 var <bold>name by Delegate()</bold>
|
||||
5 operator fun <bold>getValue(thisRef: Any?, property: KProperty<*>) = _value</bold>
|
||||
5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>_value</bold>
|
||||
4 private var <bold>_value: String = ""</bold>
|
||||
4 private var _value: String = <bold>""</bold>
|
||||
|
||||
18 name = <bold>"bye"</bold>
|
||||
25 println("My name is '${a.<bold>name</bold>}'")
|
||||
12 var <bold>name by Delegate()</bold>
|
||||
5 operator fun <bold>getValue(thisRef: Any?, property: KProperty<*>) = _value</bold>
|
||||
5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>_value</bold>
|
||||
4 private var <bold>_value: String = ""</bold>
|
||||
7 _value = <bold>value</bold>
|
||||
6 operator fun setValue(thisRef: Any?, property: KProperty<*>, <bold>value: String</bold>) {
|
||||
18 name = <bold>"bye"</bold>
|
||||
|
||||
24 val a = AClass(<bold>"hello"</bold>)
|
||||
25 println("My name is '${a.<bold>name</bold>}'")
|
||||
12 var <bold>name by Delegate()</bold>
|
||||
5 operator fun <bold>getValue(thisRef: Any?, property: KProperty<*>) = _value</bold>
|
||||
5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>_value</bold>
|
||||
4 private var <bold>_value: String = ""</bold>
|
||||
7 _value = <bold>value</bold>
|
||||
6 operator fun setValue(thisRef: Any?, property: KProperty<*>, <bold>value: String</bold>) {
|
||||
14 name = <bold>name1</bold>
|
||||
11 class AClass(<bold>name1: String</bold>){
|
||||
24 val a = AClass(<bold>"hello"</bold>)
|
||||
@@ -0,0 +1,29 @@
|
||||
4 private var _value: String = <bold>""</bold>
|
||||
19 println("Now my name is '$<bold>name</bold>'")
|
||||
12 var <bold>name by Delegate()</bold>
|
||||
5 operator fun <bold>getValue(thisRef: Any?, property: KProperty<*>) = _value</bold>
|
||||
5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>_value</bold>
|
||||
4 private var <bold>_value: String = ""</bold>
|
||||
4 private var _value: String = <bold>""</bold>
|
||||
|
||||
18 name = <bold>"bye"</bold>
|
||||
19 println("Now my name is '$<bold>name</bold>'")
|
||||
12 var <bold>name by Delegate()</bold>
|
||||
5 operator fun <bold>getValue(thisRef: Any?, property: KProperty<*>) = _value</bold>
|
||||
5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>_value</bold>
|
||||
4 private var <bold>_value: String = ""</bold>
|
||||
7 _value = <bold>value</bold>
|
||||
6 operator fun setValue(thisRef: Any?, property: KProperty<*>, <bold>value: String</bold>) {
|
||||
18 name = <bold>"bye"</bold>
|
||||
|
||||
24 val a = AClass(<bold>"hello"</bold>)
|
||||
19 println("Now my name is '$<bold>name</bold>'")
|
||||
12 var <bold>name by Delegate()</bold>
|
||||
5 operator fun <bold>getValue(thisRef: Any?, property: KProperty<*>) = _value</bold>
|
||||
5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = <bold>_value</bold>
|
||||
4 private var <bold>_value: String = ""</bold>
|
||||
7 _value = <bold>value</bold>
|
||||
6 operator fun setValue(thisRef: Any?, property: KProperty<*>, <bold>value: String</bold>) {
|
||||
14 name = <bold>name1</bold>
|
||||
11 class AClass(<bold>name1: String</bold>){
|
||||
24 val a = AClass(<bold>"hello"</bold>)
|
||||
@@ -0,0 +1,4 @@
|
||||
3 val foo: Int = <bold>1</bold>
|
||||
3 val <bold>foo: Int = 1</bold>
|
||||
3 val foo: Int = <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
3 var foo: Int = <bold>1</bold>
|
||||
3 var <bold>foo: Int = 1</bold>
|
||||
3 var foo: Int = <bold>1</bold>
|
||||
|
||||
7 foo = <bold>2</bold>
|
||||
3 var <bold>foo: Int = 1</bold>
|
||||
7 foo = <bold>2</bold>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
5 class B : A(<bold>1</bold>)
|
||||
3 open class A(val <bold>n: Int</bold>)
|
||||
5 class B : A(<bold>1</bold>)
|
||||
|
||||
8 val z = A(<bold>2</bold>).n
|
||||
3 open class A(val <bold>n: Int</bold>)
|
||||
8 val z = A(<bold>2</bold>).n
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
20 class B : A(<bold>1</bold>)
|
||||
3 open class A(var <bold>n: Int</bold>) {
|
||||
20 class B : A(<bold>1</bold>)
|
||||
|
||||
23 val z = A(<bold>2</bold>).n
|
||||
3 open class A(var <bold>n: Int</bold>) {
|
||||
23 val z = A(<bold>2</bold>).n
|
||||
|
||||
24 A(<bold>3</bold>).n = 2
|
||||
3 open class A(var <bold>n: Int</bold>) {
|
||||
24 A(<bold>3</bold>).n = 2
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
3 fun test(m: Int, <bold>n: Int</bold>) {
|
||||
4 val <bold>x = when (m) {</bold>
|
||||
4 val x = <bold>when (m) {</bold>
|
||||
6 2 -> <bold>n</bold>
|
||||
3 fun test(m: Int, <bold>n: Int</bold>) {
|
||||
|
||||
7 else -> <bold>0</bold>
|
||||
4 val <bold>x = when (m) {</bold>
|
||||
4 val x = <bold>when (m) {</bold>
|
||||
7 else -> <bold>0</bold>
|
||||
|
||||
5 1 -> <bold>1</bold>
|
||||
4 val <bold>x = when (m) {</bold>
|
||||
4 val x = <bold>when (m) {</bold>
|
||||
5 1 -> <bold>1</bold>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.slicer
|
||||
|
||||
import com.intellij.slicer.SliceRootNode
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractSlicerLeafGroupingTest : AbstractSlicerTest() {
|
||||
override fun doTest(path: String, sliceProvider: KotlinSliceProvider, rootNode: SliceRootNode) {
|
||||
val treeStructure = SliceTreeStructure(rootNode)
|
||||
val analyzer = sliceProvider.leafAnalyzer
|
||||
val possibleElementsByNode = analyzer.createMap()
|
||||
val leafExpressions = analyzer.calcLeafExpressions(rootNode, treeStructure, possibleElementsByNode)
|
||||
val newRootNode = analyzer.createTreeGroupedByValues(leafExpressions, rootNode, possibleElementsByNode)
|
||||
val renderedForest = buildString {
|
||||
for (groupRootNode in newRootNode.children) {
|
||||
append(buildTreeRepresentation(groupRootNode))
|
||||
append("\n")
|
||||
}
|
||||
}
|
||||
KotlinTestUtils.assertEqualsToFile(File(path.replace(".kt", ".leafGroups.txt")), renderedForest)
|
||||
}
|
||||
}
|
||||
@@ -17,16 +17,15 @@
|
||||
package org.jetbrains.kotlin.idea.slicer
|
||||
|
||||
import com.intellij.analysis.AnalysisScope
|
||||
import com.intellij.ide.projectView.TreeStructureProvider
|
||||
import com.intellij.ide.util.treeView.AbstractTreeStructureBase
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.slicer.DuplicateMap
|
||||
import com.intellij.slicer.SliceAnalysisParams
|
||||
import com.intellij.slicer.SliceUsage
|
||||
import com.intellij.slicer.SliceNode
|
||||
import com.intellij.slicer.SliceRootNode
|
||||
import com.intellij.usages.TextChunk
|
||||
import com.intellij.util.CommonProcessors
|
||||
import com.intellij.util.Processor
|
||||
import gnu.trove.THashSet
|
||||
import gnu.trove.TObjectHashingStrategy
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
@@ -34,80 +33,70 @@ import java.awt.Font
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractSlicerTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
object SliceUsageHashingStrategy : TObjectHashingStrategy<KotlinSliceUsage> {
|
||||
override fun computeHashCode(`object`: KotlinSliceUsage): Int {
|
||||
return `object`.usageInfo.hashCode() * 31 + `object`.forcedExpressionMode.hashCode()
|
||||
protected class SliceTreeStructure(private val rootNode: SliceNode) : AbstractTreeStructureBase(rootNode.project) {
|
||||
override fun getProviders(): List<TreeStructureProvider>? = emptyList()
|
||||
|
||||
override fun getRootElement() = rootNode
|
||||
|
||||
override fun commit() {
|
||||
|
||||
}
|
||||
|
||||
override fun equals(o1: KotlinSliceUsage, o2: KotlinSliceUsage): Boolean {
|
||||
return o1.usageInfo == o2.usageInfo && o1.forcedExpressionMode == o2.forcedExpressionMode
|
||||
}
|
||||
override fun hasSomethingToCommit() = false
|
||||
}
|
||||
|
||||
// Based on SliceUsage.processChildren
|
||||
private fun KotlinSliceUsage.processChildrenWithoutProgress(processor: (KotlinSliceUsage) -> Unit) {
|
||||
if (this is KotlinSliceDereferenceUsage) return
|
||||
|
||||
val element = runReadAction { element }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val uniqueProcessor = CommonProcessors.UniqueProcessor(
|
||||
{
|
||||
processor(it as KotlinSliceUsage)
|
||||
true
|
||||
},
|
||||
SliceUsageHashingStrategy
|
||||
) as Processor<SliceUsage>
|
||||
|
||||
runReadAction {
|
||||
if (params.dataFlowToThis) {
|
||||
processUsagesFlownDownTo(element, uniqueProcessor)
|
||||
}
|
||||
else {
|
||||
processUsagesFlownFromThe(element, uniqueProcessor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildTreeRepresentation(rootUsage: KotlinSliceUsage): String {
|
||||
val visitedUsages = THashSet<KotlinSliceUsage>(SliceUsageHashingStrategy)
|
||||
|
||||
fun TextChunk.render(): String {
|
||||
var text = text
|
||||
if (attributes.fontType == Font.BOLD) {
|
||||
text = "<bold>$text</bold>"
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
fun process(usage: KotlinSliceUsage, indent: Int): String {
|
||||
val isDuplicated = !visitedUsages.add(usage)
|
||||
|
||||
return buildString {
|
||||
val chunks = usage.text
|
||||
append(chunks.first().render() + " ")
|
||||
append("\t".repeat(indent))
|
||||
if (usage is KotlinSliceDereferenceUsage) {
|
||||
append("DEREFERENCE: ")
|
||||
companion object {
|
||||
@JvmStatic
|
||||
protected fun buildTreeRepresentation(rootNode: SliceNode): String {
|
||||
fun TextChunk.render(): String {
|
||||
var text = text
|
||||
if (attributes.fontType == Font.BOLD) {
|
||||
text = "<bold>$text</bold>"
|
||||
}
|
||||
append("[LAMBDA] ".repeat(usage.lambdaLevel))
|
||||
chunks.slice(1..chunks.size - 1).joinTo(
|
||||
this,
|
||||
separator = "",
|
||||
prefix = if (isDuplicated) "DUPLICATE: " else "",
|
||||
postfix = "\n"
|
||||
) { it.render() }
|
||||
if (!isDuplicated) {
|
||||
usage.processChildrenWithoutProgress {
|
||||
append(process(it, indent + 1))
|
||||
return text
|
||||
}
|
||||
|
||||
fun process(node: SliceNode, indent: Int): String {
|
||||
val usage = node.element!!.value as KotlinSliceUsage
|
||||
|
||||
node.calculateDupNode()
|
||||
val isDuplicated = node.duplicate != null
|
||||
|
||||
return buildString {
|
||||
when {
|
||||
node is SliceRootNode && usage.element is KtFile -> {
|
||||
node.children.forEach { append(process(it, indent)) }
|
||||
return@buildString
|
||||
}
|
||||
else -> {
|
||||
val chunks = usage.text
|
||||
append(chunks.first().render() + " ")
|
||||
append("\t".repeat(indent))
|
||||
if (usage is KotlinSliceDereferenceUsage) {
|
||||
append("DEREFERENCE: ")
|
||||
}
|
||||
append("[LAMBDA] ".repeat(usage.lambdaLevel))
|
||||
chunks.slice(1..chunks.size - 1).joinTo(
|
||||
this,
|
||||
separator = "",
|
||||
prefix = if (isDuplicated) "DUPLICATE: " else "",
|
||||
postfix = "\n"
|
||||
) { it.render() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}.replace(Regex("</bold><bold>"), "")
|
||||
}
|
||||
|
||||
return process(rootUsage, 0)
|
||||
if (!isDuplicated) {
|
||||
node.children.forEach { append(process(it, indent + 1)) }
|
||||
}
|
||||
}.replace(Regex("</bold><bold>"), "")
|
||||
}
|
||||
|
||||
return process(rootNode, 0)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun doTest(path: String, sliceProvider: KotlinSliceProvider, rootNode: SliceRootNode)
|
||||
|
||||
protected fun doTest(path: String) {
|
||||
val mainFile = File(path)
|
||||
|
||||
@@ -131,6 +120,7 @@ abstract class AbstractSlicerTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
val sliceProvider = KotlinSliceProvider()
|
||||
val expression = sliceProvider.getExpressionAtCaret(elementAtCaret, analysisParams.dataFlowToThis)!!
|
||||
val rootUsage = sliceProvider.createRootUsage(expression, analysisParams)
|
||||
KotlinTestUtils.assertEqualsToFile(File(path.replace(".kt", ".results.txt")), buildTreeRepresentation(rootUsage))
|
||||
val rootNode = SliceRootNode(project, DuplicateMap(), rootUsage)
|
||||
doTest(path, sliceProvider, rootNode)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.slicer
|
||||
|
||||
import com.intellij.slicer.SliceRootNode
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractSlicerTreeTest : AbstractSlicerTest() {
|
||||
override fun doTest(path: String, sliceProvider: KotlinSliceProvider, rootNode: SliceRootNode) {
|
||||
KotlinTestUtils.assertEqualsToFile(File(path.replace(".kt", ".results.txt")), buildTreeRepresentation(rootNode))
|
||||
}
|
||||
}
|
||||
+350
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.slicer;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/slicer/inflow")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class SlicerLeafGroupingTestGenerated extends AbstractSlicerLeafGroupingTest {
|
||||
public void testAllFilesPresentInSlicer() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/slicer/inflow"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY);
|
||||
}
|
||||
|
||||
@TestMetadata("anonymousFunBodyExpression.kt")
|
||||
public void testInflow_AnonymousFunBodyExpression() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/anonymousFunBodyExpression.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("anonymousFunReturnExpression.kt")
|
||||
public void testInflow_AnonymousFunReturnExpression() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/anonymousFunReturnExpression.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("cast.kt")
|
||||
public void testInflow_Cast() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/cast.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compositeAssignments.kt")
|
||||
public void testInflow_CompositeAssignments() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/compositeAssignments.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultGetterFieldInSetter.kt")
|
||||
public void testInflow_DefaultGetterFieldInSetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/defaultGetterFieldInSetter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegateGetter.kt")
|
||||
public void testInflow_DelegateGetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/delegateGetter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("diamondHierarchyMiddleClassFun.kt")
|
||||
public void testInflow_DiamondHierarchyMiddleClassFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/diamondHierarchyMiddleClassFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("diamondHierarchyMiddleInterfaceFun.kt")
|
||||
public void testInflow_DiamondHierarchyMiddleInterfaceFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/diamondHierarchyMiddleInterfaceFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("diamondHierarchyRootInterfaceFun.kt")
|
||||
public void testInflow_DiamondHierarchyRootInterfaceFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/diamondHierarchyRootInterfaceFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("doubleLambdaResult.kt")
|
||||
public void testInflow_DoubleLambdaResult() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/doubleLambdaResult.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funParamerer.kt")
|
||||
public void testInflow_FunParamerer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funParamerer.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funParamererWithDefault.kt")
|
||||
public void testInflow_FunParamererWithDefault() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funParamererWithDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funResultViaCallableRef.kt")
|
||||
public void testInflow_FunResultViaCallableRef() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funResultViaCallableRef.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funResultViaCallableRefWithAssignment.kt")
|
||||
public void testInflow_FunResultViaCallableRefWithAssignment() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funResultViaCallableRefWithAssignment.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funResultViaCallableRefWithDirectCall.kt")
|
||||
public void testInflow_FunResultViaCallableRefWithDirectCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funResultViaCallableRefWithDirectCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funWithExpressionBody.kt")
|
||||
public void testInflow_FunWithExpressionBody() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funWithExpressionBody.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funWithReturnExpressions.kt")
|
||||
public void testInflow_FunWithReturnExpressions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funWithReturnExpressions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("getterAndSetterUsingField.kt")
|
||||
public void testInflow_GetterAndSetterUsingField() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/getterAndSetterUsingField.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("getterExpressionBody.kt")
|
||||
public void testInflow_GetterExpressionBody() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/getterExpressionBody.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("getterReturnExpression.kt")
|
||||
public void testInflow_GetterReturnExpression() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/getterReturnExpression.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifExpression.kt")
|
||||
public void testInflow_IfExpression() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/ifExpression.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaResult.kt")
|
||||
public void testInflow_LambdaResult() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/lambdaResult.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaResultWithAssignments.kt")
|
||||
public void testInflow_LambdaResultWithAssignments() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/lambdaResultWithAssignments.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaResultWithDirectCall.kt")
|
||||
public void testInflow_LambdaResultWithDirectCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/lambdaResultWithDirectCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaResultWithDirectCallViaAssignment.kt")
|
||||
public void testInflow_LambdaResultWithDirectCallViaAssignment() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/lambdaResultWithDirectCallViaAssignment.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localVal.kt")
|
||||
public void testInflow_LocalVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/localVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localVar.kt")
|
||||
public void testInflow_LocalVar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/localVar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("memberValWithInitializer.kt")
|
||||
public void testInflow_MemberValWithInitializer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberValWithInitializer.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("memberValWithSplitInitializer.kt")
|
||||
public void testInflow_MemberValWithSplitInitializer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberValWithSplitInitializer.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("memberVarWithInitializer.kt")
|
||||
public void testInflow_MemberVarWithInitializer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberVarWithInitializer.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("memberVarWithSplitInitializer.kt")
|
||||
public void testInflow_MemberVarWithSplitInitializer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberVarWithSplitInitializer.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noFieldInGetter.kt")
|
||||
public void testInflow_NoFieldInGetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/noFieldInGetter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturn.kt")
|
||||
public void testInflow_NonLocalReturn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/nonLocalReturn.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notNullAssertion.kt")
|
||||
public void testInflow_NotNullAssertion() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/notNullAssertion.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("overridingFunctionResult.kt")
|
||||
public void testInflow_OverridingFunctionResult() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingFunctionResult.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("overridingParameter.kt")
|
||||
public void testInflow_OverridingParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("overridingPropertyGetterResult.kt")
|
||||
public void testInflow_OverridingPropertyGetterResult() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingPropertyGetterResult.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("overridingPropertyResult.kt")
|
||||
public void testInflow_OverridingPropertyResult() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/overridingPropertyResult.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorParameter.kt")
|
||||
public void testInflow_PrimaryConstructorParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/primaryConstructorParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorParameterWithDefault.kt")
|
||||
public void testInflow_PrimaryConstructorParameterWithDefault() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/primaryConstructorParameterWithDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("qualifiedAssignmentsForQualifiedRef.kt")
|
||||
public void testInflow_QualifiedAssignmentsForQualifiedRef() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/qualifiedAssignmentsForQualifiedRef.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("qualifiedAssignmentsForSimpleRef.kt")
|
||||
public void testInflow_QualifiedAssignmentsForSimpleRef() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/qualifiedAssignmentsForSimpleRef.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("safeCast.kt")
|
||||
public void testInflow_SafeCast() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/safeCast.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("secondaryConstructorParameter.kt")
|
||||
public void testInflow_SecondaryConstructorParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/secondaryConstructorParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("secondaryConstructorParameterWithDefault.kt")
|
||||
public void testInflow_SecondaryConstructorParameterWithDefault() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/secondaryConstructorParameterWithDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("settersViaDelegateForQualifiedRef.kt")
|
||||
public void testInflow_SettersViaDelegateForQualifiedRef() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("settersViaDelegateForSimpleRef.kt")
|
||||
public void testInflow_SettersViaDelegateForSimpleRef() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelVal.kt")
|
||||
public void testInflow_TopLevelVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/topLevelVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelVar.kt")
|
||||
public void testInflow_TopLevelVar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/topLevelVar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valParameter.kt")
|
||||
public void testInflow_ValParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/valParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("varParameter.kt")
|
||||
public void testInflow_VarParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/varParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whenExpression.kt")
|
||||
public void testInflow_WhenExpression() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/whenExpression.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ import java.util.regex.Pattern;
|
||||
@TestMetadata("idea/testData/slicer")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class SlicerTestGenerated extends AbstractSlicerTest {
|
||||
public class SlicerTreeTestGenerated extends AbstractSlicerTreeTest {
|
||||
public void testAllFilesPresentInSlicer() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/slicer"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY);
|
||||
}
|
||||
Reference in New Issue
Block a user