Process only correct implicit receivers
This commit is contained in:
@@ -38,7 +38,10 @@ import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -256,8 +259,14 @@ abstract class Slicer(
|
|||||||
val receiverPseudoValue = instruction.outputValue
|
val receiverPseudoValue = instruction.outputValue
|
||||||
pseudocode.getUsages(receiverPseudoValue).forEach { receiverUseInstruction ->
|
pseudocode.getUsages(receiverPseudoValue).forEach { receiverUseInstruction ->
|
||||||
if (receiverUseInstruction is KtElementInstruction) {
|
if (receiverUseInstruction is KtElementInstruction) {
|
||||||
// TODO: make sure it processes correct receiver!!
|
receiverPseudoValue.processIfReceiverValue(
|
||||||
receiverPseudoValue.processIfReceiverValue(receiverUseInstruction, mode)
|
receiverUseInstruction,
|
||||||
|
mode,
|
||||||
|
filter = { receiverValue, resolvedCall ->
|
||||||
|
receiverValue == resolvedCall.extensionReceiver &&
|
||||||
|
(receiverValue as? ImplicitReceiver)?.declarationDescriptor == callableDescriptor
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,9 +274,15 @@ abstract class Slicer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun PseudoValue.processIfReceiverValue(instruction: KtElementInstruction, mode: KotlinSliceAnalysisMode): Boolean {
|
protected fun PseudoValue.processIfReceiverValue(
|
||||||
|
instruction: KtElementInstruction,
|
||||||
|
mode: KotlinSliceAnalysisMode,
|
||||||
|
filter: (ReceiverValue, ResolvedCall<out CallableDescriptor>) -> Boolean = { _, _ -> true }
|
||||||
|
): Boolean {
|
||||||
val receiverValue = (instruction as? InstructionWithReceivers)?.receiverValues?.get(this) ?: return false
|
val receiverValue = (instruction as? InstructionWithReceivers)?.receiverValues?.get(this) ?: return false
|
||||||
val resolvedCall = instruction.element.resolveToCall() ?: return true
|
val resolvedCall = instruction.element.resolveToCall() ?: return true
|
||||||
|
if (!filter(receiverValue, resolvedCall)) return true
|
||||||
|
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
|
|
||||||
if (descriptor.isImplicitInvokeFunction()) {
|
if (descriptor.isImplicitInvokeFunction()) {
|
||||||
|
|||||||
+14
-8
@@ -1,13 +1,19 @@
|
|||||||
// FLOW: OUT
|
// FLOW: OUT
|
||||||
|
|
||||||
fun Any.extensionFun(): Any {
|
class C {
|
||||||
return this
|
fun Int.outer() {
|
||||||
}
|
fun String.stringExtensionFun() = this
|
||||||
|
fun Int.intExtensionFun() = this
|
||||||
|
fun C.cExtensionFun() = this
|
||||||
|
|
||||||
fun String.foo() {
|
fun String.foo() {
|
||||||
val v = extensionFun()
|
val string = stringExtensionFun()
|
||||||
}
|
val int = intExtensionFun()
|
||||||
|
val c = cExtensionFun()
|
||||||
|
}
|
||||||
|
|
||||||
fun main() {
|
fun bar() {
|
||||||
<caret>"A".foo()
|
<caret>"A".foo()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
12 <bold>"A"</bold>.foo()
|
16 <bold>"A"</bold>.foo()
|
||||||
7 fun <bold>String</bold>.foo() {
|
9 fun <bold>String</bold>.foo() {
|
||||||
3 fun <bold>Any</bold>.extensionFun(): Any {
|
5 fun <bold>String</bold>.stringExtensionFun() = this
|
||||||
4 return <bold>this</bold>
|
5 fun String.stringExtensionFun() = <bold>this</bold>
|
||||||
3 fun Any.<bold>extensionFun(): Any {</bold>
|
5 fun String.<bold>stringExtensionFun() = this</bold>
|
||||||
8 val v = <bold>extensionFun()</bold>
|
10 val string = <bold>stringExtensionFun()</bold>
|
||||||
8 val <bold>v = extensionFun()</bold>
|
10 val <bold>string = stringExtensionFun()</bold>
|
||||||
|
|||||||
Reference in New Issue
Block a user