Explicit this inspection: fix false positive with subclass and extension
#KT-27550 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
1dbe487077
commit
2efbc6e914
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
|
||||||
class ExplicitThisInspection : AbstractKotlinInspection() {
|
class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
|||||||
val scope = expression.getResolutionScope(context) ?: return
|
val scope = expression.getResolutionScope(context) ?: return
|
||||||
|
|
||||||
val referenceExpression = reference as? KtNameReferenceExpression ?: reference.getChildOfType() ?: 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
|
//we avoid overload-related problems by enforcing that there is only one candidate
|
||||||
val name = referenceExpression.getReferencedNameAsName()
|
val name = referenceExpression.getReferencedNameAsName()
|
||||||
@@ -62,10 +64,11 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
|||||||
if (referenceExpression.getCallableDescriptor() is SyntheticJavaPropertyDescriptor) {
|
if (referenceExpression.getCallableDescriptor() is SyntheticJavaPropertyDescriptor) {
|
||||||
if (candidates.map { it.containingDeclaration }.distinct().size != 1) return
|
if (candidates.map { it.containingDeclaration }.distinct().size != 1) return
|
||||||
} else {
|
} 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 expressionFactory = scope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType) ?: return
|
||||||
|
|
||||||
val label = thisExpression.getLabelName() ?: ""
|
val label = thisExpression.getLabelName() ?: ""
|
||||||
@@ -85,9 +88,7 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
|||||||
|
|
||||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
val thisExpression = descriptor.psiElement as? KtThisExpression ?: return
|
val thisExpression = descriptor.psiElement as? KtThisExpression ?: return
|
||||||
val parent = thisExpression.parent
|
when (val parent = thisExpression.parent) {
|
||||||
|
|
||||||
when (parent) {
|
|
||||||
is KtDotQualifiedExpression -> parent.replace(parent.selectorExpression ?: return)
|
is KtDotQualifiedExpression -> parent.replace(parent.selectorExpression ?: return)
|
||||||
is KtCallableReferenceExpression -> thisExpression.delete()
|
is KtCallableReferenceExpression -> thisExpression.delete()
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -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
|
||||||
|
}
|
||||||
+12
@@ -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
|
||||||
|
}
|
||||||
+11
@@ -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
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
open class Foo
|
||||||
|
|
||||||
|
class SubFoo : Foo()
|
||||||
|
|
||||||
|
val SubFoo.bar: String get() = ""
|
||||||
|
|
||||||
|
fun SubFoo.func() = Foo().apply {
|
||||||
|
bar
|
||||||
|
}
|
||||||
+15
@@ -3758,6 +3758,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverInstanceExtension.kt");
|
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")
|
@TestMetadata("differentReceiverType.kt")
|
||||||
public void testDifferentReceiverType() throws Exception {
|
public void testDifferentReceiverType() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverType.kt");
|
runTest("idea/testData/inspectionsLocal/explicitThis/differentReceiverType.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user