Skip to content

Commit 4c5bfae

Browse files
Evgeny GerashchenkoEvgeny Gerashchenko
authored andcommitted
Checking for different receiver in implicit calls. They are considered not recursive.
1 parent 01b8718 commit 4c5bfae

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRecursiveCallLineMarkerProvider.kt

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer
2424
import com.intellij.openapi.progress.ProgressManager
2525
import com.intellij.psi.PsiDocumentManager
2626
import com.intellij.psi.PsiElement
27+
import org.jetbrains.kotlin.descriptors.ClassDescriptor
28+
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
2729
import org.jetbrains.kotlin.idea.caches.resolve.analyze
2830
import org.jetbrains.kotlin.psi.*
29-
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
3031
import org.jetbrains.kotlin.psi.psiUtil.parents
3132
import org.jetbrains.kotlin.resolve.BindingContext
3233
import org.jetbrains.kotlin.resolve.calls.callUtil.isInlined
3334
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
35+
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
36+
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver
3437
import java.util.HashSet
3538

3639
public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider {
@@ -73,22 +76,27 @@ public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider {
7376

7477
if (resolvedCall.getCandidateDescriptor().getOriginal() != enclosingFunctionDescriptor) return false
7578

76-
val extensionReceiver = resolvedCall.getExtensionReceiver()
77-
if (extensionReceiver is ExpressionReceiver) {
78-
val thisTarget = (extensionReceiver.getExpression() as? JetThisExpression)?.getInstanceReference()?.getReference()?.resolve()
79-
if (thisTarget != enclosingFunction) {
80-
return false
81-
}
82-
}
83-
84-
val dispatchReceiver = resolvedCall.getDispatchReceiver()
85-
if (dispatchReceiver is ExpressionReceiver) {
86-
val thisTarget = (dispatchReceiver.getExpression() as? JetThisExpression)?.getInstanceReference()?.getReference()?.resolve()
87-
if (thisTarget != enclosingFunction.getNonStrictParentOfType<JetClassOrObject>()) {
88-
return false
79+
fun isDifferentReceiver(receiver: ReceiverValue): Boolean {
80+
val receiverOwner =
81+
when (receiver) {
82+
is ExpressionReceiver -> {
83+
val thisRef = (receiver.getExpression() as? JetThisExpression)?.getInstanceReference() ?: return true
84+
bindingContext[BindingContext.REFERENCE_TARGET, thisRef] ?: return true
85+
}
86+
87+
is ThisReceiver -> receiver.getDeclarationDescriptor()
88+
else -> return false
89+
}
90+
91+
return when (receiverOwner) {
92+
is SimpleFunctionDescriptor -> receiverOwner != enclosingFunctionDescriptor
93+
is ClassDescriptor -> receiverOwner != enclosingFunctionDescriptor.getContainingDeclaration()
94+
else -> throw IllegalStateException("Unexpected receiver owner: $receiverOwner")
8995
}
9096
}
9197

98+
if (isDifferentReceiver(resolvedCall.getExtensionReceiver())) return false
99+
if (isDifferentReceiver(resolvedCall.getDispatchReceiver())) return false
92100
return true
93101
}
94102

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
private fun Any.foo() {
2+
with("different extension receiver") {
3+
foo()
4+
}
5+
}
6+
7+
8+
class Klass(p: String) {
9+
private fun bar() {
10+
with(Klass("different dispatch receiver")) {
11+
bar()
12+
}
13+
}
14+
}

idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ public void testConventionCall() throws Exception {
195195
doTest(fileName);
196196
}
197197

198+
@TestMetadata("differentImplicitReceiver.kt")
199+
public void testDifferentImplicitReceiver() throws Exception {
200+
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/differentImplicitReceiver.kt");
201+
doTest(fileName);
202+
}
203+
198204
@TestMetadata("extension.kt")
199205
public void testExtension() throws Exception {
200206
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/extension.kt");

0 commit comments

Comments
 (0)