Fix several false positives and make safer "redundant companion ref"
Don't report it on an import directive #KT-23520 Fixed Don't report it if companion nested class is referenced #KT-23519 Fixed Check companion reference both by descriptor and by name
This commit is contained in:
+13
-9
@@ -11,24 +11,28 @@ import com.intellij.codeInspection.ProblemHighlightType
|
|||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElementVisitor
|
import com.intellij.psi.PsiElementVisitor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
|
||||||
import org.jetbrains.kotlin.psi.referenceExpressionVisitor
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
|
|
||||||
class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||||
return referenceExpressionVisitor(fun(expression) {
|
return referenceExpressionVisitor(fun(expression) {
|
||||||
val parent = expression.parent as? KtDotQualifiedExpression ?: return
|
val parent = expression.parent as? KtDotQualifiedExpression ?: return
|
||||||
if (expression == parent.selectorExpression && parent.parent !is KtDotQualifiedExpression) return
|
if (expression == parent.selectorExpression && parent.parent !is KtDotQualifiedExpression) return
|
||||||
|
if (parent.getStrictParentOfType<KtImportDirective>() != null) return
|
||||||
|
|
||||||
val descriptor = (expression.mainReference.resolve() as? KtObjectDeclaration)?.descriptor ?: return
|
val objectDeclaration = expression.mainReference.resolve() as? KtObjectDeclaration ?: return
|
||||||
if (!DescriptorUtils.isCompanionObject(descriptor)) return
|
if (!objectDeclaration.isCompanion()) return
|
||||||
|
if (expression.text != objectDeclaration.name) return
|
||||||
|
|
||||||
if (expression == parent.receiverExpression && expression.text == descriptor.containingDeclaration?.name?.asString()) return
|
val grandParent = parent.parent as? KtQualifiedExpression
|
||||||
|
if (grandParent != null) {
|
||||||
|
val grandParentDescriptor = grandParent.resolveToCall()?.resultingDescriptor ?: return
|
||||||
|
if (grandParentDescriptor is ConstructorDescriptor) return
|
||||||
|
}
|
||||||
|
|
||||||
holder.registerProblem(
|
holder.registerProblem(
|
||||||
expression,
|
expression,
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Owner {
|
||||||
|
companion object {
|
||||||
|
class InCompanion {
|
||||||
|
class Nested
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val y = Owner.<caret>Companion.InCompanion.Nested()
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Owner {
|
||||||
|
companion object {
|
||||||
|
class InCompanion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val y = Owner.<caret>Companion.InCompanion()
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
import Owner.<caret>Companion.some
|
||||||
|
|
||||||
|
class Owner {
|
||||||
|
companion object {
|
||||||
|
const val some = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class User {
|
||||||
|
val anything = some
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class C {
|
||||||
|
companion object Obj {
|
||||||
|
fun create() = C()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
C.<caret>Obj.create()
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class C {
|
||||||
|
companion object Obj {
|
||||||
|
fun create() = C()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
C.create()
|
||||||
|
}
|
||||||
+24
@@ -2553,6 +2553,18 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("companionDoubleNested.kt")
|
||||||
|
public void testCompanionDoubleNested() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/companionDoubleNested.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("companionNested.kt")
|
||||||
|
public void testCompanionNested() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/companionNested.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("directCompanion.kt")
|
@TestMetadata("directCompanion.kt")
|
||||||
public void testDirectCompanion() throws Exception {
|
public void testDirectCompanion() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt");
|
||||||
@@ -2565,12 +2577,24 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("import.kt")
|
||||||
|
public void testImport() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/import.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("methodArgument.kt")
|
@TestMetadata("methodArgument.kt")
|
||||||
public void testMethodArgument() throws Exception {
|
public void testMethodArgument() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/methodArgument.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/methodArgument.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("named.kt")
|
||||||
|
public void testNamed() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/named.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("notCompanion.kt")
|
@TestMetadata("notCompanion.kt")
|
||||||
public void testNotCompanion() throws Exception {
|
public void testNotCompanion() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/notCompanion.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/notCompanion.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user