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