Code improvements
This commit is contained in:
@@ -56,22 +56,10 @@ abstract class ChangeFunctionSignatureFix(
|
|||||||
override fun startInWriteAction() = false
|
override fun startInWriteAction() = false
|
||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
||||||
if (!super.isAvailable(project, editor, file)) {
|
if (!super.isAvailable(project, editor, file)) return false
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val declarations = DescriptorToSourceUtilsIde.getAllDeclarations(project, functionDescriptor)
|
val declarations = DescriptorToSourceUtilsIde.getAllDeclarations(project, functionDescriptor)
|
||||||
if (declarations.isEmpty()) {
|
return declarations.all { it.isValid && QuickFixUtil.canModifyElement(it) }
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for (declaration in declarations) {
|
|
||||||
if (!declaration.isValid || !QuickFixUtil.canModifyElement(declaration)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun getNewArgumentName(argument: ValueArgument, validator: Function1<String, Boolean>): String {
|
protected fun getNewArgumentName(argument: ValueArgument, validator: Function1<String, Boolean>): String {
|
||||||
@@ -80,10 +68,12 @@ abstract class ChangeFunctionSignatureFix(
|
|||||||
|
|
||||||
if (argumentName != null) {
|
if (argumentName != null) {
|
||||||
return KotlinNameSuggester.suggestNameByName(argumentName.asName.asString(), validator)
|
return KotlinNameSuggester.suggestNameByName(argumentName.asName.asString(), validator)
|
||||||
} else if (expression != null) {
|
}
|
||||||
|
else if (expression != null) {
|
||||||
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
return KotlinNameSuggester.suggestNamesByExpressionAndType(expression, bindingContext, validator, "param").iterator().next()
|
return KotlinNameSuggester.suggestNamesByExpressionAndType(expression, bindingContext, validator, "param").first()
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return KotlinNameSuggester.suggestNameByName("param", validator)
|
return KotlinNameSuggester.suggestNameByName("param", validator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,119 +81,75 @@ abstract class ChangeFunctionSignatureFix(
|
|||||||
protected fun getNewParameterInfo(
|
protected fun getNewParameterInfo(
|
||||||
functionDescriptor: FunctionDescriptor,
|
functionDescriptor: FunctionDescriptor,
|
||||||
argument: ValueArgument,
|
argument: ValueArgument,
|
||||||
validator: Function1<String, Boolean>): JetParameterInfo {
|
validator: Function1<String, Boolean>
|
||||||
|
): JetParameterInfo {
|
||||||
val name = getNewArgumentName(argument, validator)
|
val name = getNewArgumentName(argument, validator)
|
||||||
val expression = argument.getArgumentExpression()
|
val expression = argument.getArgumentExpression()
|
||||||
val type = expression?.let { it.analyze().getType(it) } ?: functionDescriptor.builtIns.nullableAnyType
|
val type = expression?.let { it.analyze().getType(it) } ?: functionDescriptor.builtIns.nullableAnyType
|
||||||
val parameterInfo = JetParameterInfo(functionDescriptor, -1, name, type, null, null, JetValVar.None, null)
|
return JetParameterInfo(functionDescriptor, -1, name, type, null, null, JetValVar.None, null)
|
||||||
parameterInfo.currentTypeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
|
.apply { currentTypeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(type) }
|
||||||
|
|
||||||
return parameterInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
object Factory : JetSingleIntentionActionFactory() {
|
||||||
|
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
||||||
fun createFactory(): JetSingleIntentionActionFactory {
|
val callElement = PsiTreeUtil.getParentOfType(diagnostic.psiElement, JetCallElement::class.java) ?: return null
|
||||||
return object : JetSingleIntentionActionFactory() {
|
val descriptor = DiagnosticFactory.cast(diagnostic, Errors.TOO_MANY_ARGUMENTS, Errors.NO_VALUE_FOR_PARAMETER).a
|
||||||
public override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
return createFix(callElement, callElement, descriptor)
|
||||||
val callElement = PsiTreeUtil.getParentOfType(diagnostic.psiElement, JetCallElement::class.java)
|
|
||||||
//noinspection unchecked
|
|
||||||
val descriptor = DiagnosticFactory.cast(diagnostic, Errors.TOO_MANY_ARGUMENTS, Errors.NO_VALUE_FOR_PARAMETER).a
|
|
||||||
|
|
||||||
if (callElement != null) {
|
|
||||||
return createFix(callElement, callElement, descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun createFactoryForParametersNumberMismatch(): JetSingleIntentionActionFactory {
|
object FactoryForParametersNumberMismatch: JetSingleIntentionActionFactory() {
|
||||||
return object : JetSingleIntentionActionFactory() {
|
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
||||||
public override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
val diagnosticWithParameters = EXPECTED_PARAMETERS_NUMBER_MISMATCH.cast(diagnostic)
|
||||||
val diagnosticWithParameters = EXPECTED_PARAMETERS_NUMBER_MISMATCH.cast(diagnostic)
|
val functionLiteral = diagnosticWithParameters.psiElement as? JetFunctionLiteral ?: return null
|
||||||
val functionLiteral = diagnosticWithParameters.psiElement
|
val descriptor = functionLiteral.resolveToDescriptor() as? FunctionDescriptor ?: return null
|
||||||
val descriptor = functionLiteral.resolveToDescriptor()
|
return ChangeFunctionLiteralSignatureFix(functionLiteral, descriptor, diagnosticWithParameters.b)
|
||||||
|
|
||||||
if (descriptor is FunctionDescriptor && functionLiteral is JetFunctionLiteral) {
|
|
||||||
return ChangeFunctionLiteralSignatureFix(functionLiteral, descriptor,
|
|
||||||
diagnosticWithParameters.b)
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun createFactoryForUnusedParameter(): JetSingleIntentionActionFactory {
|
object FactoryForUnusedParameter : JetSingleIntentionActionFactory() {
|
||||||
return object : JetSingleIntentionActionFactory() {
|
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
||||||
public override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
val descriptor = UNUSED_PARAMETER.cast(diagnostic).a as? ValueParameterDescriptor ?: return null
|
||||||
@SuppressWarnings("unchecked")
|
return createFix(null, diagnostic.psiElement, descriptor)
|
||||||
val descriptor = UNUSED_PARAMETER.cast(diagnostic).a
|
|
||||||
|
|
||||||
if (descriptor is ValueParameterDescriptor) {
|
|
||||||
return createFix(null, diagnostic.psiElement, descriptor as CallableDescriptor)
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createFix(callElement: JetCallElement?, context: PsiElement, descriptor: CallableDescriptor): ChangeFunctionSignatureFix? {
|
|
||||||
var functionDescriptor: FunctionDescriptor? = null
|
|
||||||
|
|
||||||
if (descriptor is FunctionDescriptor) {
|
|
||||||
functionDescriptor = descriptor
|
|
||||||
} else if (descriptor is ValueParameterDescriptor) {
|
|
||||||
val containingDescriptor = descriptor.containingDeclaration
|
|
||||||
|
|
||||||
if (containingDescriptor is FunctionDescriptor) {
|
|
||||||
functionDescriptor = containingDescriptor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (functionDescriptor == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (functionDescriptor.kind == SYNTHESIZED) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor is ValueParameterDescriptor) {
|
|
||||||
return RemoveFunctionParametersFix(context, functionDescriptor, descriptor)
|
|
||||||
} else {
|
|
||||||
val parameters = functionDescriptor.valueParameters
|
|
||||||
val arguments = callElement!!.valueArguments
|
|
||||||
|
|
||||||
if (arguments.size() > parameters.size()) {
|
|
||||||
val bindingContext = callElement.analyze()
|
|
||||||
val hasTypeMismatches = hasTypeMismatches(parameters, arguments, bindingContext)
|
|
||||||
return AddFunctionParametersFix(callElement, functionDescriptor, hasTypeMismatches)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasTypeMismatches(
|
|
||||||
parameters: List<ValueParameterDescriptor>,
|
|
||||||
arguments: List<ValueArgument>,
|
|
||||||
bindingContext: BindingContext): Boolean {
|
|
||||||
for (i in parameters.indices) {
|
|
||||||
assert(i < arguments.size()) // number of parameters must not be greater than the number of arguments (it's called only for TOO_MANY_ARGUMENTS error)
|
|
||||||
val argumentExpression = arguments.get(i).getArgumentExpression()
|
|
||||||
val argumentType = if (argumentExpression != null) bindingContext.getType(argumentExpression) else null
|
|
||||||
val parameterType = parameters.get(i).type
|
|
||||||
|
|
||||||
if (argumentType == null || !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameterType)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createFix(callElement: JetCallElement?, context: PsiElement, descriptor: CallableDescriptor): ChangeFunctionSignatureFix? {
|
||||||
|
val functionDescriptor = when (descriptor) {
|
||||||
|
is FunctionDescriptor -> descriptor as FunctionDescriptor
|
||||||
|
else -> if (descriptor is ValueParameterDescriptor) descriptor.containingDeclaration as? FunctionDescriptor
|
||||||
|
else null
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
|
if (functionDescriptor.kind == SYNTHESIZED) return null
|
||||||
|
|
||||||
|
if (descriptor is ValueParameterDescriptor) {
|
||||||
|
return RemoveFunctionParametersFix(context, functionDescriptor, descriptor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val parameters = functionDescriptor.valueParameters
|
||||||
|
val arguments = callElement!!.valueArguments
|
||||||
|
|
||||||
|
if (arguments.size > parameters.size) {
|
||||||
|
val hasTypeMismatches = hasTypeMismatches(parameters, arguments, callElement.analyze())
|
||||||
|
return AddFunctionParametersFix(callElement, functionDescriptor, hasTypeMismatches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasTypeMismatches(
|
||||||
|
parameters: List<ValueParameterDescriptor>,
|
||||||
|
arguments: List<ValueArgument>,
|
||||||
|
bindingContext: BindingContext
|
||||||
|
): Boolean {
|
||||||
|
assert(parameters.size <= arguments.size) // number of parameters must not be greater than the number of arguments (it's called only for TOO_MANY_ARGUMENTS error)
|
||||||
|
for ((parameter, argument) in parameters.zip(arguments)) {
|
||||||
|
val argumentType = argument.getArgumentExpression()?.let { bindingContext.getType(it) }
|
||||||
|
if (argumentType == null || !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameter.type)) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -222,10 +222,10 @@ public class QuickFixRegistrar : QuickFixContributor {
|
|||||||
COMPARE_TO_TYPE_MISMATCH.registerFactory(ChangeFunctionReturnTypeFix.createFactoryForCompareToTypeMismatch())
|
COMPARE_TO_TYPE_MISMATCH.registerFactory(ChangeFunctionReturnTypeFix.createFactoryForCompareToTypeMismatch())
|
||||||
IMPLICIT_NOTHING_RETURN_TYPE.registerFactory(ChangeFunctionReturnTypeFix.createFactoryForChangingReturnTypeToNothing())
|
IMPLICIT_NOTHING_RETURN_TYPE.registerFactory(ChangeFunctionReturnTypeFix.createFactoryForChangingReturnTypeToNothing())
|
||||||
|
|
||||||
TOO_MANY_ARGUMENTS.registerFactory(ChangeFunctionSignatureFix.createFactory())
|
TOO_MANY_ARGUMENTS.registerFactory(ChangeFunctionSignatureFix.Factory)
|
||||||
NO_VALUE_FOR_PARAMETER.registerFactory(ChangeFunctionSignatureFix.createFactory())
|
NO_VALUE_FOR_PARAMETER.registerFactory(ChangeFunctionSignatureFix.Factory)
|
||||||
UNUSED_PARAMETER.registerFactory(ChangeFunctionSignatureFix.createFactoryForUnusedParameter())
|
UNUSED_PARAMETER.registerFactory(ChangeFunctionSignatureFix.FactoryForUnusedParameter)
|
||||||
EXPECTED_PARAMETERS_NUMBER_MISMATCH.registerFactory(ChangeFunctionSignatureFix.createFactoryForParametersNumberMismatch())
|
EXPECTED_PARAMETERS_NUMBER_MISMATCH.registerFactory(ChangeFunctionSignatureFix.FactoryForParametersNumberMismatch)
|
||||||
|
|
||||||
EXPECTED_PARAMETER_TYPE_MISMATCH.registerFactory(ChangeTypeFix.createFactoryForExpectedParameterTypeMismatch())
|
EXPECTED_PARAMETER_TYPE_MISMATCH.registerFactory(ChangeTypeFix.createFactoryForExpectedParameterTypeMismatch())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user