Extract common part in inspections that checks usage of descriptor in some call
This commit is contained in:
@@ -14,14 +14,11 @@ import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.moveCaret
|
||||
import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.util.getThisReceiverOwner
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
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.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
@@ -42,7 +39,7 @@ class RedundantWithInspection : AbstractKotlinInspection() {
|
||||
if (callExpression.getResolvedCall(context)?.resultingDescriptor?.fqNameSafe != FqName("kotlin.with")) return
|
||||
|
||||
val lambdaDescriptor = context[BindingContext.FUNCTION, lambda.functionLiteral] ?: return
|
||||
val lambdaExtensionReceiver = lambdaDescriptor.extensionReceiverParameter
|
||||
|
||||
var used = false
|
||||
lambda.functionLiteral.acceptChildren(object : KtVisitorVoid() {
|
||||
override fun visitKtElement(element: KtElement) {
|
||||
@@ -55,27 +52,13 @@ class RedundantWithInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
|
||||
val resolvedCall = element.getResolvedCall(context) ?: return
|
||||
if (isUsageOfReceiver(resolvedCall, context)) {
|
||||
used = true
|
||||
} else if (resolvedCall is VariableAsFunctionResolvedCall && isUsageOfReceiver(resolvedCall.variableCall, context)) {
|
||||
used = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun isUsageOfReceiver(resolvedCall: ResolvedCall<*>, bindingContext: BindingContext): Boolean {
|
||||
// As receiver of call
|
||||
if (resolvedCall.dispatchReceiver.getThisReceiverOwner(bindingContext) == lambdaDescriptor ||
|
||||
resolvedCall.extensionReceiver.getThisReceiverOwner(bindingContext) == lambdaDescriptor
|
||||
) {
|
||||
return true
|
||||
if (isUsageOfDescriptor(lambdaDescriptor, resolvedCall, context)) {
|
||||
used = true
|
||||
}
|
||||
// As explicit "this"
|
||||
if (resolvedCall.candidateDescriptor == lambdaExtensionReceiver) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
if (!used) {
|
||||
val quickfix = when (receiver) {
|
||||
is KtSimpleNameExpression, is KtStringTemplateExpression, is KtConstantExpression -> RemoveRedundantWithFix()
|
||||
|
||||
+26
-25
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
@@ -69,16 +70,16 @@ class UnusedReceiverParameterInspection : AbstractKotlinInspection() {
|
||||
callableDeclaration.isOverridable()
|
||||
) return
|
||||
|
||||
val context = receiverTypeReference.analyze()
|
||||
val context = callableDeclaration.analyze()
|
||||
val receiverType = context[BindingContext.TYPE, receiverTypeReference] ?: return
|
||||
val receiverTypeDeclaration = receiverType.constructor.declarationDescriptor
|
||||
if (DescriptorUtils.isCompanionObject(receiverTypeDeclaration)) return
|
||||
|
||||
val callable = callableDeclaration.descriptor
|
||||
val callable = callableDeclaration.descriptor ?: return
|
||||
|
||||
if (callable != null && MainFunctionDetector.isMain(callable)) return
|
||||
if (MainFunctionDetector.isMain(callable)) return
|
||||
|
||||
val containingDeclaration = callable?.containingDeclaration
|
||||
val containingDeclaration = callable.containingDeclaration
|
||||
if (containingDeclaration != null && containingDeclaration == receiverTypeDeclaration) {
|
||||
val thisLabelName = containingDeclaration.getThisLabelName()
|
||||
if (!callableDeclaration.anyDescendantOfType<KtThisExpression> { it.getLabelName() == thisLabelName }) {
|
||||
@@ -93,31 +94,12 @@ class UnusedReceiverParameterInspection : AbstractKotlinInspection() {
|
||||
if (used) return
|
||||
element.acceptChildren(this)
|
||||
|
||||
val bindingContext = element.analyze()
|
||||
val resolvedCall = element.getResolvedCall(bindingContext) ?: return
|
||||
val resolvedCall = element.getResolvedCall(context) ?: return
|
||||
|
||||
if (isUsageOfReceiver(resolvedCall, bindingContext)) {
|
||||
used = true
|
||||
} else if (resolvedCall is VariableAsFunctionResolvedCall
|
||||
&& isUsageOfReceiver(resolvedCall.variableCall, bindingContext)
|
||||
) {
|
||||
if (isUsageOfDescriptor(callable, resolvedCall, context)) {
|
||||
used = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun isUsageOfReceiver(resolvedCall: ResolvedCall<*>, bindingContext: BindingContext): Boolean {
|
||||
// As receiver of call
|
||||
if (resolvedCall.dispatchReceiver.getThisReceiverOwner(bindingContext) == callable ||
|
||||
resolvedCall.extensionReceiver.getThisReceiverOwner(bindingContext) == callable
|
||||
) {
|
||||
return true
|
||||
}
|
||||
// As explicit "this"
|
||||
if ((resolvedCall.candidateDescriptor as? ReceiverParameterDescriptor)?.containingDeclaration == callable) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
if (!used) registerProblem(receiverTypeReference)
|
||||
@@ -175,3 +157,22 @@ class UnusedReceiverParameterInspection : AbstractKotlinInspection() {
|
||||
override fun startInWriteAction() = false
|
||||
}
|
||||
}
|
||||
|
||||
fun isUsageOfDescriptor(descriptor: DeclarationDescriptor, resolvedCall: ResolvedCall<*>, bindingContext: BindingContext): Boolean {
|
||||
// As receiver of call
|
||||
if (resolvedCall.dispatchReceiver.getThisReceiverOwner(bindingContext) == descriptor ||
|
||||
resolvedCall.extensionReceiver.getThisReceiverOwner(bindingContext) == descriptor
|
||||
) {
|
||||
return true
|
||||
}
|
||||
// As explicit "this"
|
||||
if ((resolvedCall.candidateDescriptor as? ReceiverParameterDescriptor)?.containingDeclaration == descriptor) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||
return isUsageOfDescriptor(descriptor, resolvedCall.variableCall, bindingContext)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user