Explicit this inspection: fix false negative with local variable
#KT-30136 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
eb469b924f
commit
0ec18b4a33
@@ -22,13 +22,18 @@ import com.intellij.codeInspection.ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.CallableReferencesToClassMembersWithEmptyLHS
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
@@ -60,7 +65,14 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||
|
||||
//we avoid overload-related problems by enforcing that there is only one candidate
|
||||
val name = referenceExpression.getReferencedNameAsName()
|
||||
val candidates = scope.getAllAccessibleVariables(name) + scope.getAllAccessibleFunctions(name)
|
||||
val candidates = if (reference is KtCallExpression
|
||||
|| (expression is KtCallableReferenceExpression && reference.mainReference.resolve() is KtFunction)
|
||||
) {
|
||||
scope.getAllAccessibleFunctions(name) +
|
||||
scope.getAllAccessibleVariables(name).filter { it is LocalVariableDescriptor && it.canInvoke() }
|
||||
} else {
|
||||
scope.getAllAccessibleVariables(name)
|
||||
}
|
||||
if (referenceExpression.getCallableDescriptor() is SyntheticJavaPropertyDescriptor) {
|
||||
if (candidates.map { it.containingDeclaration }.distinct().size != 1) return
|
||||
} else {
|
||||
@@ -76,6 +88,11 @@ class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||
|
||||
holder.registerProblem(thisExpression, "Redundant explicit this", LIKE_UNUSED_SYMBOL, Fix(thisExpression.text))
|
||||
}
|
||||
|
||||
private fun VariableDescriptor.canInvoke(): Boolean {
|
||||
val declarationDescriptor = this.type.constructor.declarationDescriptor as? LazyClassDescriptor ?: return false
|
||||
return declarationDescriptor.declaredCallableMembers.any { (it as? FunctionDescriptor)?.isOperator == true }
|
||||
}
|
||||
|
||||
private fun ReceiverExpressionFactory.matchesLabel(label: String): Boolean {
|
||||
val implicitLabel = expressionText.substringAfter("@", "")
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// PROBLEM: none
|
||||
class Some {
|
||||
operator fun invoke() {}
|
||||
}
|
||||
|
||||
class Other {
|
||||
fun foo() {
|
||||
val a = Some()
|
||||
<caret>this.a()
|
||||
a()
|
||||
}
|
||||
|
||||
fun a() {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
fun foo() {
|
||||
val a = 1
|
||||
<caret>this.a()
|
||||
}
|
||||
|
||||
fun a() {
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
fun foo() {
|
||||
val a = 1
|
||||
<caret>a()
|
||||
}
|
||||
|
||||
fun a() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
fun foo() {
|
||||
fun a() {
|
||||
}
|
||||
<caret>this.a
|
||||
}
|
||||
|
||||
val a = 1
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
fun foo() {
|
||||
fun a() {
|
||||
}
|
||||
<caret>a
|
||||
}
|
||||
|
||||
val a = 1
|
||||
}
|
||||
+15
@@ -4196,6 +4196,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
runTest("idea/testData/inspectionsLocal/explicitThis/functionReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionWithSameNameInvocableVariable.kt")
|
||||
public void testFunctionWithSameNameInvocableVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/explicitThis/functionWithSameNameInvocableVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionWithSameNameVariable.kt")
|
||||
public void testFunctionWithSameNameVariable() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/explicitThis/functionWithSameNameVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleReceivers.kt")
|
||||
public void testMultipleReceivers() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/explicitThis/multipleReceivers.kt");
|
||||
@@ -4265,6 +4275,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
public void testVariableWithSameName() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/explicitThis/variableWithSameName.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("variableWithSameNameFunction.kt")
|
||||
public void testVariableWithSameNameFunction() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/explicitThis/variableWithSameNameFunction.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/inspectionsLocal/foldInitializerAndIfToElvis")
|
||||
|
||||
Reference in New Issue
Block a user