mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin] 'Redundant explicit this' inspection: fix false negative with overloaded extension functions of Int
^KTIJ-28762 Fixed closes https://github.com/JetBrains/intellij-community/pull/2667 GitOrigin-RevId: d5f9122282ad1191011ad006821529913f4d6dd6
This commit is contained in:
committed by
intellij-monorepo-bot
parent
50bee645b4
commit
5be8877345
+18
-18
@@ -14,14 +14,15 @@ import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection
|
||||
import org.jetbrains.kotlin.idea.inspections.ExplicitThisInspection.Util.thisAsReceiverOrNull
|
||||
import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
|
||||
import org.jetbrains.kotlin.idea.intentions.receiverType
|
||||
import org.jetbrains.kotlin.idea.util.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||
@@ -39,7 +40,7 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
|
||||
object Util {
|
||||
fun KtExpression.thisAsReceiverOrNull() = when (this) {
|
||||
fun KtExpression.thisAsReceiverOrNull(): KtThisExpression? = when (this) {
|
||||
is KtCallableReferenceExpression -> receiverExpression as? KtThisExpression
|
||||
is KtDotQualifiedExpression -> receiverExpression as? KtThisExpression
|
||||
else -> null
|
||||
@@ -52,15 +53,14 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||
is KtDotQualifiedExpression -> expression.selectorExpression as? KtReferenceExpression
|
||||
else -> null
|
||||
} ?: return false
|
||||
val context = expression.analyze()
|
||||
val scope = expression.getResolutionScope(context) ?: return false
|
||||
|
||||
val referenceExpression = reference as? KtNameReferenceExpression ?: reference.getChildOfType() ?: return false
|
||||
if (context.diagnostics.forElement(referenceExpression).any { it.factory == Errors.UNRESOLVED_REFERENCE }) return false
|
||||
val receiverType = context[BindingContext.EXPRESSION_TYPE_INFO, thisExpression]?.type ?: return false
|
||||
val referenceTarget = context[BindingContext.REFERENCE_TARGET, reference.referenceExpression()]
|
||||
|
||||
//we avoid overload-related problems by enforcing that there is only one candidate
|
||||
val context = expression.analyze()
|
||||
if (context.diagnostics.forElement(referenceExpression).any { it.factory == Errors.UNRESOLVED_REFERENCE }) return false
|
||||
val scope = expression.getResolutionScope(context) ?: return false
|
||||
val receiverType = context[BindingContext.EXPRESSION_TYPE_INFO, thisExpression]?.type ?: return false
|
||||
|
||||
val referenceTarget = context[BindingContext.REFERENCE_TARGET, reference.referenceExpression()]
|
||||
val name = referenceExpression.getReferencedNameAsName()
|
||||
val candidates = if (reference is KtCallExpression
|
||||
|| (expression is KtCallableReferenceExpression && referenceTarget is FunctionDescriptor)
|
||||
@@ -70,16 +70,16 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||
} else {
|
||||
scope.getAllAccessibleVariables(name)
|
||||
}
|
||||
if (referenceExpression.getCallableDescriptor() is SyntheticJavaPropertyDescriptor) {
|
||||
if (candidates.map { it.containingDeclaration }.distinct().size != 1) return false
|
||||
} else {
|
||||
val candidate = candidates.singleOrNull() ?: return false
|
||||
val extensionType = candidate.extensionReceiverParameter?.type
|
||||
if (extensionType != null && extensionType != receiverType && receiverType.isSubtypeOf(extensionType)) return false
|
||||
}
|
||||
if (candidates.any { it.receiverType() == null }) return false
|
||||
|
||||
val implicitThis = reference.getResolutionScope(context)?.getImplicitReceiversHierarchy()?.firstOrNull() ?: return false
|
||||
val explicitThis = thisExpression.getResolvedCall(context)?.resultingDescriptor ?: return false
|
||||
val candidate = (if (implicitThis == explicitThis) candidates.firstOrNull() else candidates.singleOrNull()) ?: return false
|
||||
|
||||
val extensionType = candidate.extensionReceiverParameter?.type
|
||||
if (extensionType != null && extensionType != receiverType && receiverType.isSubtypeOf(extensionType)) return false
|
||||
|
||||
val expressionFactory = scope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType) ?: return false
|
||||
|
||||
val label = thisExpression.getLabelName() ?: ""
|
||||
return expressionFactory.matchesLabel(label)
|
||||
}
|
||||
|
||||
+10
@@ -5166,11 +5166,21 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
|
||||
runTest("testData/inspectionsLocal/explicitThis/nestedReceiversExtensionDifferentParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overloadedIntFunction.kt")
|
||||
public void testOverloadedIntFunction() throws Exception {
|
||||
runTest("testData/inspectionsLocal/explicitThis/overloadedIntFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
runTest("testData/inspectionsLocal/explicitThis/property.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyNamedCode.kt")
|
||||
public void testPropertyNamedCode() throws Exception {
|
||||
runTest("testData/inspectionsLocal/explicitThis/propertyNamedCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyReference.kt")
|
||||
public void testPropertyReference() throws Exception {
|
||||
runTest("testData/inspectionsLocal/explicitThis/propertyReference.kt");
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fun Int.foo(): Int {
|
||||
return <caret>this.times(3)
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fun Int.foo(): Int {
|
||||
return times(3)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A(private var code: String) {
|
||||
fun foo() {
|
||||
<caret>this.code
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class A(private var code: String) {
|
||||
fun foo() {
|
||||
code
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user