KT-7883 Receiver parameter falsely marked as unused

#KT-7883 fixed
This commit is contained in:
Evgeny Gerashchenko
2015-06-15 20:25:35 +03:00
parent 7511b5bafe
commit cc70ea2586
4 changed files with 38 additions and 18 deletions
@@ -17,13 +17,17 @@
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.psi.JetPsiUtil
import org.jetbrains.kotlin.psi.JetThisExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver
public enum class CallType { public enum class CallType {
NORMAL, NORMAL,
@@ -102,3 +106,15 @@ public fun CallableDescriptor.substituteExtensionIfCallable(
} }
} }
public fun ReceiverValue.getThisReceiverOwner(bindingContext: BindingContext): DeclarationDescriptor? {
return when (this) {
is ExpressionReceiver -> {
val thisRef = (JetPsiUtil.deparenthesize(this.getExpression()) as? JetThisExpression)?.getInstanceReference() ?: return null
bindingContext[BindingContext.REFERENCE_TARGET, thisRef]
}
is ThisReceiver -> this.getDeclarationDescriptor()
else -> null
}
}
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.util.getThisReceiverOwner
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
@@ -77,17 +78,9 @@ public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider {
if (resolvedCall.getCandidateDescriptor().getOriginal() != enclosingFunctionDescriptor) return false if (resolvedCall.getCandidateDescriptor().getOriginal() != enclosingFunctionDescriptor) return false
fun isDifferentReceiver(receiver: ReceiverValue): Boolean { fun isDifferentReceiver(receiver: ReceiverValue): Boolean {
val receiverOwner = if (receiver == ReceiverValue.NO_RECEIVER) return false
when (receiver) {
is ExpressionReceiver -> {
val thisRef = (JetPsiUtil.deparenthesize(receiver.getExpression()) as?
JetThisExpression)?.getInstanceReference() ?: return true
bindingContext[BindingContext.REFERENCE_TARGET, thisRef] ?: return true
}
is ThisReceiver -> receiver.getDeclarationDescriptor() val receiverOwner = receiver.getThisReceiverOwner(bindingContext) ?: return true
else -> return false
}
return when (receiverOwner) { return when (receiverOwner) {
is SimpleFunctionDescriptor -> receiverOwner != enclosingFunctionDescriptor is SimpleFunctionDescriptor -> receiverOwner != enclosingFunctionDescriptor
@@ -19,16 +19,23 @@ package org.jetbrains.kotlin.idea.inspections
import com.intellij.codeInspection.* import com.intellij.codeInspection.*
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.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.idea.JetBundle import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.util.getThisReceiverOwner
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isOverridable import org.jetbrains.kotlin.psi.psiUtil.isOverridable
import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver
import kotlin.properties.Delegates import kotlin.properties.Delegates
public class UnusedReceiverParameterInspection : AbstractKotlinInspection() { public class UnusedReceiverParameterInspection : AbstractKotlinInspection() {
@@ -52,10 +59,9 @@ public class UnusedReceiverParameterInspection : AbstractKotlinInspection() {
val bindingContext = element.analyze() val bindingContext = element.analyze()
val resolvedCall = element.getResolvedCall(bindingContext) ?: return val resolvedCall = element.getResolvedCall(bindingContext) ?: return
if ((resolvedCall.getDispatchReceiver() as? ExtensionReceiver)?.getDeclarationDescriptor() == callable) {
used = true if (resolvedCall.getDispatchReceiver().getThisReceiverOwner(bindingContext) == callable ||
} resolvedCall.getExtensionReceiver().getThisReceiverOwner(bindingContext) == callable) {
else if (((resolvedCall.getExtensionReceiver() as? ExtensionReceiver)?.getDeclarationDescriptor() == callable)) {
used = true used = true
} }
else if ((resolvedCall.getCandidateDescriptor() as? ReceiverParameterDescriptor)?.getContainingDeclaration() == callable) { else if ((resolvedCall.getCandidateDescriptor() as? ReceiverParameterDescriptor)?.getContainingDeclaration() == callable) {
@@ -0,0 +1,5 @@
// KT-7883 Receiver parameter falsely marked as unused
fun (() -> Any).foo() {
this()
}