Minor: refactoring ChangeFunctionSignature quickfix

This commit is contained in:
Dmitry Gridin
2019-04-02 15:19:22 +07:00
parent cb38f13399
commit c48c274e59
3 changed files with 66 additions and 69 deletions
@@ -38,9 +38,10 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import java.util.*
class AddFunctionParametersFix(
callElement: KtCallElement,
functionDescriptor: FunctionDescriptor,
private val hasTypeMismatches: Boolean) : ChangeFunctionSignatureFix(callElement, functionDescriptor) {
callElement: KtCallElement,
functionDescriptor: FunctionDescriptor,
private val hasTypeMismatches: Boolean
) : ChangeFunctionSignatureFix(callElement, functionDescriptor) {
private val callElement: KtCallElement?
get() = element as? KtCallElement
@@ -59,8 +60,7 @@ class AddFunctionParametersFix(
val callableDescription = if (isConstructor()) {
val className = functionDescriptor.containingDeclaration.name.asString()
"constructor '$className'"
}
else {
} else {
val functionName = functionDescriptor.name.asString()
"function '$functionName'"
}
@@ -88,9 +88,9 @@ class AddFunctionParametersFix(
private fun addParameterConfiguration(): KotlinChangeSignatureConfiguration {
return object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify {
val callElement = callElement ?: return@modify
val call = callElement.getCall(callElement.analyze()) ?: return@modify
return originalDescriptor.modify(fun(descriptor: KotlinMutableMethodDescriptor) {
val callElement = callElement ?: return
val call = callElement.getCall(callElement.analyze()) ?: return
val parameters = functionDescriptor.valueParameters
val arguments = callElement.valueArguments
val validator = CollectingNameValidator()
@@ -109,15 +109,14 @@ class AddFunctionParametersFix(
val parameterType = parameters[i].type
if (argumentType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameterType)) {
it.parameters[i].currentTypeInfo = KotlinTypeInfo(false, argumentType)
descriptor.parameters[i].currentTypeInfo = KotlinTypeInfo(false, argumentType)
typesToShorten.add(argumentType)
}
}
else {
} else {
val parameterInfo = getNewParameterInfo(
originalDescriptor.baseDescriptor as FunctionDescriptor,
argument,
validator
originalDescriptor.baseDescriptor as FunctionDescriptor,
argument,
validator
)
parameterInfo.originalTypeInfo.type?.let { typesToShorten.add(it) }
@@ -125,10 +124,10 @@ class AddFunctionParametersFix(
parameterInfo.defaultValueForCall = expression
}
it.addParameter(parameterInfo)
descriptor.addParameter(parameterInfo)
}
}
}
})
}
override fun performSilently(affectedFunctions: Collection<PsiElement>): Boolean {
@@ -139,15 +138,15 @@ class AddFunctionParametersFix(
}
private fun getNewParameterInfo(
functionDescriptor: FunctionDescriptor,
argument: ValueArgument,
validator: (String) -> Boolean
functionDescriptor: FunctionDescriptor,
argument: ValueArgument,
validator: (String) -> Boolean
): KotlinParameterInfo {
val name = getNewArgumentName(argument, validator)
val expression = argument.getArgumentExpression()
val type = expression?.let { getDataFlowAwareTypes(it).firstOrNull() } ?: functionDescriptor.builtIns.nullableAnyType
return KotlinParameterInfo(functionDescriptor, -1, name, KotlinTypeInfo(false, null))
.apply { currentTypeInfo = KotlinTypeInfo(false, type) }
.apply { currentTypeInfo = KotlinTypeInfo(false, type) }
}
private fun hasOtherUsages(function: PsiElement): Boolean {
@@ -32,9 +32,9 @@ import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.types.KotlinType
class ChangeFunctionLiteralSignatureFix private constructor(
functionLiteral: KtFunctionLiteral,
functionDescriptor: FunctionDescriptor,
private val parameterTypes: List<KotlinType>
functionLiteral: KtFunctionLiteral,
functionDescriptor: FunctionDescriptor,
private val parameterTypes: List<KotlinType>
) : ChangeFunctionSignatureFix(functionLiteral, functionDescriptor) {
override fun getText() = "Change the signature of lambda expression"
@@ -42,25 +42,26 @@ class ChangeFunctionLiteralSignatureFix private constructor(
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
runChangeSignature(
project,
functionDescriptor,
object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify { descriptor ->
val validator = CollectingNameValidator()
descriptor.clearNonReceiverParameters()
for (type in parameterTypes) {
val name = KotlinNameSuggester.suggestNamesByType(type, validator, "param")[0]
descriptor.addParameter(KotlinParameterInfo(functionDescriptor, -1, name, KotlinTypeInfo(false, type)))
}
project,
functionDescriptor,
object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify { descriptor ->
val validator = CollectingNameValidator()
descriptor.clearNonReceiverParameters()
for (type in parameterTypes) {
val name = KotlinNameSuggester.suggestNamesByType(type, validator, "param")[0]
descriptor.addParameter(KotlinParameterInfo(functionDescriptor, -1, name, KotlinTypeInfo(false, type)))
}
}
}
override fun performSilently(affectedFunctions: Collection<PsiElement>) = false
override fun forcePerformForSelectedFunctionOnly() = false
},
element,
text)
override fun performSilently(affectedFunctions: Collection<PsiElement>) = false
override fun forcePerformForSelectedFunctionOnly() = false
},
element,
text
)
}
companion object : KotlinSingleIntentionActionFactoryWithDelegate<KtFunctionLiteral, Companion.Data>() {
@@ -77,7 +78,7 @@ class ChangeFunctionLiteralSignatureFix private constructor(
return Data(descriptor, parameterTypes)
}
override fun createFix(originalElement: KtFunctionLiteral, data: Data): IntentionAction?
= ChangeFunctionLiteralSignatureFix(originalElement, data.descriptor, data.parameterTypes)
override fun createFix(originalElement: KtFunctionLiteral, data: Data): IntentionAction? =
ChangeFunctionLiteralSignatureFix(originalElement, data.descriptor, data.parameterTypes)
}
}
@@ -44,8 +44,8 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
abstract class ChangeFunctionSignatureFix(
element: PsiElement,
protected val functionDescriptor: FunctionDescriptor
element: PsiElement,
protected val functionDescriptor: FunctionDescriptor
) : KotlinQuickFixAction<PsiElement>(element) {
override fun getFamilyName() = FAMILY_NAME
@@ -71,9 +71,7 @@ abstract class ChangeFunctionSignatureFix(
}
companion object : KotlinSingleIntentionActionFactoryWithDelegate<KtCallElement, CallableDescriptor>() {
override fun getElementOfInterest(diagnostic: Diagnostic): KtCallElement? {
return diagnostic.psiElement.getNonStrictParentOfType<KtCallElement>()
}
override fun getElementOfInterest(diagnostic: Diagnostic): KtCallElement? = diagnostic.psiElement.getNonStrictParentOfType()
override fun extractFixData(element: KtCallElement, diagnostic: Diagnostic): CallableDescriptor? {
return DiagnosticFactory.cast(diagnostic, Errors.TOO_MANY_ARGUMENTS, Errors.NO_VALUE_FOR_PARAMETER).a
@@ -81,15 +79,14 @@ abstract class ChangeFunctionSignatureFix(
override fun createFix(originalElement: KtCallElement, data: CallableDescriptor): ChangeFunctionSignatureFix? {
val functionDescriptor = data as? FunctionDescriptor
?: (data as? ValueParameterDescriptor)?.containingDeclaration as? FunctionDescriptor
?: return null
?: (data as? ValueParameterDescriptor)?.containingDeclaration as? FunctionDescriptor
?: return null
if (functionDescriptor.kind == SYNTHESIZED) return null
if (data is ValueParameterDescriptor) {
return RemoveParameterFix(originalElement, functionDescriptor, data)
}
else {
} else {
val parameters = functionDescriptor.valueParameters
val arguments = originalElement.valueArguments
@@ -97,8 +94,7 @@ abstract class ChangeFunctionSignatureFix(
val bindingContext = originalElement.analyze()
val call = originalElement.getCall(bindingContext) ?: return null
val argumentToParameter = call.mapArgumentsToParameters(functionDescriptor)
val hasTypeMismatches = argumentToParameter.any {
val (argument, parameter) = it
val hasTypeMismatches = argumentToParameter.any { (argument, parameter) ->
val argumentType = argument.getArgumentExpression()?.let { bindingContext.getType(it) }
argumentType == null || !KotlinTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameter.type)
}
@@ -110,9 +106,9 @@ abstract class ChangeFunctionSignatureFix(
}
private class RemoveParameterFix(
element: PsiElement,
functionDescriptor: FunctionDescriptor,
private val parameterToRemove: ValueParameterDescriptor
element: PsiElement,
functionDescriptor: FunctionDescriptor,
private val parameterToRemove: ValueParameterDescriptor
) : ChangeFunctionSignatureFix(element, functionDescriptor) {
override fun getText() = "Remove parameter '${parameterToRemove.name.asString()}'"
@@ -122,26 +118,27 @@ abstract class ChangeFunctionSignatureFix(
}
}
val FAMILY_NAME = "Change signature of function/constructor"
const val FAMILY_NAME = "Change signature of function/constructor"
fun runRemoveParameter(parameterDescriptor: ValueParameterDescriptor, context: PsiElement) {
val functionDescriptor = parameterDescriptor.containingDeclaration as FunctionDescriptor
runChangeSignature(
context.project,
functionDescriptor,
object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify { descriptor ->
val index = if (descriptor.receiver != null) parameterDescriptor.index + 1 else parameterDescriptor.index
descriptor.removeParameter(index)
}
context.project,
functionDescriptor,
object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify { descriptor ->
val index = if (descriptor.receiver != null) parameterDescriptor.index + 1 else parameterDescriptor.index
descriptor.removeParameter(index)
}
}
override fun performSilently(affectedFunctions: Collection<PsiElement>) = true
override fun forcePerformForSelectedFunctionOnly() = false
},
context,
"Remove parameter '${parameterDescriptor.name.asString()}'")
override fun performSilently(affectedFunctions: Collection<PsiElement>) = true
override fun forcePerformForSelectedFunctionOnly() = false
},
context,
"Remove parameter '${parameterDescriptor.name.asString()}'"
)
}
}