Make quick evaluate work on receiver in qualified expressions (KT-13269)

(cherry picked from commit 970ac5a)

 #KT-13269 Fixed
This commit is contained in:
Nikolay Krasko
2016-08-05 15:09:24 +03:00
committed by Nikolay Krasko
parent 7325baa06a
commit 7a4d20b4cf
10 changed files with 108 additions and 26 deletions
+2 -1
View File
@@ -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-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-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-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 ### JS
@@ -61,40 +61,48 @@ class KotlinEditorTextProvider : EditorTextProvider {
fun findExpressionInner(element: PsiElement, allowMethodCalls: Boolean): KtExpression? { fun findExpressionInner(element: PsiElement, allowMethodCalls: Boolean): KtExpression? {
if (!isAcceptedAsCodeFragmentContext(element)) return null if (!isAcceptedAsCodeFragmentContext(element)) return null
val jetElement = PsiTreeUtil.getParentOfType(element, KtElement::class.java) val ktElement = PsiTreeUtil.getParentOfType(element, KtElement::class.java) ?: return null
if (jetElement == null) return null
if (jetElement is KtProperty) { if (ktElement is KtProperty) {
val nameIdentifier = jetElement.nameIdentifier val nameIdentifier = ktElement.nameIdentifier
if (nameIdentifier == element) { if (nameIdentifier == element) {
return jetElement return ktElement
} }
} }
val parent = jetElement.parent val parent = ktElement.parent ?: return null
if (parent == null) return null
val newExpression = when (parent) { val newExpression = when (parent) {
is KtThisExpression, is KtThisExpression -> parent
is KtSuperExpression, is KtSuperExpression -> {
is KtReferenceExpression -> {
val pparent = parent.parent val pparent = parent.parent
when (pparent) { when (pparent) {
is KtQualifiedExpression -> pparent is KtQualifiedExpression -> pparent
else -> parent else -> parent
} }
} }
is KtQualifiedExpression -> { is KtReferenceExpression -> {
if (parent.receiverExpression != jetElement) { val pparent = parent.parent
if (pparent is KtQualifiedExpression && pparent.selectorExpression == parent) {
pparent
}
else {
parent parent
} else { }
}
is KtQualifiedExpression -> {
if (parent.receiverExpression != ktElement) {
parent
}
else {
null null
} }
} }
is KtOperationExpression -> { is KtOperationExpression -> {
if (parent.operationReference == jetElement) { if (parent.operationReference == ktElement) {
parent parent
} else { }
else {
null null
} }
} }
@@ -104,22 +112,21 @@ class KotlinEditorTextProvider : EditorTextProvider {
if (!allowMethodCalls && newExpression != null) { if (!allowMethodCalls && newExpression != null) {
fun PsiElement.isCall() = this is KtCallExpression || this is KtOperationExpression || this is KtArrayAccessExpression fun PsiElement.isCall() = this is KtCallExpression || this is KtOperationExpression || this is KtArrayAccessExpression
if (newExpression.isCall() || if (newExpression.isCall() || newExpression is KtQualifiedExpression && newExpression.selectorExpression!!.isCall()) {
newExpression is KtQualifiedExpression && newExpression.selectorExpression!!.isCall()) {
return null return null
} }
} }
return when { return when {
newExpression is KtExpression -> newExpression newExpression is KtExpression -> newExpression
jetElement is KtSimpleNameExpression -> { ktElement is KtSimpleNameExpression -> {
val context = jetElement.analyzeAndGetResult().bindingContext val context = ktElement.analyzeAndGetResult().bindingContext
val qualifier = context[BindingContext.QUALIFIER, jetElement] val qualifier = context[BindingContext.QUALIFIER, ktElement]
if (qualifier != null && !DescriptorUtils.isObject(qualifier.descriptor)) { if (qualifier != null && !DescriptorUtils.isObject(qualifier.descriptor)) {
null null
} }
else { else {
jetElement ktElement
} }
} }
else -> null else -> null
@@ -135,5 +142,4 @@ class KotlinEditorTextProvider : EditorTextProvider {
PsiTreeUtil.getParentOfType(element, *NOT_ACCEPTED_AS_CONTEXT_TYPES) == null PsiTreeUtil.getParentOfType(element, *NOT_ACCEPTED_AS_CONTEXT_TYPES) == null
} }
} }
} }
@@ -0,0 +1,11 @@
class Derived: Base() {
fun test() {
super.<caret>test()
}
}
open class Base {
fun test() {}
}
// EXPECTED: null
@@ -4,4 +4,4 @@ class MyClass {
} }
} }
// EXPECTED: null // EXPECTED: this
@@ -0,0 +1,7 @@
class MyClass {
fun test() {
<caret>this.test()
}
}
// EXPECTED: this
@@ -0,0 +1,9 @@
fun one() = "one"
fun String.two() = this + "two"
fun String.three() = this + "three"
fun main(args: Array<String>) {
val s = <caret>one().two().three() // Can't select 'one()' with Alt in debugger, only 'one().two()' and 'one().two().three()' are available
}
// EXPECTED: one()
@@ -0,0 +1,11 @@
class Derived: Base() {
fun test() {
super.<caret>test()
}
}
open class Base {
fun test() {}
}
// EXPECTED: super.test()
+1 -1
View File
@@ -4,4 +4,4 @@ class MyClass {
} }
} }
// EXPECTED: this.test() // EXPECTED: this
@@ -0,0 +1,7 @@
class MyClass {
fun test() {
this.<caret>test()
}
}
// EXPECTED: this.test()
@@ -79,6 +79,12 @@ public class SelectExpressionForDebuggerTestGenerated extends AbstractSelectExpr
doTest(fileName); 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") @TestMetadata("fullyQualified.kt")
public void testFullyQualified() throws Exception { public void testFullyQualified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/fullyQualified.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/fullyQualified.kt");
@@ -205,12 +211,24 @@ public class SelectExpressionForDebuggerTestGenerated extends AbstractSelectExpr
doTest(fileName); 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") @TestMetadata("this.kt")
public void testThis() throws Exception { public void testThis() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/this.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/this.kt");
doTest(fileName); 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") @TestMetadata("thisWithLabel.kt")
public void testThisWithLabel() throws Exception { public void testThisWithLabel() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/thisWithLabel.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/thisWithLabel.kt");
@@ -340,12 +358,24 @@ public class SelectExpressionForDebuggerTestGenerated extends AbstractSelectExpr
doTestWoMethodCalls(fileName); 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") @TestMetadata("this.kt")
public void testThis() throws Exception { public void testThis() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/this.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/this.kt");
doTestWoMethodCalls(fileName); 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") @TestMetadata("thisWithLabel.kt")
public void testThisWithLabel() throws Exception { public void testThisWithLabel() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/thisWithLabel.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/selectExpression/disallowMethodCalls/thisWithLabel.kt");