diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRecursiveCallLineMarkerProvider.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRecursiveCallLineMarkerProvider.kt index d66b301d03d..f2051e5ebfa 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRecursiveCallLineMarkerProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRecursiveCallLineMarkerProvider.kt @@ -24,13 +24,16 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer import com.intellij.openapi.progress.ProgressManager import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.isInlined import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver import java.util.HashSet public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider { @@ -73,22 +76,27 @@ public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider { if (resolvedCall.getCandidateDescriptor().getOriginal() != enclosingFunctionDescriptor) return false - val extensionReceiver = resolvedCall.getExtensionReceiver() - if (extensionReceiver is ExpressionReceiver) { - val thisTarget = (extensionReceiver.getExpression() as? JetThisExpression)?.getInstanceReference()?.getReference()?.resolve() - if (thisTarget != enclosingFunction) { - return false - } - } - - val dispatchReceiver = resolvedCall.getDispatchReceiver() - if (dispatchReceiver is ExpressionReceiver) { - val thisTarget = (dispatchReceiver.getExpression() as? JetThisExpression)?.getInstanceReference()?.getReference()?.resolve() - if (thisTarget != enclosingFunction.getNonStrictParentOfType()) { - return false + fun isDifferentReceiver(receiver: ReceiverValue): Boolean { + val receiverOwner = + when (receiver) { + is ExpressionReceiver -> { + val thisRef = (receiver.getExpression() as? JetThisExpression)?.getInstanceReference() ?: return true + bindingContext[BindingContext.REFERENCE_TARGET, thisRef] ?: return true + } + + is ThisReceiver -> receiver.getDeclarationDescriptor() + else -> return false + } + + return when (receiverOwner) { + is SimpleFunctionDescriptor -> receiverOwner != enclosingFunctionDescriptor + is ClassDescriptor -> receiverOwner != enclosingFunctionDescriptor.getContainingDeclaration() + else -> throw IllegalStateException("Unexpected receiver owner: $receiverOwner") } } + if (isDifferentReceiver(resolvedCall.getExtensionReceiver())) return false + if (isDifferentReceiver(resolvedCall.getDispatchReceiver())) return false return true } diff --git a/idea/testData/codeInsight/lineMarker/recursiveCall/differentImplicitReceiver.kt b/idea/testData/codeInsight/lineMarker/recursiveCall/differentImplicitReceiver.kt new file mode 100644 index 00000000000..04f13bd3447 --- /dev/null +++ b/idea/testData/codeInsight/lineMarker/recursiveCall/differentImplicitReceiver.kt @@ -0,0 +1,14 @@ +private fun Any.foo() { + with("different extension receiver") { + foo() + } +} + + +class Klass(p: String) { + private fun bar() { + with(Klass("different dispatch receiver")) { + bar() + } + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java index 9024c6b015d..f8e7f6f4ee6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java @@ -195,6 +195,12 @@ public class LineMarkersTestGenerated extends AbstractLineMarkersTest { doTest(fileName); } + @TestMetadata("differentImplicitReceiver.kt") + public void testDifferentImplicitReceiver() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/differentImplicitReceiver.kt"); + doTest(fileName); + } + @TestMetadata("extension.kt") public void testExtension() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/extension.kt");