diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java index 422ec0d83c3..a8bfc98b21b 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java @@ -461,6 +461,23 @@ public class KotlinIntroduceVariableHandler extends KotlinIntroduceHandlerBase { @Override public void visitExpression(@NotNull JetExpression expression) { if (PsiEquivalenceUtil.areElementsEquivalent(expression, actualExpression, null, new Comparator() { + private boolean compareCalleesAndReceivers(@NotNull ResolvedCall rc1, @NotNull ResolvedCall rc2) { + if (rc1.getResultingDescriptor() != rc2.getResultingDescriptor() || + rc1.getExplicitReceiverKind() != rc2.getExplicitReceiverKind()) return false; + + switch (rc1.getExplicitReceiverKind()) { + case NO_EXPLICIT_RECEIVER: + return rc1.getReceiverArgument() == rc2.getReceiverArgument() + && rc1.getThisObject() == rc2.getThisObject(); + case RECEIVER_ARGUMENT: + return rc1.getThisObject() == rc2.getThisObject(); + case THIS_OBJECT: + return rc1.getReceiverArgument() == rc2.getReceiverArgument(); + default: + return true; + } + } + @Override public int compare(@NotNull PsiElement element1, @NotNull PsiElement element2) { if (element1.getNode().getElementType() == JetTokens.IDENTIFIER && @@ -472,12 +489,7 @@ public class KotlinIntroduceVariableHandler extends KotlinIntroduceHandlerBase { ResolvedCall rc1 = bindingContext.get(BindingContext.RESOLVED_CALL, expr1); ResolvedCall rc2 = bindingContext.get(BindingContext.RESOLVED_CALL, expr2); - if (rc1 == null || rc2 == null) return rc1 == rc2 ? 0 : 1; - - return rc1.getResultingDescriptor() == rc2.getResultingDescriptor() - && rc1.getExplicitReceiverKind() == rc2.getExplicitReceiverKind() - && rc1.getReceiverArgument() == rc2.getReceiverArgument() - && rc1.getThisObject() == rc2.getThisObject() ? 0 : 1; + return (rc1 != null && rc2 != null) && compareCalleesAndReceivers(rc1, rc2) ? 0 : 1; } } if (!element1.textMatches(element2)) { diff --git a/idea/testData/refactoring/introduceVariable/NoExplicitReceivers.kt b/idea/testData/refactoring/introduceVariable/NoExplicitReceivers.kt new file mode 100644 index 00000000000..25aaada9d5c --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/NoExplicitReceivers.kt @@ -0,0 +1,12 @@ +fun main(args: Array) { + with(A()) { + println(prop) + println(prop) + } +} + +class A { + val prop = 1 +} + +public inline fun with(receiver: T, f: T.() -> R): R = receiver.f() \ No newline at end of file diff --git a/idea/testData/refactoring/introduceVariable/NoExplicitReceivers.kt.after b/idea/testData/refactoring/introduceVariable/NoExplicitReceivers.kt.after new file mode 100644 index 00000000000..f7a5564a17e --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/NoExplicitReceivers.kt.after @@ -0,0 +1,13 @@ +fun main(args: Array) { + with(A()) { + val i = prop + println(i) + println(i) + } +} + +class A { + val prop = 1 +} + +public inline fun with(receiver: T, f: T.() -> R): R = receiver.f() \ No newline at end of file diff --git a/idea/testData/refactoring/introduceVariable/NoExplicitReceiversUnresolved.kt b/idea/testData/refactoring/introduceVariable/NoExplicitReceiversUnresolved.kt new file mode 100644 index 00000000000..80f82ada789 --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/NoExplicitReceiversUnresolved.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + println(a1) + println(a2) +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceVariable/NoExplicitReceiversUnresolved.kt.after b/idea/testData/refactoring/introduceVariable/NoExplicitReceiversUnresolved.kt.after new file mode 100644 index 00000000000..0a35a0444ac --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/NoExplicitReceiversUnresolved.kt.after @@ -0,0 +1,5 @@ +fun main(args: Array) { + val a = a1 + println(a) + println(a2) +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt b/idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt new file mode 100644 index 00000000000..a1d5d227d81 --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt @@ -0,0 +1,9 @@ +fun main(args: Array) { + val myA = A() + println(myA.prop) + println(myA.prop) +} + +class A { + val prop = 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt.after b/idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt.after new file mode 100644 index 00000000000..9e04e8bcfcb --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt.after @@ -0,0 +1,10 @@ +fun main(args: Array) { + val myA = A() + val i = myA.prop + println(i) + println(i) +} + +class A { + val prop = 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceVariable/TwoExplicitReceivers.kt b/idea/testData/refactoring/introduceVariable/TwoExplicitReceivers.kt new file mode 100644 index 00000000000..2bebed4dcc7 --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/TwoExplicitReceivers.kt @@ -0,0 +1,12 @@ +class Bar { +} + +class Foo() { + fun Bar.invoke(): Int = 1 +} + +fun main(args: Array) { + val f = Foo() + println(Bar().f()) + println(Bar().f()) +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceVariable/TwoExplicitReceivers.kt.after b/idea/testData/refactoring/introduceVariable/TwoExplicitReceivers.kt.after new file mode 100644 index 00000000000..31349566aed --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/TwoExplicitReceivers.kt.after @@ -0,0 +1,13 @@ +class Bar { +} + +class Foo() { + fun Bar.invoke(): Int = 1 +} + +fun main(args: Array) { + val f = Foo() + val i = Bar().f() + println(i) + println(i) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java index 1769329e2d3..617e11a6b3c 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java @@ -133,11 +133,26 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/noConflictWithInnerVariable.kt"); } + @TestMetadata("NoExplicitReceivers.kt") + public void testNoExplicitReceivers() throws Exception { + doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/NoExplicitReceivers.kt"); + } + + @TestMetadata("NoExplicitReceiversUnresolved.kt") + public void testNoExplicitReceiversUnresolved() throws Exception { + doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/NoExplicitReceiversUnresolved.kt"); + } + @TestMetadata("nonEquivalentReceivers.kt") public void testNonEquivalentReceivers() throws Exception { doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/nonEquivalentReceivers.kt"); } + @TestMetadata("OneExplicitReceiver.kt") + public void testOneExplicitReceiver() throws Exception { + doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt"); + } + @TestMetadata("ReplaceOccurence.kt") public void testReplaceOccurence() throws Exception { doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/ReplaceOccurence.kt"); @@ -158,6 +173,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/StringInjection.kt"); } + @TestMetadata("TwoExplicitReceivers.kt") + public void testTwoExplicitReceivers() throws Exception { + doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/TwoExplicitReceivers.kt"); + } + @TestMetadata("WhenAddBlock.kt") public void testWhenAddBlock() throws Exception { doIntroduceVariableTest("idea/testData/refactoring/introduceVariable/WhenAddBlock.kt");