Add explicit this: fix false negative on variable call

^KT-39929 Fixed

Original commit: 277ceaaf669dc1dd9ee2c4997360f7c32671deb2

GitOrigin-RevId: 4e3fc1624eff48a2d39312b8c9de16a94444c4fe
This commit is contained in:
Toshiaki Kameyama
2020-11-20 10:34:34 +03:00
committed by intellij-monorepo-bot
parent 5fddd9cf67
commit 06003b1cc4
6 changed files with 58 additions and 5 deletions
@@ -10,12 +10,15 @@ import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
import org.jetbrains.kotlin.idea.util.getFactoryForImplicitReceiverWithSubtypeOf
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
class ImplicitThisInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = object : KtVisitorVoid() {
@@ -41,10 +44,10 @@ class ImplicitThisInspection : AbstractKotlinInspection() {
val context = reference.analyze()
val scope = reference.getResolutionScope(context) ?: return
val descriptor = reference.getCallableDescriptor() ?: return
val receiverDescriptor = descriptor.extensionReceiverParameter
?: descriptor.dispatchReceiverParameter
?: return
val resolvedCall = reference.getResolvedCall(context) ?: return
val variableDescriptor = (resolvedCall as? VariableAsFunctionResolvedCall)?.variableCall?.resultingDescriptor
val callableDescriptor = resolvedCall.resultingDescriptor
val receiverDescriptor = variableDescriptor?.receiverDescriptor() ?: callableDescriptor.receiverDescriptor() ?: return
val receiverType = receiverDescriptor.type
val expressionFactory = scope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType) ?: return
@@ -59,6 +62,10 @@ class ImplicitThisInspection : AbstractKotlinInspection() {
)
}
private fun CallableDescriptor.receiverDescriptor(): ReceiverParameterDescriptor? {
return extensionReceiverParameter ?: dispatchReceiverParameter
}
private fun KtExpression.isSelectorOfDotQualifiedExpression(): Boolean {
val parent = parent
return parent is KtDotQualifiedExpression && parent.selectorExpression == this
@@ -4885,6 +4885,16 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
runTest("testData/inspectionsLocal/implicitThis/already.kt");
}
@TestMetadata("callVariableAsFunction.kt")
public void testCallVariableAsFunction() throws Exception {
runTest("testData/inspectionsLocal/implicitThis/callVariableAsFunction.kt");
}
@TestMetadata("callVariableAsFunction2.kt")
public void testCallVariableAsFunction2() throws Exception {
runTest("testData/inspectionsLocal/implicitThis/callVariableAsFunction2.kt");
}
@TestMetadata("function.kt")
public void testFunction() throws Exception {
runTest("testData/inspectionsLocal/implicitThis/function.kt");
@@ -0,0 +1,11 @@
class Foo {
operator fun invoke() {}
}
class Bar {
val foo = Foo()
}
fun Bar.test() {
<caret>foo()
}
@@ -0,0 +1,11 @@
class Foo {
operator fun invoke() {}
}
class Bar {
val foo = Foo()
}
fun Bar.test() {
this.foo()
}
@@ -0,0 +1,7 @@
class Bar {
val bar: () -> Unit = {}
}
fun Bar.test() {
<caret>bar()
}
@@ -0,0 +1,7 @@
class Bar {
val bar: () -> Unit = {}
}
fun Bar.test() {
this.bar()
}