From 1b0fac4a677c954e2cf23ff9456cea0a638c0aab Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 20 Dec 2019 17:29:58 +0900 Subject: [PATCH] Add quick fix for PROPERTY_TYPE_MISMATCH_ON_OVERRIDE on constructor parameter #KT-29934 Fixed --- .../idea/quickfix/ChangeVariableTypeFix.kt | 67 +++++++++---------- ...OverriddenPropertyTypeFromCtorParameter.kt | 6 ++ ...ddenPropertyTypeFromCtorParameter.kt.after | 6 ++ .../changeOverridingCtorParameterType.kt | 6 ++ ...changeOverridingCtorParameterType.kt.after | 6 ++ .../idea/quickfix/QuickFixTestGenerated.java | 10 +++ 6 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt create mode 100644 idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt.after create mode 100644 idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt create mode 100644 idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt index 65e178e4344..41c8953b65a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt @@ -39,7 +39,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import java.util.* -open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinType) : KotlinQuickFixAction(element) { +open class ChangeVariableTypeFix(element: KtCallableDeclaration, type: KotlinType) : KotlinQuickFixAction(element) { private val typeContainsError = ErrorUtils.containsErrorType(type) private val typePresentation = IdeDescriptorRenderers.SOURCE_CODE_TYPES_WITH_SHORT_NAMES.renderType(type) private val typeSourceCode = IdeDescriptorRenderers.SOURCE_CODE_TYPES.renderType(type) @@ -67,7 +67,7 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp } } - class OnType(element: KtVariableDeclaration, type: KotlinType) : ChangeVariableTypeFix(element, type), HighPriorityAction { + class OnType(element: KtCallableDeclaration, type: KotlinType) : ChangeVariableTypeFix(element, type), HighPriorityAction { override fun variablePresentation() = null } @@ -122,45 +122,44 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp override fun doCreateActions(diagnostic: Diagnostic): List { val actions = LinkedList() - if (diagnostic.psiElement is KtProperty) { - val property = diagnostic.psiElement as KtProperty - val descriptor = property.resolveToDescriptorIfAny(BodyResolveMode.FULL) as? PropertyDescriptor ?: return actions + val element = diagnostic.psiElement as? KtCallableDeclaration + if (element !is KtProperty && element !is KtParameter) return actions + val descriptor = element.resolveToDescriptorIfAny(BodyResolveMode.FULL) as? PropertyDescriptor ?: return actions - var lowerBoundOfOverriddenPropertiesTypes = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(descriptor) + var lowerBoundOfOverriddenPropertiesTypes = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(descriptor) - val propertyType = descriptor.returnType ?: error("Property type cannot be null if it mismatches something") + val propertyType = descriptor.returnType ?: error("Property type cannot be null if it mismatches something") - val overriddenMismatchingProperties = LinkedList() - var canChangeOverriddenPropertyType = true - for (overriddenProperty in descriptor.overriddenDescriptors) { - val overriddenPropertyType = overriddenProperty.returnType - if (overriddenPropertyType != null) { - if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(propertyType, overriddenPropertyType)) { - overriddenMismatchingProperties.add(overriddenProperty) - } else if (overriddenProperty.isVar && !KotlinTypeChecker.DEFAULT.equalTypes( - overriddenPropertyType, - propertyType - ) - ) { - canChangeOverriddenPropertyType = false - } - if (overriddenProperty.isVar && lowerBoundOfOverriddenPropertiesTypes != null && - !KotlinTypeChecker.DEFAULT.equalTypes(lowerBoundOfOverriddenPropertiesTypes, overriddenPropertyType) - ) { - lowerBoundOfOverriddenPropertiesTypes = null - } + val overriddenMismatchingProperties = LinkedList() + var canChangeOverriddenPropertyType = true + for (overriddenProperty in descriptor.overriddenDescriptors) { + val overriddenPropertyType = overriddenProperty.returnType + if (overriddenPropertyType != null) { + if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(propertyType, overriddenPropertyType)) { + overriddenMismatchingProperties.add(overriddenProperty) + } else if (overriddenProperty.isVar && !KotlinTypeChecker.DEFAULT.equalTypes( + overriddenPropertyType, + propertyType + ) + ) { + canChangeOverriddenPropertyType = false + } + if (overriddenProperty.isVar && lowerBoundOfOverriddenPropertiesTypes != null && + !KotlinTypeChecker.DEFAULT.equalTypes(lowerBoundOfOverriddenPropertiesTypes, overriddenPropertyType) + ) { + lowerBoundOfOverriddenPropertiesTypes = null } } + } - if (lowerBoundOfOverriddenPropertiesTypes != null) { - actions.add(OnType(property, lowerBoundOfOverriddenPropertiesTypes)) - } + if (lowerBoundOfOverriddenPropertiesTypes != null) { + actions.add(OnType(element, lowerBoundOfOverriddenPropertiesTypes)) + } - if (overriddenMismatchingProperties.size == 1 && canChangeOverriddenPropertyType) { - val overriddenProperty = DescriptorToSourceUtils.descriptorToDeclaration(overriddenMismatchingProperties.single()) - if (overriddenProperty is KtProperty) { - actions.add(ForOverridden(overriddenProperty, propertyType)) - } + if (overriddenMismatchingProperties.size == 1 && canChangeOverriddenPropertyType) { + val overriddenProperty = DescriptorToSourceUtils.descriptorToDeclaration(overriddenMismatchingProperties.single()) + if (overriddenProperty is KtProperty) { + actions.add(ForOverridden(overriddenProperty, propertyType)) } } diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt new file mode 100644 index 00000000000..9daa097c738 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt @@ -0,0 +1,6 @@ +// "Change type of base property 'A.x' to 'Any'" "true" +interface A { + val x: CharSequence +} + +class B(override val x: Any) : A \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt.after b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt.after new file mode 100644 index 00000000000..970fa13870e --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt.after @@ -0,0 +1,6 @@ +// "Change type of base property 'A.x' to 'Any'" "true" +interface A { + val x: Any +} + +class B(override val x: Any) : A \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt new file mode 100644 index 00000000000..280487ae400 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt @@ -0,0 +1,6 @@ +// "Change type to 'CharSequence'" "true" +interface A { + val x: CharSequence +} + +class B(override val x: Any) : A \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt.after b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt.after new file mode 100644 index 00000000000..2c475dd6e1a --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt.after @@ -0,0 +1,6 @@ +// "Change type to 'CharSequence'" "true" +interface A { + val x: CharSequence +} + +class B(override val x: CharSequence) : A \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index c89dcc9f2f5..8cbf86fe271 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -10085,6 +10085,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyType2.kt"); } + @TestMetadata("changeOverriddenPropertyTypeFromCtorParameter.kt") + public void testChangeOverriddenPropertyTypeFromCtorParameter() throws Exception { + runTest("idea/testData/quickfix/override/typeMismatchOnOverride/changeOverriddenPropertyTypeFromCtorParameter.kt"); + } + + @TestMetadata("changeOverridingCtorParameterType.kt") + public void testChangeOverridingCtorParameterType() throws Exception { + runTest("idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingCtorParameterType.kt"); + } + @TestMetadata("changeOverridingPropertyTypeToFunctionType.kt") public void testChangeOverridingPropertyTypeToFunctionType() throws Exception { runTest("idea/testData/quickfix/override/typeMismatchOnOverride/changeOverridingPropertyTypeToFunctionType.kt");