Code improvements

This commit is contained in:
Valentin Kipyatkov
2015-10-14 17:38:56 +03:00
parent f67e05de72
commit bce9f26327
2 changed files with 71 additions and 125 deletions
@@ -56,22 +56,10 @@ abstract class ChangeFunctionSignatureFix(
override fun startInWriteAction() = false
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
if (!super.isAvailable(project, editor, file)) {
return false
}
if (!super.isAvailable(project, editor, file)) return false
val declarations = DescriptorToSourceUtilsIde.getAllDeclarations(project, functionDescriptor)
if (declarations.isEmpty()) {
return false
}
for (declaration in declarations) {
if (!declaration.isValid || !QuickFixUtil.canModifyElement(declaration)) {
return false
}
}
return true
return declarations.all { it.isValid && QuickFixUtil.canModifyElement(it) }
}
protected fun getNewArgumentName(argument: ValueArgument, validator: Function1<String, Boolean>): String {
@@ -80,10 +68,12 @@ abstract class ChangeFunctionSignatureFix(
if (argumentName != null) {
return KotlinNameSuggester.suggestNameByName(argumentName.asName.asString(), validator)
} else if (expression != null) {
}
else if (expression != null) {
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
return KotlinNameSuggester.suggestNamesByExpressionAndType(expression, bindingContext, validator, "param").iterator().next()
} else {
return KotlinNameSuggester.suggestNamesByExpressionAndType(expression, bindingContext, validator, "param").first()
}
else {
return KotlinNameSuggester.suggestNameByName("param", validator)
}
}
@@ -91,119 +81,75 @@ abstract class ChangeFunctionSignatureFix(
protected fun getNewParameterInfo(
functionDescriptor: FunctionDescriptor,
argument: ValueArgument,
validator: Function1<String, Boolean>): JetParameterInfo {
validator: Function1<String, Boolean>
): JetParameterInfo {
val name = getNewArgumentName(argument, validator)
val expression = argument.getArgumentExpression()
val type = expression?.let { it.analyze().getType(it) } ?: functionDescriptor.builtIns.nullableAnyType
val parameterInfo = JetParameterInfo(functionDescriptor, -1, name, type, null, null, JetValVar.None, null)
parameterInfo.currentTypeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
return parameterInfo
return JetParameterInfo(functionDescriptor, -1, name, type, null, null, JetValVar.None, null)
.apply { currentTypeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(type) }
}
companion object {
fun createFactory(): JetSingleIntentionActionFactory {
return object : JetSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
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
}
}
object Factory : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
val callElement = PsiTreeUtil.getParentOfType(diagnostic.psiElement, JetCallElement::class.java) ?: return null
val descriptor = DiagnosticFactory.cast(diagnostic, Errors.TOO_MANY_ARGUMENTS, Errors.NO_VALUE_FOR_PARAMETER).a
return createFix(callElement, callElement, descriptor)
}
}
fun createFactoryForParametersNumberMismatch(): JetSingleIntentionActionFactory {
return object : JetSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
val diagnosticWithParameters = EXPECTED_PARAMETERS_NUMBER_MISMATCH.cast(diagnostic)
val functionLiteral = diagnosticWithParameters.psiElement
val descriptor = functionLiteral.resolveToDescriptor()
if (descriptor is FunctionDescriptor && functionLiteral is JetFunctionLiteral) {
return ChangeFunctionLiteralSignatureFix(functionLiteral, descriptor,
diagnosticWithParameters.b)
} else {
return null
}
}
}
object FactoryForParametersNumberMismatch: JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
val diagnosticWithParameters = EXPECTED_PARAMETERS_NUMBER_MISMATCH.cast(diagnostic)
val functionLiteral = diagnosticWithParameters.psiElement as? JetFunctionLiteral ?: return null
val descriptor = functionLiteral.resolveToDescriptor() as? FunctionDescriptor ?: return null
return ChangeFunctionLiteralSignatureFix(functionLiteral, descriptor, diagnosticWithParameters.b)
}
}
fun createFactoryForUnusedParameter(): JetSingleIntentionActionFactory {
return object : JetSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
@SuppressWarnings("unchecked")
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
object FactoryForUnusedParameter : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
val descriptor = UNUSED_PARAMETER.cast(diagnostic).a as? ValueParameterDescriptor ?: return null
return createFix(null, diagnostic.psiElement, descriptor)
}
}
}
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())
IMPLICIT_NOTHING_RETURN_TYPE.registerFactory(ChangeFunctionReturnTypeFix.createFactoryForChangingReturnTypeToNothing())
TOO_MANY_ARGUMENTS.registerFactory(ChangeFunctionSignatureFix.createFactory())
NO_VALUE_FOR_PARAMETER.registerFactory(ChangeFunctionSignatureFix.createFactory())
UNUSED_PARAMETER.registerFactory(ChangeFunctionSignatureFix.createFactoryForUnusedParameter())
EXPECTED_PARAMETERS_NUMBER_MISMATCH.registerFactory(ChangeFunctionSignatureFix.createFactoryForParametersNumberMismatch())
TOO_MANY_ARGUMENTS.registerFactory(ChangeFunctionSignatureFix.Factory)
NO_VALUE_FOR_PARAMETER.registerFactory(ChangeFunctionSignatureFix.Factory)
UNUSED_PARAMETER.registerFactory(ChangeFunctionSignatureFix.FactoryForUnusedParameter)
EXPECTED_PARAMETERS_NUMBER_MISMATCH.registerFactory(ChangeFunctionSignatureFix.FactoryForParametersNumberMismatch)
EXPECTED_PARAMETER_TYPE_MISMATCH.registerFactory(ChangeTypeFix.createFactoryForExpectedParameterTypeMismatch())