Redundant companion reference: don't report in case of name conflicts
#KT-27539 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
6e27d7a2a5
commit
1db7a0e0cc
+41
-13
@@ -18,12 +18,13 @@ import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
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.findFunctionByName
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findPropertyByName
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
|
||||
|
||||
@@ -46,24 +47,25 @@ class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
||||
when (selectorDescriptor) {
|
||||
is PropertyDescriptor -> {
|
||||
val name = selectorDescriptor.name
|
||||
if (containingClass.findPropertyByName(name.asString()) != null) return
|
||||
if (containingClassDescriptor.findMemberVariable(name.asString()) != null) return
|
||||
val variable = expression.getResolutionScope().findVariable(name, NoLookupLocation.FROM_IDE)
|
||||
if (variable != null && variable.isLocalOrExtension(containingClassDescriptor)) return
|
||||
}
|
||||
is FunctionDescriptor -> {
|
||||
val name = selectorDescriptor.name
|
||||
val function = containingClass.findFunctionByName(name.asString())?.descriptor
|
||||
?: expression.getResolutionScope().findFunction(name, NoLookupLocation.FROM_IDE)?.takeIf {
|
||||
val functions = containingClassDescriptor.collectMemberFunction(name.asString()) + listOfNotNull(
|
||||
expression.getResolutionScope().findFunction(name, NoLookupLocation.FROM_IDE)?.takeIf {
|
||||
it.isLocalOrExtension(containingClassDescriptor)
|
||||
}
|
||||
if (function is FunctionDescriptor) {
|
||||
val functionParams = function.valueParameters
|
||||
val calleeParams =
|
||||
(selectorExpression as? KtCallExpression)?.calleeExpression?.getCallableDescriptor()?.valueParameters.orEmpty()
|
||||
if (functionParams.size == calleeParams.size &&
|
||||
functionParams.zip(calleeParams).all { it.first.type == it.second.type }
|
||||
) return
|
||||
}
|
||||
)
|
||||
if (functions.any {
|
||||
val functionParams = it.valueParameters
|
||||
val calleeParams = (selectorExpression as? KtCallExpression)?.calleeExpression?.getCallableDescriptor()
|
||||
?.valueParameters.orEmpty()
|
||||
functionParams.size == calleeParams.size && functionParams.zip(calleeParams).all { param ->
|
||||
param.first.type == param.second.type
|
||||
}
|
||||
}) return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +85,32 @@ class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.findMemberVariable(name: String): PropertyDescriptor? {
|
||||
val variable = unsubstitutedMemberScope.getContributedVariables(Name.identifier(name), NoLookupLocation.FROM_IDE).firstOrNull()
|
||||
if (variable != null) return variable
|
||||
|
||||
val variableInSuperClass = getSuperClassNotAny()?.findMemberVariable(name)
|
||||
if (variableInSuperClass != null) return variableInSuperClass
|
||||
|
||||
getSuperInterfaces().forEach {
|
||||
val variableInInterface = it.findMemberVariable(name)
|
||||
if (variableInInterface != null) return variableInInterface
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.collectMemberFunction(name: String): MutableList<FunctionDescriptor> {
|
||||
val functions = mutableListOf<FunctionDescriptor>()
|
||||
fun collect(descriptor: ClassDescriptor) {
|
||||
functions.addAll(descriptor.unsubstitutedMemberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_IDE))
|
||||
descriptor.getSuperClassNotAny()?.let { collect(it) }
|
||||
descriptor.getSuperInterfaces().forEach { collect(it) }
|
||||
}
|
||||
collect(this)
|
||||
return functions
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.isLocalOrExtension(extensionClassDescriptor: ClassDescriptor): Boolean {
|
||||
return visibility == Visibilities.LOCAL ||
|
||||
extensionReceiverParameter?.type?.constructor?.declarationDescriptor == extensionClassDescriptor
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// PROBLEM: none
|
||||
|
||||
open class B {
|
||||
fun foo(x: Int) = "B$x"
|
||||
}
|
||||
|
||||
class C : B() {
|
||||
fun test(): String {
|
||||
return <caret>Companion.foo(1)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun foo(x: Int) = "C$x"
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// PROBLEM: none
|
||||
|
||||
open class A {
|
||||
fun foo(x: Int) = "A$x"
|
||||
}
|
||||
|
||||
open class B: A() {
|
||||
}
|
||||
|
||||
class C : B() {
|
||||
fun test(): String {
|
||||
return <caret>Companion.foo(1)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun foo(x: Int) = "C$x"
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// PROBLEM: none
|
||||
|
||||
interface A {
|
||||
fun foo(x: Int) = "A$x"
|
||||
}
|
||||
|
||||
open class B {
|
||||
}
|
||||
|
||||
class C : B(), A {
|
||||
fun test(): String {
|
||||
return <caret>Companion.foo(1)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun foo(x: Int) = "C$x"
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// PROBLEM: none
|
||||
|
||||
open class B {
|
||||
val foo = "B"
|
||||
}
|
||||
|
||||
class C : B() {
|
||||
fun test(): String {
|
||||
return <caret>Companion.foo
|
||||
}
|
||||
|
||||
companion object {
|
||||
val foo = "C"
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// PROBLEM: none
|
||||
|
||||
open class A {
|
||||
val foo = "A"
|
||||
}
|
||||
|
||||
open class B: A() {
|
||||
}
|
||||
|
||||
class C : B() {
|
||||
fun test(): String {
|
||||
return <caret>Companion.foo
|
||||
}
|
||||
|
||||
companion object {
|
||||
val foo = "C"
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// PROBLEM: none
|
||||
|
||||
interface A {
|
||||
val foo: String
|
||||
get() = "A"
|
||||
}
|
||||
|
||||
open class B {
|
||||
}
|
||||
|
||||
class C : B(), A {
|
||||
fun test(): String {
|
||||
return <caret>Companion.foo
|
||||
}
|
||||
|
||||
companion object {
|
||||
val foo = "C"
|
||||
}
|
||||
}
|
||||
+30
@@ -4083,6 +4083,36 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
public void testSameNameMemberVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameMemberVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameSuperMemberFunction.kt")
|
||||
public void testSameNameSuperMemberFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameSuperMemberFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameSuperMemberFunction2.kt")
|
||||
public void testSameNameSuperMemberFunction2() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameSuperMemberFunction2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameSuperMemberFunction3.kt")
|
||||
public void testSameNameSuperMemberFunction3() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameSuperMemberFunction3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameSuperMemberVariable.kt")
|
||||
public void testSameNameSuperMemberVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameSuperMemberVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameSuperMemberVariable2.kt")
|
||||
public void testSameNameSuperMemberVariable2() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameSuperMemberVariable2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameSuperMemberVariable3.kt")
|
||||
public void testSameNameSuperMemberVariable3() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameSuperMemberVariable3.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/inspectionsLocal/redundantExplicitType")
|
||||
|
||||
Reference in New Issue
Block a user