Explicit this inspection: fix false positive with subclass and extension

#KT-27550 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-06-21 17:10:31 +09:00
committed by Mikhail Glukhikh
parent 1dbe487077
commit 2efbc6e914
6 changed files with 67 additions and 5 deletions
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
class ExplicitThisInspection : AbstractKotlinInspection() {
@@ -55,6 +56,7 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
val scope = expression.getResolutionScope(context) ?: return
val referenceExpression = reference as? KtNameReferenceExpression ?: reference.getChildOfType() ?: return
val receiverType = context[BindingContext.EXPRESSION_TYPE_INFO, thisExpression]?.type ?: return
//we avoid overload-related problems by enforcing that there is only one candidate
val name = referenceExpression.getReferencedNameAsName()
@@ -62,10 +64,11 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
if (referenceExpression.getCallableDescriptor() is SyntheticJavaPropertyDescriptor) {
if (candidates.map { it.containingDeclaration }.distinct().size != 1) return
} else {
if (candidates.size != 1) return
val candidate = candidates.singleOrNull() ?: return
val extensionType = candidate.extensionReceiverParameter?.type
if (extensionType != null && extensionType != receiverType && receiverType.isSubtypeOf(extensionType)) return
}
val receiverType = context[BindingContext.EXPRESSION_TYPE_INFO, thisExpression]?.type ?: return
val expressionFactory = scope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType) ?: return
val label = thisExpression.getLabelName() ?: ""
@@ -85,9 +88,7 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val thisExpression = descriptor.psiElement as? KtThisExpression ?: return
val parent = thisExpression.parent
when (parent) {
when (val parent = thisExpression.parent) {
is KtDotQualifiedExpression -> parent.replace(parent.selectorExpression ?: return)
is KtCallableReferenceExpression -> thisExpression.delete()
}
@@ -0,0 +1,12 @@
// WITH_RUNTIME
// PROBLEM: none
open class Foo
class SubFoo : Foo()
val Foo.bar: String get() = ""
fun Foo.func() = Foo().apply {
<caret>this@func.bar
}
@@ -0,0 +1,12 @@
// WITH_RUNTIME
// PROBLEM: none
open class Foo
class SubFoo : Foo()
val Foo.bar: String get() = ""
fun SubFoo.func() = Foo().apply {
<caret>this@func.bar
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
open class Foo
class SubFoo : Foo()
val SubFoo.bar: String get() = ""
fun SubFoo.func() = Foo().apply {
<caret>this@func.bar
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
open class Foo
class SubFoo : Foo()
val SubFoo.bar: String get() = ""
fun SubFoo.func() = Foo().apply {
bar
}
@@ -3758,6 +3758,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverInstanceExtension.kt");
}
@TestMetadata("differentReceiverInstanceExtension2.kt")
public void testDifferentReceiverInstanceExtension2() throws Exception {
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverInstanceExtension2.kt");
}
@TestMetadata("differentReceiverInstanceExtension3.kt")
public void testDifferentReceiverInstanceExtension3() throws Exception {
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverInstanceExtension3.kt");
}
@TestMetadata("differentReceiverInstanceExtension4.kt")
public void testDifferentReceiverInstanceExtension4() throws Exception {
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverInstanceExtension4.kt");
}
@TestMetadata("differentReceiverType.kt")
public void testDifferentReceiverType() throws Exception {
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverType.kt");