"Redundant Companion": Don't suggest if same callable name is in use
So #KT-24425 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
a2435ff3b0
commit
5ad98a139d
+46
-2
@@ -11,24 +11,59 @@ import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
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.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.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
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.scopes.utils.findFunction
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
|
||||
|
||||
class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||
return referenceExpressionVisitor(fun(expression) {
|
||||
val parent = expression.parent as? KtDotQualifiedExpression ?: return
|
||||
if (expression == parent.selectorExpression && parent.parent !is KtDotQualifiedExpression) return
|
||||
val selectorExpression = parent.selectorExpression
|
||||
if (expression == selectorExpression && parent.parent !is KtDotQualifiedExpression) return
|
||||
if (parent.getStrictParentOfType<KtImportDirective>() != null) return
|
||||
|
||||
val objectDeclaration = expression.mainReference.resolve() as? KtObjectDeclaration ?: return
|
||||
if (!objectDeclaration.isCompanion()) return
|
||||
if (expression.text != objectDeclaration.name) return
|
||||
|
||||
val containingClass = objectDeclaration.containingClass() ?: return
|
||||
val selectorDescriptor = selectorExpression?.getCallableDescriptor()
|
||||
when (selectorDescriptor) {
|
||||
is PropertyDescriptor -> {
|
||||
val name = selectorDescriptor.name
|
||||
if (containingClass.findPropertyByName(name.asString()) != null) return
|
||||
val variable = expression.getResolutionScope().findVariable(name, NoLookupLocation.FROM_IDE)
|
||||
if (variable.isLocalOrExtension(containingClass)) return
|
||||
}
|
||||
is FunctionDescriptor -> {
|
||||
val name = selectorDescriptor.name
|
||||
val function = containingClass.findFunctionByName(name.asString())?.descriptor
|
||||
?: expression.getResolutionScope().findFunction(name, NoLookupLocation.FROM_IDE)?.takeIf {
|
||||
it.isLocalOrExtension(containingClass)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val grandParent = parent.parent as? KtQualifiedExpression
|
||||
if (grandParent != null) {
|
||||
val grandParentDescriptor = grandParent.resolveToCall()?.resultingDescriptor ?: return
|
||||
@@ -45,6 +80,15 @@ class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtClass.findFunctionByName(name: String): KtDeclaration? {
|
||||
return declarations.firstOrNull { it is KtNamedFunction && it.name == name }
|
||||
}
|
||||
|
||||
private fun CallableDescriptor?.isLocalOrExtension(extensionClass: KtClass): Boolean {
|
||||
return this?.visibility == Visibilities.LOCAL
|
||||
|| this?.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == extensionClass.descriptor
|
||||
}
|
||||
|
||||
private class RemoveRedundantCompanionReferenceFix : LocalQuickFix {
|
||||
override fun getName() = "Remove redundant Companion reference"
|
||||
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
companion object {
|
||||
fun f(x: Int, y: Int) = 1
|
||||
}
|
||||
|
||||
fun f(x: Int, y: String) = 2
|
||||
|
||||
fun test() {
|
||||
<caret>Companion.f(1, 2)
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
companion object {
|
||||
fun f(x: Int, y: Int) = 1
|
||||
}
|
||||
|
||||
fun f(x: Int, y: String) = 2
|
||||
|
||||
fun test() {
|
||||
f(1, 2)
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// PROBLEM: none
|
||||
|
||||
class Test {
|
||||
companion object {
|
||||
fun extentionFun() = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>Companion.extentionFun()
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.extentionFun() = 2
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// PROBLEM: none
|
||||
|
||||
class Test {
|
||||
companion object {
|
||||
val extentionVar = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>Companion.extentionVar
|
||||
}
|
||||
}
|
||||
|
||||
val Test.extentionVar: Int
|
||||
get() = 2
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
companion object {
|
||||
fun globalFun() = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>Companion.globalFun()
|
||||
}
|
||||
}
|
||||
|
||||
fun globalFun() = 2
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
companion object {
|
||||
fun globalFun() = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
globalFun()
|
||||
}
|
||||
}
|
||||
|
||||
fun globalFun() = 2
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
companion object {
|
||||
val globalVar = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>Companion.globalVar
|
||||
}
|
||||
}
|
||||
|
||||
val globalVar = 2
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
companion object {
|
||||
val globalVar = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
globalVar
|
||||
}
|
||||
}
|
||||
|
||||
val globalVar = 2
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// PROBLEM: none
|
||||
|
||||
class Test {
|
||||
companion object {
|
||||
fun localFun() = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
fun localFun() = 2
|
||||
|
||||
<caret>Companion.localFun()
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// PROBLEM: none
|
||||
|
||||
class Test {
|
||||
companion object {
|
||||
val localVar = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
var localVar = 2
|
||||
|
||||
<caret>Companion.localVar
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// PROBLEM: none
|
||||
|
||||
class Test {
|
||||
companion object {
|
||||
val localVar = 1
|
||||
}
|
||||
|
||||
fun test(localVar: Int) {
|
||||
<caret>Companion.localVar
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// PROBLEM: none
|
||||
|
||||
class Test {
|
||||
companion object {
|
||||
fun memberFun(x: Int) = 1
|
||||
}
|
||||
|
||||
fun memberFun(x: Int) = 2
|
||||
|
||||
fun test() {
|
||||
<caret>Companion.memberFun(0)
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// PROBLEM: none
|
||||
|
||||
class Test {
|
||||
companion object {
|
||||
val memberVar = 1
|
||||
}
|
||||
|
||||
val memberVar = 2
|
||||
|
||||
fun test() {
|
||||
<caret>Companion.memberVar
|
||||
}
|
||||
}
|
||||
+50
@@ -3024,6 +3024,56 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
public void testOnlyCompanion() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/onlyCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameDifferentArgsFunction.kt")
|
||||
public void testSameNameDifferentArgsFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameDifferentArgsFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameExtensionFunction.kt")
|
||||
public void testSameNameExtensionFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameExtensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameExtensionVariable.kt")
|
||||
public void testSameNameExtensionVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameExtensionVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameGlobalFunction.kt")
|
||||
public void testSameNameGlobalFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameGlobalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameGlobalVariable.kt")
|
||||
public void testSameNameGlobalVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameGlobalVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameLocalFunction.kt")
|
||||
public void testSameNameLocalFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameLocalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameLocalVariable.kt")
|
||||
public void testSameNameLocalVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameLocalVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameLocalVariable2.kt")
|
||||
public void testSameNameLocalVariable2() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameLocalVariable2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameMemberFunction.kt")
|
||||
public void testSameNameMemberFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameMemberFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameNameMemberVariable.kt")
|
||||
public void testSameNameMemberVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/redundantCompanionReference/sameNameMemberVariable.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/inspectionsLocal/redundantExplicitType")
|
||||
|
||||
Reference in New Issue
Block a user