From 2e6d82a72b444685b8c903677e4d87cfd4a92d6a Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 17 Dec 2015 13:06:27 +0300 Subject: [PATCH 1/2] Minor. Green code. --- .../UnusedReceiverParameterInspection.kt | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt index 9d0b1cb17ef..cf9444fcdea 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt @@ -19,9 +19,7 @@ package org.jetbrains.kotlin.idea.inspections import com.intellij.codeInspection.* import com.intellij.openapi.project.Project import com.intellij.psi.PsiElementVisitor -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor @@ -30,23 +28,18 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.isOverridable 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.scopes.receivers.ExpressionReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue -import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver -import kotlin.properties.Delegates public class UnusedReceiverParameterInspection : AbstractKotlinInspection() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { return object : KtVisitorVoid() { private fun check(callableDeclaration: KtCallableDeclaration) { - val receiverTypeReference = callableDeclaration.getReceiverTypeReference() + val receiverTypeReference = callableDeclaration.receiverTypeReference if (receiverTypeReference == null || receiverTypeReference.textRange.isEmpty) return if (callableDeclaration.isOverridable() || callableDeclaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return - if (callableDeclaration is KtProperty && callableDeclaration.getAccessors().isEmpty()) return + if (callableDeclaration is KtProperty && callableDeclaration.accessors.isEmpty()) return if (callableDeclaration is KtNamedFunction && !callableDeclaration.hasBody()) return val callable = callableDeclaration.descriptor @@ -60,11 +53,11 @@ public class UnusedReceiverParameterInspection : AbstractKotlinInspection() { val bindingContext = element.analyze() val resolvedCall = element.getResolvedCall(bindingContext) ?: return - if (resolvedCall.getDispatchReceiver().getThisReceiverOwner(bindingContext) == callable || + if (resolvedCall.dispatchReceiver.getThisReceiverOwner(bindingContext) == callable || (resolvedCall.extensionReceiver as ReceiverValue?).getThisReceiverOwner(bindingContext) == callable) { used = true } - else if ((resolvedCall.getCandidateDescriptor() as? ReceiverParameterDescriptor)?.getContainingDeclaration() == callable) { + else if ((resolvedCall.candidateDescriptor as? ReceiverParameterDescriptor)?.containingDeclaration == callable) { used = true } } @@ -99,6 +92,6 @@ public class UnusedReceiverParameterInspection : AbstractKotlinInspection() { declaration.setReceiverTypeReference(null) } - override fun getFamilyName(): String = getName() + override fun getFamilyName(): String = name } } From 9aa38d99fbe16fbe4856ca64d88cd0e879d2837d Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 17 Dec 2015 13:31:43 +0300 Subject: [PATCH 2/2] KT-8365 Bogus "Receiver never used" warning when receiver is used in invoke() convention call #KT-8365 fixed --- .../UnusedReceiverParameterInspection.kt | 21 ++++++++++++-- .../implicitReceiverOfInvokeConvention.kt | 29 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 idea/testData/inspections/unusedReceiverParameter/implicitReceiverOfInvokeConvention.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt index cf9444fcdea..4bc6f40fad3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedReceiverParameterInspection.kt @@ -28,7 +28,10 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.isOverridable 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.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue public class UnusedReceiverParameterInspection : AbstractKotlinInspection() { @@ -53,13 +56,25 @@ public class UnusedReceiverParameterInspection : AbstractKotlinInspection() { val bindingContext = element.analyze() val resolvedCall = element.getResolvedCall(bindingContext) ?: return + if (isUsageOfReceiver(resolvedCall, bindingContext)) { + used = true + } else if (resolvedCall is VariableAsFunctionResolvedCall + && isUsageOfReceiver(resolvedCall.variableCall, bindingContext)) { + used = true + } + } + + private fun isUsageOfReceiver(resolvedCall: ResolvedCall<*>, bindingContext: BindingContext): Boolean { + // As receiver of call if (resolvedCall.dispatchReceiver.getThisReceiverOwner(bindingContext) == callable || (resolvedCall.extensionReceiver as ReceiverValue?).getThisReceiverOwner(bindingContext) == callable) { - used = true + return true } - else if ((resolvedCall.candidateDescriptor as? ReceiverParameterDescriptor)?.containingDeclaration == callable) { - used = true + // As explicit "this" + if ((resolvedCall.candidateDescriptor as? ReceiverParameterDescriptor)?.containingDeclaration == callable) { + return true } + return false } }) diff --git a/idea/testData/inspections/unusedReceiverParameter/implicitReceiverOfInvokeConvention.kt b/idea/testData/inspections/unusedReceiverParameter/implicitReceiverOfInvokeConvention.kt new file mode 100644 index 00000000000..e796ee2b3bb --- /dev/null +++ b/idea/testData/inspections/unusedReceiverParameter/implicitReceiverOfInvokeConvention.kt @@ -0,0 +1,29 @@ +// KT-8365 Bogus "Receiver never used" warning +class FunctionLike { + fun invoke() {} +} + +class OwnerClass { + val functionLike = FunctionLike() + val function = { } +} + +val OwnerClass.extFunctionLike = FunctionLike() +val OwnerClass.extFunction = { } + + +fun OwnerClass.f1() { + functionLike() +} + +fun OwnerClass.f2() { + function() +} + +fun OwnerClass.f3() { + extFunctionLike() +} + +fun OwnerClass.f4() { + extFunction() +} \ No newline at end of file