diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeParameterTypeFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeParameterTypeFix.kt index 719a3022ded..0482e9d0511 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeParameterTypeFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeParameterTypeFix.kt @@ -18,12 +18,17 @@ package org.jetbrains.kotlin.idea.quickfix import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.refactoring.changeSignature.* import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.util.ShortenReferences import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.KotlinType class ChangeParameterTypeFix(element: KtParameter, private val type: KotlinType) : KotlinQuickFixAction(element) { @@ -52,9 +57,17 @@ class ChangeParameterTypeFix(element: KtParameter, private val type: KotlinType) override fun getFamilyName() = KotlinBundle.message("change.type.family") public override operator fun invoke(project: Project, editor: Editor?, file: KtFile) { - val newTypeRef = KtPsiFactory(file).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type)) - element.setTypeReference(newTypeRef)?.let { - ShortenReferences.DEFAULT.process(it) + val function = element.getStrictParentOfType() ?: return + val parameterIndex = function.valueParameters.indexOf(element) + val context = function.analyze() + val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor ?: return + val configuration = object : KotlinChangeSignatureConfiguration { + override fun configure(originalDescriptor: KotlinMethodDescriptor) = originalDescriptor.apply { + parameters[if (receiver != null) parameterIndex + 1 else parameterIndex].currentTypeInfo = KotlinTypeInfo(false, type) + } + + override fun performSilently(affectedFunctions: Collection) = true } + runChangeSignature(element.project, descriptor, configuration, element, text) } } diff --git a/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.after.Dependency.java b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.after.Dependency.java new file mode 100644 index 00000000000..c51b60423ec --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.after.Dependency.java @@ -0,0 +1,11 @@ +// "Change parameter 'a' type of function 'test.B.foo' to 'String'" "true" +package test; + +import org.jetbrains.annotations.NotNull; + +class J extends B { + @Override + void foo(@NotNull String a) { + super.foo(a); + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.after.kt b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.after.kt new file mode 100644 index 00000000000..13ace8cae48 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.after.kt @@ -0,0 +1,15 @@ +// "Change parameter 'a' type of function 'test.B.foo' to 'String'" "true" +// DISABLE-ERRORS +package test + +open class B { + open fun foo(a: String) {} +} + +class C : B() { + override fun foo(a: String) = super.foo(a) +} + +fun test(b: B) { + b.foo("") +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.before.Dependency.java b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.before.Dependency.java new file mode 100644 index 00000000000..5379e6829f2 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.before.Dependency.java @@ -0,0 +1,9 @@ +// "Change parameter 'a' type of function 'test.B.foo' to 'String'" "true" +package test; + +class J extends B { + @Override + void foo(int a) { + super.foo(a); + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.before.Main.kt b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.before.Main.kt new file mode 100644 index 00000000000..2b54a9299c6 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/paramTypeInOverrides.before.Main.kt @@ -0,0 +1,15 @@ +// "Change parameter 'a' type of function 'test.B.foo' to 'String'" "true" +// DISABLE-ERRORS +package test + +open class B { + open fun foo(a: Int) {} +} + +class C : B() { + override fun foo(a: Int) = super.foo(a) +} + +fun test(b: B) { + b.foo("") +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 4f78108a176..1fcb1df18b4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -1490,6 +1490,12 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/typeMismatch"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), true); } + @TestMetadata("paramTypeInOverrides.before.Main.kt") + public void testParamTypeInOverrides() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/paramTypeInOverrides.before.Main.kt"); + doTestWithExtraFile(fileName); + } + @TestMetadata("idea/testData/quickfix/typeMismatch/genericVarianceViolation") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)