Refactoring: extract KtCallExpression.isCall(FqName) function

This commit is contained in:
Toshiaki Kameyama
2018-09-10 14:02:43 +03:00
committed by Mikhail Glukhikh
parent 9a725b99b2
commit 416d33fc92
4 changed files with 25 additions and 14 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.inspections.collections
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtQualifiedExpression
@@ -36,9 +37,7 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() {
val context = expression.analyze()
val firstResolvedCall = firstExpression.getResolvedCall(context) ?: return null
val conversion = actualConversions.firstOrNull {
firstResolvedCall.resultingDescriptor.fqNameOrNull()?.asString() == it.firstFqName
} ?: return null
val conversion = actualConversions.firstOrNull { firstResolvedCall.isCalling(FqName(it.firstFqName)) } ?: return null
val secondResolvedCall = expression.getResolvedCall(context) ?: return null
if (!additionalCallCheck(conversion, firstResolvedCall, secondResolvedCall, context)) return null
@@ -47,8 +46,7 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() {
val lambdaArgument = firstCallExpression.lambdaArguments.firstOrNull()
if (lambdaArgument?.anyDescendantOfType<KtReturnExpression>() == true) return null
val secondResultingDescriptor = secondResolvedCall.resultingDescriptor
if (secondResultingDescriptor.fqNameOrNull()?.asString() != conversion.secondFqName) return null
if (!secondResolvedCall.isCalling(FqName(conversion.secondFqName))) return null
if (secondResolvedCall.valueArguments.any { (parameter, resolvedArgument) ->
parameter.type.isFunctionOfAnyKind() &&
resolvedArgument !is DefaultValueArgument
@@ -84,8 +82,6 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() {
fun getCallExpression(firstExpression: KtExpression) =
(firstExpression as? KtQualifiedExpression)?.selectorExpression as? KtCallExpression
?: firstExpression as? KtCallExpression
?: firstExpression as? KtCallExpression
}
}
@@ -199,17 +199,17 @@ private fun KtCallExpression.hasReturn(): Boolean = valueArguments.any { arg ->
private fun KtCallExpression.isTransformationOrTermination(context: BindingContext): Boolean {
val fqName = transformationAndTerminations[calleeExpression?.text] ?: return false
return fqName == getResolvedCall(context)?.resultingDescriptor?.fqNameSafe
return isCalling(fqName, context)
}
private fun KtCallExpression.isTermination(context: BindingContext): Boolean {
val fqName = terminations[calleeExpression?.text] ?: return false
return fqName == getResolvedCall(context)?.resultingDescriptor?.fqNameSafe
return isCalling(fqName, context)
}
private fun KtCallExpression.isLazyTermination(context: BindingContext): Boolean {
val fqName = lazyTerminations[calleeExpression?.text] ?: return false
return fqName == getResolvedCall(context)?.resultingDescriptor?.fqNameSafe
return isCalling(fqName, context)
}
private val transformations = listOf(
@@ -23,9 +23,7 @@ class ConvertFlatMapToFlattenInspection : AbstractKotlinInspection() {
qualifiedExpressionVisitor(fun(expression) {
val callExpression = expression.selectorExpression as? KtCallExpression ?: return
val calleeExpression = callExpression.calleeExpression ?: return
if (calleeExpression.text != "flatMap") return
val context = expression.analyze(BodyResolveMode.PARTIAL)
if (FqName("kotlin.collections.flatMap") != callExpression.getResolvedCall(context)?.resultingDescriptor?.fqNameSafe) return
if (!callExpression.isCalling(FqName("kotlin.collections.flatMap"))) return
val argument = callExpression.valueArguments.singleOrNull() ?: return
val lambdaExpression = (argument as? KtLambdaArgument)?.getLambdaExpression()
@@ -18,11 +18,18 @@ package org.jetbrains.kotlin.idea.inspections.collections
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
fun KotlinType.isFunctionOfAnyKind() = constructor.declarationDescriptor?.getFunctionalClassKind() != null
@@ -32,6 +39,16 @@ fun KotlinType?.isMap(builtIns: KotlinBuiltIns): Boolean {
return classDescriptor.name.asString().endsWith("Map") && classDescriptor.isSubclassOf(builtIns.map)
}
fun KtCallExpression.isCalling(fqName: FqName, context: BindingContext = analyze(BodyResolveMode.PARTIAL)): Boolean {
val function = fqName.asString().takeLastWhile { it != '.' }
if (calleeExpression?.text != function) return false
return getResolvedCall(context)?.isCalling(fqName) == true
}
fun ResolvedCall<out CallableDescriptor>.isCalling(fqName: FqName): Boolean {
return resultingDescriptor.fqNameSafe == fqName
}
fun ResolvedCall<*>.hasLastFunctionalParameterWithResult(context: BindingContext, predicate: (KotlinType) -> Boolean): Boolean {
val lastParameter = resultingDescriptor.valueParameters.lastOrNull() ?: return false
val lastArgument = valueArguments[lastParameter]?.arguments?.singleOrNull() ?: return false