"Remove parameter" quick fix makes generic function call incompilable when type could be inferred from removed parameter only
#KT-23511 Fixed
This commit is contained in:
committed by
Alexey Sedunov
parent
8271e85dbb
commit
1d0a11cecd
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.quickfix
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAny
|
||||
@@ -25,6 +26,8 @@ import org.jetbrains.kotlin.idea.intentions.RemoveEmptyPrimaryConstructorIntenti
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
@@ -36,15 +39,25 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA
|
||||
override fun startInWriteAction(): Boolean = false
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||
val element = element ?: return
|
||||
val primaryConstructor = element.parent?.parent as? KtPrimaryConstructor
|
||||
val parameterList = element.parent as? KtParameterList
|
||||
val parameterDescriptor = element.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
|
||||
ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, element)
|
||||
val nextParameter = parameterList?.parameters?.getOrNull(parameterDescriptor.index)
|
||||
if (nextParameter != null) {
|
||||
editor?.caretModel?.moveToOffset(nextParameter.startOffset)
|
||||
val parameter = element ?: return
|
||||
val parameterList = parameter.parent as? KtParameterList ?: return
|
||||
val parameterDescriptor = parameter.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
|
||||
val parameterSize = parameterList.parameters.size
|
||||
val redundantTypeParameter = redundantTypeParameter(parameter)
|
||||
val primaryConstructor = parameterList.parent as? KtPrimaryConstructor
|
||||
|
||||
ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, parameter)
|
||||
if (redundantTypeParameter != null) {
|
||||
runRemoveTypeParameter(redundantTypeParameter)
|
||||
}
|
||||
|
||||
if (parameterSize > 1) {
|
||||
val nextParameter = parameterList.parameters.getOrNull(parameterDescriptor.index)
|
||||
if (nextParameter != null) {
|
||||
editor?.caretModel?.moveToOffset(nextParameter.startOffset)
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryConstructor != null) {
|
||||
val removeConstructorIntention = RemoveEmptyPrimaryConstructorIntention()
|
||||
if (removeConstructorIntention.isApplicableTo(primaryConstructor)) {
|
||||
@@ -56,6 +69,29 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA
|
||||
}
|
||||
}
|
||||
|
||||
private fun redundantTypeParameter(parameter: KtParameter): KtTypeParameter? {
|
||||
val typeParameter = parameter.typeReference?.typeElement?.getChildOfType<KtNameReferenceExpression>()?.reference?.resolve()
|
||||
as? KtTypeParameter ?: return null
|
||||
val parameterParent =
|
||||
parameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true }
|
||||
val typeParameterParent =
|
||||
typeParameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true }
|
||||
return if (parameterParent == typeParameterParent) typeParameter else null
|
||||
}
|
||||
|
||||
private fun runRemoveTypeParameter(typeParameter: KtTypeParameter) {
|
||||
if (ReferencesSearch.search(typeParameter).findFirst() != null) return
|
||||
|
||||
val typeParameterList = typeParameter.parent as? KtTypeParameterList ?: return
|
||||
val typeParameters = typeParameterList.parameters
|
||||
runWriteAction {
|
||||
if (typeParameters.size == 1)
|
||||
typeParameterList.delete()
|
||||
else
|
||||
EditCommaSeparatedListHelper.removeItem(typeParameter)
|
||||
}
|
||||
}
|
||||
|
||||
companion object : KotlinSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtParameter>? {
|
||||
val parameter = Errors.UNUSED_PARAMETER.cast(diagnostic).psiElement
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
fun <X> foo(<caret>x: X) {}
|
||||
|
||||
fun test() {
|
||||
foo(x = 1)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
fun foo(<caret>) {}
|
||||
|
||||
fun test() {
|
||||
foo()
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
fun <X> foo(<caret>x: X, x2: X) {}
|
||||
|
||||
fun test() {
|
||||
foo(x = 1, x2 = 2)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
fun <X> foo(<caret>x2: X) {}
|
||||
|
||||
fun test() {
|
||||
foo(x2 = 2)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
fun <X, Y> foo(<caret>x: X, y: Y) {}
|
||||
|
||||
fun test() {
|
||||
foo(x = 1, y = 2)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
fun <Y> foo(<caret>y: Y) {}
|
||||
|
||||
fun test() {
|
||||
foo(y = 2)
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
class Bar<X> {
|
||||
fun foo(<caret>x: X) {}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
class Bar<X> {
|
||||
fun foo(<caret>) {}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
class Foo<X>(<caret>x: X)
|
||||
|
||||
val foo = Foo(1)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
class Foo<caret>
|
||||
|
||||
val foo = Foo()
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
class Foo<X> {
|
||||
constructor(<caret>x: X)
|
||||
}
|
||||
|
||||
val foo = Foo(1)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Remove parameter 'x'" "true"
|
||||
class Foo {
|
||||
constructor(<caret>)
|
||||
}
|
||||
|
||||
val foo = Foo()
|
||||
@@ -1643,6 +1643,42 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
runTest("idea/testData/quickfix/changeSignature/removeUnusedParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("removeUnusedParameterWithTypeParameter.kt")
|
||||
public void testRemoveUnusedParameterWithTypeParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("removeUnusedParameterWithTypeParameter2.kt")
|
||||
public void testRemoveUnusedParameterWithTypeParameter2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("removeUnusedParameterWithTypeParameter3.kt")
|
||||
public void testRemoveUnusedParameterWithTypeParameter3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("removeUnusedParameterWithTypeParameter4.kt")
|
||||
public void testRemoveUnusedParameterWithTypeParameter4() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter4.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("removeUnusedParameterWithTypeParameter5.kt")
|
||||
public void testRemoveUnusedParameterWithTypeParameter5() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter5.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("removeUnusedParameterWithTypeParameter6.kt")
|
||||
public void testRemoveUnusedParameterWithTypeParameter6() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter6.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("removeUnusedPrimaryConstructorParameter.kt")
|
||||
public void testRemoveUnusedPrimaryConstructorParameter() throws Exception {
|
||||
runTest("idea/testData/quickfix/changeSignature/removeUnusedPrimaryConstructorParameter.kt");
|
||||
|
||||
Reference in New Issue
Block a user