Reformat: ConvertLambdaToReferenceIntention
This commit is contained in:
committed by
Mikhail Glukhikh
parent
b87dd07dd1
commit
271cbc1dd3
+28
-26
@@ -46,10 +46,10 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit
|
|||||||
class ConvertLambdaToReferenceInspection : IntentionBasedInspection<KtLambdaExpression>(ConvertLambdaToReferenceIntention::class)
|
class ConvertLambdaToReferenceInspection : IntentionBasedInspection<KtLambdaExpression>(ConvertLambdaToReferenceIntention::class)
|
||||||
|
|
||||||
open class ConvertLambdaToReferenceIntention(text: String) :
|
open class ConvertLambdaToReferenceIntention(text: String) :
|
||||||
SelfTargetingOffsetIndependentIntention<KtLambdaExpression>(KtLambdaExpression::class.java, text) {
|
SelfTargetingOffsetIndependentIntention<KtLambdaExpression>(KtLambdaExpression::class.java, text) {
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
constructor(): this("Convert lambda to reference")
|
constructor() : this("Convert lambda to reference")
|
||||||
|
|
||||||
open fun buildReferenceText(element: KtLambdaExpression) = buildReferenceText(lambdaExpression = element, shortTypes = false)
|
open fun buildReferenceText(element: KtLambdaExpression) = buildReferenceText(lambdaExpression = element, shortTypes = false)
|
||||||
|
|
||||||
@@ -59,10 +59,10 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isConvertibleCallInLambda(
|
private fun isConvertibleCallInLambda(
|
||||||
callableExpression: KtExpression,
|
callableExpression: KtExpression,
|
||||||
explicitReceiver: KtExpression? = null,
|
explicitReceiver: KtExpression? = null,
|
||||||
lambdaExpression: KtLambdaExpression,
|
lambdaExpression: KtLambdaExpression,
|
||||||
lambdaMustReturnUnit: Boolean
|
lambdaMustReturnUnit: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val context = callableExpression.analyze()
|
val context = callableExpression.analyze()
|
||||||
val calleeReferenceExpression = when (callableExpression) {
|
val calleeReferenceExpression = when (callableExpression) {
|
||||||
@@ -97,10 +97,9 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val explicitReceiverDescriptor =
|
val explicitReceiverDescriptor = (explicitReceiver as? KtNameReferenceExpression)?.let {
|
||||||
(explicitReceiver as? KtNameReferenceExpression)?.let {
|
context[REFERENCE_TARGET, it]
|
||||||
context[REFERENCE_TARGET, it]
|
} as? ValueDescriptor
|
||||||
} as? ValueDescriptor
|
|
||||||
val lambdaValueParameterDescriptors = context[FUNCTION, lambdaExpression.functionLiteral]?.valueParameters ?: return false
|
val lambdaValueParameterDescriptors = context[FUNCTION, lambdaExpression.functionLiteral]?.valueParameters ?: return false
|
||||||
val lambdaParameterAsExplicitReceiver = when (noBoundReferences) {
|
val lambdaParameterAsExplicitReceiver = when (noBoundReferences) {
|
||||||
true -> explicitReceiver != null
|
true -> explicitReceiver != null
|
||||||
@@ -115,7 +114,8 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
val receiverType = explicitReceiverDescriptor.type
|
val receiverType = explicitReceiverDescriptor.type
|
||||||
// No exotic receiver types
|
// No exotic receiver types
|
||||||
if (receiverType.isTypeParameter() || receiverType.isError || receiverType.isDynamic() ||
|
if (receiverType.isTypeParameter() || receiverType.isError || receiverType.isDynamic() ||
|
||||||
!receiverType.constructor.isDenotable || receiverType.isFunctionType) return false
|
!receiverType.constructor.isDenotable || receiverType.isFunctionType
|
||||||
|
) return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same lambda / references function parameter order
|
// Same lambda / references function parameter order
|
||||||
@@ -124,8 +124,7 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
val resolvedCall = callableExpression.getResolvedCall(context) ?: return false
|
val resolvedCall = callableExpression.getResolvedCall(context) ?: return false
|
||||||
resolvedCall.valueArguments.entries.forEach { (valueParameter, resolvedArgument) ->
|
resolvedCall.valueArguments.entries.forEach { (valueParameter, resolvedArgument) ->
|
||||||
val argumentExpression =
|
val argumentExpression =
|
||||||
resolvedArgument.arguments.singleOrNull()?.getArgumentExpression() as? KtNameReferenceExpression
|
resolvedArgument.arguments.singleOrNull()?.getArgumentExpression() as? KtNameReferenceExpression ?: return false
|
||||||
?: return false
|
|
||||||
val argumentTarget = context[REFERENCE_TARGET, argumentExpression] as? ValueParameterDescriptor ?: return false
|
val argumentTarget = context[REFERENCE_TARGET, argumentExpression] as? ValueParameterDescriptor ?: return false
|
||||||
if (argumentTarget != lambdaValueParameterDescriptors[valueParameter.index + explicitReceiverShift]) return false
|
if (argumentTarget != lambdaValueParameterDescriptors[valueParameter.index + explicitReceiverShift]) return false
|
||||||
}
|
}
|
||||||
@@ -150,14 +149,21 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
|
|
||||||
return when (singleStatement) {
|
return when (singleStatement) {
|
||||||
is KtCallExpression -> {
|
is KtCallExpression -> {
|
||||||
isConvertibleCallInLambda(callableExpression = singleStatement, lambdaExpression = element,
|
isConvertibleCallInLambda(
|
||||||
lambdaMustReturnUnit = lambdaMustReturnUnit)
|
callableExpression = singleStatement,
|
||||||
|
lambdaExpression = element,
|
||||||
|
lambdaMustReturnUnit = lambdaMustReturnUnit
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is KtNameReferenceExpression -> false // Global property reference is not possible (?!)
|
is KtNameReferenceExpression -> false // Global property reference is not possible (?!)
|
||||||
is KtDotQualifiedExpression -> {
|
is KtDotQualifiedExpression -> {
|
||||||
val selector = singleStatement.selectorExpression ?: return false
|
val selector = singleStatement.selectorExpression ?: return false
|
||||||
isConvertibleCallInLambda(callableExpression = selector, explicitReceiver = singleStatement.receiverExpression,
|
isConvertibleCallInLambda(
|
||||||
lambdaExpression = element, lambdaMustReturnUnit = lambdaMustReturnUnit)
|
callableExpression = selector,
|
||||||
|
explicitReceiver = singleStatement.receiverExpression,
|
||||||
|
lambdaExpression = element,
|
||||||
|
lambdaMustReturnUnit = lambdaMustReturnUnit
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
@@ -171,8 +177,7 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
// Without lambda argument syntax, just replace lambda with reference
|
// Without lambda argument syntax, just replace lambda with reference
|
||||||
val callableReferenceExpr = factory.createCallableReferenceExpression(referenceName) ?: return
|
val callableReferenceExpr = factory.createCallableReferenceExpression(referenceName) ?: return
|
||||||
(element.replace(callableReferenceExpr) as? KtElement)?.let { ShortenReferences.RETAIN_COMPANION.process(it) }
|
(element.replace(callableReferenceExpr) as? KtElement)?.let { ShortenReferences.RETAIN_COMPANION.process(it) }
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Otherwise, replace the whole argument list for lambda argument-using call
|
// Otherwise, replace the whole argument list for lambda argument-using call
|
||||||
val outerCallExpression = lambdaArgument.parent as? KtCallExpression ?: return
|
val outerCallExpression = lambdaArgument.parent as? KtCallExpression ?: return
|
||||||
val outerCalleeDescriptor = lambdaArgument.outerCalleeDescriptor() ?: return
|
val outerCalleeDescriptor = lambdaArgument.outerCalleeDescriptor() ?: return
|
||||||
@@ -181,7 +186,7 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
val arguments = outerCallExpression.valueArguments.filter { it !is KtLambdaArgument }
|
val arguments = outerCallExpression.valueArguments.filter { it !is KtLambdaArgument }
|
||||||
val hadDefaultValues = valueParameters.size - 1 > arguments.size
|
val hadDefaultValues = valueParameters.size - 1 > arguments.size
|
||||||
val useNamedArguments = valueParameters.any { it.hasDefaultValue() } && hadDefaultValues
|
val useNamedArguments = valueParameters.any { it.hasDefaultValue() } && hadDefaultValues
|
||||||
|| arguments.any { it.getArgumentName() != null }
|
|| arguments.any { it.getArgumentName() != null }
|
||||||
|
|
||||||
val newArgumentList = factory.buildValueArgumentList {
|
val newArgumentList = factory.buildValueArgumentList {
|
||||||
appendFixedText("(")
|
appendFixedText("(")
|
||||||
@@ -204,8 +209,7 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
val argumentList = outerCallExpression.valueArgumentList
|
val argumentList = outerCallExpression.valueArgumentList
|
||||||
if (argumentList == null) {
|
if (argumentList == null) {
|
||||||
(lambdaArgument.replace(newArgumentList) as? KtElement)?.let { ShortenReferences.RETAIN_COMPANION.process(it) }
|
(lambdaArgument.replace(newArgumentList) as? KtElement)?.let { ShortenReferences.RETAIN_COMPANION.process(it) }
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
(argumentList.replace(newArgumentList) as? KtValueArgumentList)?.let {
|
(argumentList.replace(newArgumentList) as? KtValueArgumentList)?.let {
|
||||||
ShortenReferences.RETAIN_COMPANION.process(it.arguments.last())
|
ShortenReferences.RETAIN_COMPANION.process(it.arguments.last())
|
||||||
}
|
}
|
||||||
@@ -248,12 +252,10 @@ open class ConvertLambdaToReferenceIntention(text: String) :
|
|||||||
val receiverType = originalReceiverType.approximateFlexibleTypes(preferNotNull = true)
|
val receiverType = originalReceiverType.approximateFlexibleTypes(preferNotNull = true)
|
||||||
if (shortTypes) {
|
if (shortTypes) {
|
||||||
"${IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.renderType(receiverType)}::$selectorReferenceName"
|
"${IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.renderType(receiverType)}::$selectorReferenceName"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
"${IdeDescriptorRenderers.SOURCE_CODE.renderType(receiverType)}::$selectorReferenceName"
|
"${IdeDescriptorRenderers.SOURCE_CODE.renderType(receiverType)}::$selectorReferenceName"
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val receiverName = receiverDescriptor.importableFqName ?: receiverDescriptor.name
|
val receiverName = receiverDescriptor.importableFqName ?: receiverDescriptor.name
|
||||||
"$receiverName::$selectorReferenceName"
|
"$receiverName::$selectorReferenceName"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user