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.openapi.progress.ProgressManager
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiElement
|
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.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isInlined
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isInlined
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
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
|
import java.util.HashSet
|
||||||
|
|
||||||
public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider {
|
public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider {
|
||||||
@@ -73,22 +76,27 @@ public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider {
|
|||||||
|
|
||||||
if (resolvedCall.getCandidateDescriptor().getOriginal() != enclosingFunctionDescriptor) return false
|
if (resolvedCall.getCandidateDescriptor().getOriginal() != enclosingFunctionDescriptor) return false
|
||||||
|
|
||||||
val extensionReceiver = resolvedCall.getExtensionReceiver()
|
fun isDifferentReceiver(receiver: ReceiverValue): Boolean {
|
||||||
if (extensionReceiver is ExpressionReceiver) {
|
val receiverOwner =
|
||||||
val thisTarget = (extensionReceiver.getExpression() as? JetThisExpression)?.getInstanceReference()?.getReference()?.resolve()
|
when (receiver) {
|
||||||
if (thisTarget != enclosingFunction) {
|
is ExpressionReceiver -> {
|
||||||
return false
|
val thisRef = (receiver.getExpression() as? JetThisExpression)?.getInstanceReference() ?: return true
|
||||||
}
|
bindingContext[BindingContext.REFERENCE_TARGET, thisRef] ?: return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val dispatchReceiver = resolvedCall.getDispatchReceiver()
|
is ThisReceiver -> receiver.getDeclarationDescriptor()
|
||||||
if (dispatchReceiver is ExpressionReceiver) {
|
else -> return false
|
||||||
val thisTarget = (dispatchReceiver.getExpression() as? JetThisExpression)?.getInstanceReference()?.getReference()?.resolve()
|
}
|
||||||
if (thisTarget != enclosingFunction.getNonStrictParentOfType<JetClassOrObject>()) {
|
|
||||||
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
|
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);
|
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")
|
@TestMetadata("extension.kt")
|
||||||
public void testExtension() throws Exception {
|
public void testExtension() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/extension.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/extension.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user