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.psiUtil.forEachDescendantOfType
|
||||
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.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
@@ -256,8 +259,14 @@ abstract class Slicer(
|
||||
val receiverPseudoValue = instruction.outputValue
|
||||
pseudocode.getUsages(receiverPseudoValue).forEach { receiverUseInstruction ->
|
||||
if (receiverUseInstruction is KtElementInstruction) {
|
||||
// TODO: make sure it processes correct receiver!!
|
||||
receiverPseudoValue.processIfReceiverValue(receiverUseInstruction, mode)
|
||||
receiverPseudoValue.processIfReceiverValue(
|
||||
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 resolvedCall = instruction.element.resolveToCall() ?: return true
|
||||
if (!filter(receiverValue, resolvedCall)) return true
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
|
||||
if (descriptor.isImplicitInvokeFunction()) {
|
||||
|
||||
+14
-8
@@ -1,13 +1,19 @@
|
||||
// FLOW: OUT
|
||||
|
||||
fun Any.extensionFun(): Any {
|
||||
return this
|
||||
}
|
||||
class C {
|
||||
fun Int.outer() {
|
||||
fun String.stringExtensionFun() = this
|
||||
fun Int.intExtensionFun() = this
|
||||
fun C.cExtensionFun() = this
|
||||
|
||||
fun String.foo() {
|
||||
val v = extensionFun()
|
||||
}
|
||||
fun String.foo() {
|
||||
val string = stringExtensionFun()
|
||||
val int = intExtensionFun()
|
||||
val c = cExtensionFun()
|
||||
}
|
||||
|
||||
fun main() {
|
||||
<caret>"A".foo()
|
||||
fun bar() {
|
||||
<caret>"A".foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
12 <bold>"A"</bold>.foo()
|
||||
7 fun <bold>String</bold>.foo() {
|
||||
3 fun <bold>Any</bold>.extensionFun(): Any {
|
||||
4 return <bold>this</bold>
|
||||
3 fun Any.<bold>extensionFun(): Any {</bold>
|
||||
8 val v = <bold>extensionFun()</bold>
|
||||
8 val <bold>v = extensionFun()</bold>
|
||||
16 <bold>"A"</bold>.foo()
|
||||
9 fun <bold>String</bold>.foo() {
|
||||
5 fun <bold>String</bold>.stringExtensionFun() = this
|
||||
5 fun String.stringExtensionFun() = <bold>this</bold>
|
||||
5 fun String.<bold>stringExtensionFun() = this</bold>
|
||||
10 val string = <bold>stringExtensionFun()</bold>
|
||||
10 val <bold>string = stringExtensionFun()</bold>
|
||||
|
||||
Reference in New Issue
Block a user