Checking for different receiver in implicit calls. They are considered not recursive.
This commit is contained in:
+22
-14
@@ -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<JetClassOrObject>()) {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user