From 7a4d20b4cfb3cce4f00dd7a3f3b265d9a6f72a70 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 5 Aug 2016 15:09:24 +0300 Subject: [PATCH] Make quick evaluate work on receiver in qualified expressions (KT-13269) (cherry picked from commit 970ac5a) #KT-13269 Fixed --- ChangeLog.md | 3 +- .../idea/debugger/KotlinEditorTextProvider.kt | 52 +++++++++++-------- .../disallowMethodCalls/superSelector.kt | 11 ++++ .../disallowMethodCalls/this.kt | 2 +- .../disallowMethodCalls/thisSelector.kt | 7 +++ .../selectExpression/firstCallInChain.kt | 9 ++++ .../selectExpression/superSelector.kt | 11 ++++ .../debugger/selectExpression/this.kt | 2 +- .../debugger/selectExpression/thisSelector.kt | 7 +++ ...ectExpressionForDebuggerTestGenerated.java | 30 +++++++++++ 10 files changed, 108 insertions(+), 26 deletions(-) create mode 100644 idea/testData/debugger/selectExpression/disallowMethodCalls/superSelector.kt create mode 100644 idea/testData/debugger/selectExpression/disallowMethodCalls/thisSelector.kt create mode 100644 idea/testData/debugger/selectExpression/firstCallInChain.kt create mode 100644 idea/testData/debugger/selectExpression/superSelector.kt create mode 100644 idea/testData/debugger/selectExpression/thisSelector.kt diff --git a/ChangeLog.md b/ChangeLog.md index 86e1c6cda60..43e9b63b295 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -269,7 +269,8 @@ Using 'this' as function argument in constructor of non-final class - [`KT-13037`](https://youtrack.jetbrains.com/issue/KT-13037) Fix possible deadlock in debugger in 2016.1 and exception in 2016.2 - [`KT-12651`](https://youtrack.jetbrains.com/issue/KT-12651) Fix exception in evaluate expression when bad identifier is used for marking object - [`KT-12896`](https://youtrack.jetbrains.com/issue/KT-12896) Fix "Step In" to inline functions for Android -- [`KT-7549`](https://youtrack.jetbrains.com/issue/KT-13037) Allow to evaluate kotlin expressions in Java files +- [`KT-13269`](https://youtrack.jetbrains.com/issue/KT-13269) Make quick evaluate work on receiver in qualified expressions +- [`KT-7549`](https://youtrack.jetbrains.com/issue/KT-7549) Allow to evaluate kotlin expressions in Java files ### JS diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinEditorTextProvider.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinEditorTextProvider.kt index 2a14449a6d0..092b5656e3a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinEditorTextProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinEditorTextProvider.kt @@ -61,40 +61,48 @@ class KotlinEditorTextProvider : EditorTextProvider { fun findExpressionInner(element: PsiElement, allowMethodCalls: Boolean): KtExpression? { if (!isAcceptedAsCodeFragmentContext(element)) return null - val jetElement = PsiTreeUtil.getParentOfType(element, KtElement::class.java) - if (jetElement == null) return null + val ktElement = PsiTreeUtil.getParentOfType(element, KtElement::class.java) ?: return null - if (jetElement is KtProperty) { - val nameIdentifier = jetElement.nameIdentifier + if (ktElement is KtProperty) { + val nameIdentifier = ktElement.nameIdentifier if (nameIdentifier == element) { - return jetElement + return ktElement } } - val parent = jetElement.parent - if (parent == null) return null + val parent = ktElement.parent ?: return null val newExpression = when (parent) { - is KtThisExpression, - is KtSuperExpression, - is KtReferenceExpression -> { + is KtThisExpression -> parent + is KtSuperExpression -> { val pparent = parent.parent when (pparent) { is KtQualifiedExpression -> pparent else -> parent } } - is KtQualifiedExpression -> { - if (parent.receiverExpression != jetElement) { + is KtReferenceExpression -> { + val pparent = parent.parent + if (pparent is KtQualifiedExpression && pparent.selectorExpression == parent) { + pparent + } + else { parent - } else { + } + } + is KtQualifiedExpression -> { + if (parent.receiverExpression != ktElement) { + parent + } + else { null } } is KtOperationExpression -> { - if (parent.operationReference == jetElement) { + if (parent.operationReference == ktElement) { parent - } else { + } + else { null } } @@ -104,22 +112,21 @@ class KotlinEditorTextProvider : EditorTextProvider { if (!allowMethodCalls && newExpression != null) { fun PsiElement.isCall() = this is KtCallExpression || this is KtOperationExpression || this is KtArrayAccessExpression - if (newExpression.isCall() || - newExpression is KtQualifiedExpression && newExpression.selectorExpression!!.isCall()) { + if (newExpression.isCall() || newExpression is KtQualifiedExpression && newExpression.selectorExpression!!.isCall()) { return null } } return when { newExpression is KtExpression -> newExpression - jetElement is KtSimpleNameExpression -> { - val context = jetElement.analyzeAndGetResult().bindingContext - val qualifier = context[BindingContext.QUALIFIER, jetElement] + ktElement is KtSimpleNameExpression -> { + val context = ktElement.analyzeAndGetResult().bindingContext + val qualifier = context[BindingContext.QUALIFIER, ktElement] if (qualifier != null && !DescriptorUtils.isObject(qualifier.descriptor)) { null } else { - jetElement + ktElement } } else -> null @@ -135,5 +142,4 @@ class KotlinEditorTextProvider : EditorTextProvider { PsiTreeUtil.getParentOfType(element, *NOT_ACCEPTED_AS_CONTEXT_TYPES) == null } } -} - +} \ No newline at end of file diff --git a/idea/testData/debugger/selectExpression/disallowMethodCalls/superSelector.kt b/idea/testData/debugger/selectExpression/disallowMethodCalls/superSelector.kt new file mode 100644 index 00000000000..f4cdce77fd1 --- /dev/null +++ b/idea/testData/debugger/selectExpression/disallowMethodCalls/superSelector.kt @@ -0,0 +1,11 @@ +class Derived: Base() { + fun test() { + super.test() + } +} + +open class Base { + fun test() {} +} + +// EXPECTED: null \ No newline at end of file diff --git a/idea/testData/debugger/selectExpression/disallowMethodCalls/this.kt b/idea/testData/debugger/selectExpression/disallowMethodCalls/this.kt index 212e9643e6b..e8130b65caf 100644 --- a/idea/testData/debugger/selectExpression/disallowMethodCalls/this.kt +++ b/idea/testData/debugger/selectExpression/disallowMethodCalls/this.kt @@ -4,4 +4,4 @@ class MyClass { } } -// EXPECTED: null \ No newline at end of file +// EXPECTED: this \ No newline at end of file diff --git a/idea/testData/debugger/selectExpression/disallowMethodCalls/thisSelector.kt b/idea/testData/debugger/selectExpression/disallowMethodCalls/thisSelector.kt new file mode 100644 index 00000000000..e8130b65caf --- /dev/null +++ b/idea/testData/debugger/selectExpression/disallowMethodCalls/thisSelector.kt @@ -0,0 +1,7 @@ +class MyClass { + fun test() { + this.test() + } +} + +// EXPECTED: this \ No newline at end of file diff --git a/idea/testData/debugger/selectExpression/firstCallInChain.kt b/idea/testData/debugger/selectExpression/firstCallInChain.kt new file mode 100644 index 00000000000..4f46ff17753 --- /dev/null +++ b/idea/testData/debugger/selectExpression/firstCallInChain.kt @@ -0,0 +1,9 @@ +fun one() = "one" +fun String.two() = this + "two" +fun String.three() = this + "three" + +fun main(args: Array) { + val s = one().two().three() // Can't select 'one()' with Alt in debugger, only 'one().two()' and 'one().two().three()' are available +} + +// EXPECTED: one() \ No newline at end of file diff --git a/idea/testData/debugger/selectExpression/superSelector.kt b/idea/testData/debugger/selectExpression/superSelector.kt new file mode 100644 index 00000000000..fbcf533e925 --- /dev/null +++ b/idea/testData/debugger/selectExpression/superSelector.kt @@ -0,0 +1,11 @@ +class Derived: Base() { + fun test() { + super.test() + } +} + +open class Base { + fun test() {} +} + +// EXPECTED: super.test() \ No newline at end of file diff --git a/idea/testData/debugger/selectExpression/this.kt b/idea/testData/debugger/selectExpression/this.kt index 3f4f4540e49..e8130b65caf 100644 --- a/idea/testData/debugger/selectExpression/this.kt +++ b/idea/testData/debugger/selectExpression/this.kt @@ -4,4 +4,4 @@ class MyClass { } } -// EXPECTED: this.test() \ No newline at end of file +// EXPECTED: this \ No newline at end of file diff --git a/idea/testData/debugger/selectExpression/thisSelector.kt b/idea/testData/debugger/selectExpression/thisSelector.kt new file mode 100644 index 00000000000..d2ed5c7d858 --- /dev/null +++ b/idea/testData/debugger/selectExpression/thisSelector.kt @@ -0,0 +1,7 @@ +class MyClass { + fun test() { + this.test() + } +} + +// EXPECTED: this.test() \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/SelectExpressionForDebuggerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/SelectExpressionForDebuggerTestGenerated.java index d03d1007e4a..a92d85f35aa 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/SelectExpressionForDebuggerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/SelectExpressionForDebuggerTestGenerated.java @@ -79,6 +79,12 @@ public class SelectExpressionForDebuggerTestGenerated extends AbstractSelectExpr doTest(fileName); } + @TestMetadata("firstCallInChain.kt") + public void testFirstCallInChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/firstCallInChain.kt"); + doTest(fileName); + } + @TestMetadata("fullyQualified.kt") public void testFullyQualified() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/fullyQualified.kt"); @@ -205,12 +211,24 @@ public class SelectExpressionForDebuggerTestGenerated extends AbstractSelectExpr doTest(fileName); } + @TestMetadata("superSelector.kt") + public void testSuperSelector() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/superSelector.kt"); + doTest(fileName); + } + @TestMetadata("this.kt") public void testThis() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/this.kt"); doTest(fileName); } + @TestMetadata("thisSelector.kt") + public void testThisSelector() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/thisSelector.kt"); + doTest(fileName); + } + @TestMetadata("thisWithLabel.kt") public void testThisWithLabel() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/thisWithLabel.kt"); @@ -340,12 +358,24 @@ public class SelectExpressionForDebuggerTestGenerated extends AbstractSelectExpr doTestWoMethodCalls(fileName); } + @TestMetadata("superSelector.kt") + public void testSuperSelector() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/superSelector.kt"); + doTestWoMethodCalls(fileName); + } + @TestMetadata("this.kt") public void testThis() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/this.kt"); doTestWoMethodCalls(fileName); } + @TestMetadata("thisSelector.kt") + public void testThisSelector() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/thisSelector.kt"); + doTestWoMethodCalls(fileName); + } + @TestMetadata("thisWithLabel.kt") public void testThisWithLabel() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/thisWithLabel.kt");