diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantCompanionReferenceInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantCompanionReferenceInspection.kt index af3e3855c7e..36315906ac8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantCompanionReferenceInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantCompanionReferenceInspection.kt @@ -12,8 +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.caches.resolve.resolveToCall -import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor import org.jetbrains.kotlin.idea.util.getResolutionScope @@ -21,7 +20,10 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* 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.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces @@ -40,10 +42,12 @@ class RedundantCompanionReferenceInspection : AbstractKotlinInspection() { if (!objectDeclaration.isCompanion()) return if (expression.text != objectDeclaration.name) return + val context = expression.analyze() + val containingClass = objectDeclaration.containingClass() ?: return if (expression.containingClass() != containingClass && expression == parent.receiverExpression) return val containingClassDescriptor = containingClass.descriptor as? ClassDescriptor ?: return - val selectorDescriptor = selectorExpression?.getCallableDescriptor() + val selectorDescriptor = selectorExpression?.getResolvedCall(context)?.resultingDescriptor when (selectorDescriptor) { is PropertyDescriptor -> { val name = selectorDescriptor.name @@ -59,9 +63,13 @@ class RedundantCompanionReferenceInspection : AbstractKotlinInspection() { } } + (expression as? KtSimpleNameExpression)?.getReceiverExpression()?.getQualifiedElementSelector() + ?.mainReference?.resolveToDescriptors(context)?.firstOrNull() + ?.let { if (it != containingClassDescriptor) return } + val grandParent = parent.parent as? KtQualifiedExpression if (grandParent != null) { - val grandParentDescriptor = grandParent.resolveToCall()?.resultingDescriptor ?: return + val grandParentDescriptor = grandParent.getResolvedCall(context)?.resultingDescriptor ?: return if (grandParentDescriptor is ConstructorDescriptor || grandParentDescriptor is FakeCallableDescriptorForObject) return } diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision.kt new file mode 100644 index 00000000000..6d608b52425 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision.kt @@ -0,0 +1,12 @@ +// PROBLEM: none +package my.sample + +class Class { + companion object Class { + fun say() {} + } +} + +fun test() { + Class.say() +} diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision2.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision2.kt new file mode 100644 index 00000000000..c2cbd45d1ab --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision2.kt @@ -0,0 +1,14 @@ +// PROBLEM: none +package my.sample + +class Outer { + class Class { + companion object Class { + fun say() {} + } + } +} + +fun test() { + Outer.Class.say() +} diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicablePackage.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicablePackage.kt new file mode 100644 index 00000000000..b66cfa21c00 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantCompanionReference/notApplicablePackage.kt @@ -0,0 +1,12 @@ +// PROBLEM: none +package my.sample + +class Class { + fun test() { + my.sample.Class.say() + } + + companion object Class { + fun say() {} + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index bc8e39d576a..37a3bbc22e2 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -4662,6 +4662,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/redundantCompanionReference/named.kt"); } + @TestMetadata("notApplicableCollision.kt") + public void testNotApplicableCollision() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision.kt"); + } + + @TestMetadata("notApplicableCollision2.kt") + public void testNotApplicableCollision2() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantCompanionReference/notApplicableCollision2.kt"); + } + + @TestMetadata("notApplicablePackage.kt") + public void testNotApplicablePackage() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantCompanionReference/notApplicablePackage.kt"); + } + @TestMetadata("notCompanion.kt") public void testNotCompanion() throws Exception { runTest("idea/testData/inspectionsLocal/redundantCompanionReference/notCompanion.kt");