Redundant companion reference: fix false positive when companion has same name member as companion name
#KT-36707 Fixed
This commit is contained in:
committed by
Vladimir Dolzhenko
parent
98ce49ba73
commit
19093e2e02
+19
-7
@@ -12,6 +12,7 @@ import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
@@ -50,19 +52,22 @@ class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
||||
companion object {
|
||||
fun isRedundantCompanionReference(reference: KtReferenceExpression): Boolean {
|
||||
val parent = reference.parent as? KtDotQualifiedExpression ?: return false
|
||||
val grandParent = parent.parent
|
||||
val selectorExpression = parent.selectorExpression
|
||||
if (reference == selectorExpression && parent.parent !is KtDotQualifiedExpression) return false
|
||||
if (reference == selectorExpression && grandParent !is KtDotQualifiedExpression) return false
|
||||
if (parent.getStrictParentOfType<KtImportDirective>() != null) return false
|
||||
|
||||
val objectDeclaration = reference.mainReference.resolve() as? KtObjectDeclaration ?: return false
|
||||
if (!objectDeclaration.isCompanion()) return false
|
||||
if (reference.text != objectDeclaration.name) return false
|
||||
|
||||
val context = reference.analyze()
|
||||
val referenceText = reference.text
|
||||
if (referenceText != objectDeclaration.name) return false
|
||||
if (reference != selectorExpression && referenceText == (selectorExpression as? KtNameReferenceExpression)?.text) return false
|
||||
|
||||
val containingClass = objectDeclaration.containingClass() ?: return false
|
||||
if (reference.containingClass() != containingClass && reference == parent.receiverExpression) return false
|
||||
val containingClassDescriptor = containingClass.descriptor as? ClassDescriptor ?: return false
|
||||
val context = reference.analyze()
|
||||
val containingClassDescriptor =
|
||||
context[BindingContext.DECLARATION_TO_DESCRIPTOR, containingClass] as? ClassDescriptor ?: return false
|
||||
when (val selectorDescriptor = selectorExpression?.getResolvedCall(context)?.resultingDescriptor) {
|
||||
is PropertyDescriptor -> {
|
||||
val name = selectorDescriptor.name
|
||||
@@ -89,11 +94,18 @@ class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
||||
?.mainReference?.resolveToDescriptors(context)?.firstOrNull()
|
||||
?.let { if (it != containingClassDescriptor) return false }
|
||||
|
||||
val grandParent = parent.parent as? KtQualifiedExpression
|
||||
if (grandParent != null) {
|
||||
if (grandParent is KtQualifiedExpression) {
|
||||
val grandParentDescriptor = grandParent.getResolvedCall(context)?.resultingDescriptor ?: return false
|
||||
if (grandParentDescriptor is ConstructorDescriptor || grandParentDescriptor is FakeCallableDescriptorForObject) return false
|
||||
}
|
||||
|
||||
if (selectorExpression is KtCallExpression && referenceText == selectorExpression.calleeExpression?.text) {
|
||||
val newExpression = KtPsiFactory(reference).createExpressionByPattern("$0", selectorExpression)
|
||||
val newContext = newExpression.analyzeAsReplacement(parent, context)
|
||||
val descriptor = newExpression.getResolvedCall(newContext)?.resultingDescriptor as? FunctionDescriptor
|
||||
if (descriptor?.isOperator == true) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// PROBLEM: none
|
||||
class B {
|
||||
companion object foo {
|
||||
fun foo() {}
|
||||
|
||||
operator fun invoke() {
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>foo.foo()
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
companion object foo {
|
||||
fun foo() {}
|
||||
|
||||
operator fun invoke(i: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>foo.foo()
|
||||
}
|
||||
}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
companion object foo {
|
||||
fun foo() {}
|
||||
|
||||
operator fun invoke(i: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo()
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// PROBLEM: none
|
||||
class A {
|
||||
companion object foo {
|
||||
val foo = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>foo.foo
|
||||
}
|
||||
}
|
||||
+15
@@ -6950,6 +6950,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/named.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("namedWithSameNameFunction.kt")
|
||||
public void testNamedWithSameNameFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/namedWithSameNameFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("namedWithSameNameFunction2.kt")
|
||||
public void testNamedWithSameNameFunction2() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/namedWithSameNameFunction2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("namedWithSameNameProperty.kt")
|
||||
public void testNamedWithSameNameProperty() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/namedWithSameNameProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notApplicableCollision.kt")
|
||||
public void testNotApplicableCollision() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision.kt");
|
||||
|
||||
Reference in New Issue
Block a user