Shorten References: Compare resolved calls when shortening receiver of qualified call expression

#KT-13660 Fixed
This commit is contained in:
Alexey Sedunov
2016-08-31 17:27:39 +03:00
parent c1296e2134
commit cf28dd04c8
5 changed files with 32 additions and 1 deletions
+1
View File
@@ -124,6 +124,7 @@ These artifacts include extensions for the types available in the latter JDKs, s
- [`KT-13553`](https://youtrack.jetbrains.com/issue/KT-13553) Move: Do not show directory selection dialog if target directory is already specified by drag-and-drop
- [`KT-8867`](https://youtrack.jetbrains.com/issue/KT-8867) Rename: Rename all overridden members if user chooses to refactor base declaration(s)
- Pull Up: Drop 'override' modifier if moved member doesn't override anything
- [`KT-13660`](https://youtrack.jetbrains.com/issue/KT-13660) Move: Do not drop object receivers when calling variable of extension functional type
##### New features
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
@@ -428,13 +429,17 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
val selector = element.selectorExpression ?: return Skip
val callee = selector.getCalleeExpressionIfAny() as? KtReferenceExpression ?: return Skip
val targets = callee.targets(bindingContext)
val varAsFunResolvedCall = callee.getResolvedCall(bindingContext) as? VariableAsFunctionResolvedCall
if (targets.isEmpty()) return Skip
val scope = element.getResolutionScope(bindingContext, resolutionFacade)
val selectorCopy = selector.copy() as KtReferenceExpression
val newContext = selectorCopy.analyzeInContext(scope, selector)
val targetsWhenShort = (selectorCopy.getCalleeExpressionIfAny() as KtReferenceExpression).targets(newContext)
val newCallee = selectorCopy.getCalleeExpressionIfAny() as KtReferenceExpression
val targetsWhenShort = newCallee.targets(newContext)
val varAsFunResolvedCallWhenShort = newCallee.getResolvedCall(newContext) as? VariableAsFunctionResolvedCall
val targetsMatch = targetsMatch(targets, targetsWhenShort)
&& (varAsFunResolvedCall == null || resolvedCallsMatch(varAsFunResolvedCall, varAsFunResolvedCallWhenShort))
if (receiver is KtThisExpression) {
if (!targetsMatch) return Skip
@@ -471,6 +476,11 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
}
}
private fun resolvedCallsMatch(rc1: VariableAsFunctionResolvedCall?, rc2: VariableAsFunctionResolvedCall?): Boolean {
return rc1?.variableCall?.candidateDescriptor?.asString() == rc2?.variableCall?.candidateDescriptor?.asString() &&
rc1?.functionCall?.candidateDescriptor?.asString() == rc2?.functionCall?.candidateDescriptor?.asString()
}
override fun shortenElement(element: KtDotQualifiedExpression): KtElement {
return element.replace(element.selectorExpression!!) as KtElement
}
@@ -0,0 +1,7 @@
object X{ }
<selection>class Y {
fun f(op: X.()->Unit) {
X.op()
}
}</selection>
@@ -0,0 +1,7 @@
object X{ }
class Y {
fun f(op: X.()->Unit) {
X.op()
}
}
@@ -59,6 +59,12 @@ public class ShortenRefsTestGenerated extends AbstractShortenRefsTest {
doTest(fileName);
}
@TestMetadata("extensionFunctionVarInvokedWithQualifier.kt")
public void testExtensionFunctionVarInvokedWithQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/shortenRefs/extensionFunctionVarInvokedWithQualifier.kt");
doTest(fileName);
}
@TestMetadata("InterfaceInExpression.kt")
public void testInterfaceInExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/shortenRefs/InterfaceInExpression.kt");