"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.editor.Editor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAny
|
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.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
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.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
@@ -36,15 +39,25 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA
|
|||||||
override fun startInWriteAction(): Boolean = false
|
override fun startInWriteAction(): Boolean = false
|
||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
val element = element ?: return
|
val parameter = element ?: return
|
||||||
val primaryConstructor = element.parent?.parent as? KtPrimaryConstructor
|
val parameterList = parameter.parent as? KtParameterList ?: return
|
||||||
val parameterList = element.parent as? KtParameterList
|
val parameterDescriptor = parameter.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
|
||||||
val parameterDescriptor = element.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
|
val parameterSize = parameterList.parameters.size
|
||||||
ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, element)
|
val redundantTypeParameter = redundantTypeParameter(parameter)
|
||||||
val nextParameter = parameterList?.parameters?.getOrNull(parameterDescriptor.index)
|
val primaryConstructor = parameterList.parent as? KtPrimaryConstructor
|
||||||
if (nextParameter != null) {
|
|
||||||
editor?.caretModel?.moveToOffset(nextParameter.startOffset)
|
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) {
|
if (primaryConstructor != null) {
|
||||||
val removeConstructorIntention = RemoveEmptyPrimaryConstructorIntention()
|
val removeConstructorIntention = RemoveEmptyPrimaryConstructorIntention()
|
||||||
if (removeConstructorIntention.isApplicableTo(primaryConstructor)) {
|
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() {
|
companion object : KotlinSingleIntentionActionFactory() {
|
||||||
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtParameter>? {
|
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtParameter>? {
|
||||||
val parameter = Errors.UNUSED_PARAMETER.cast(diagnostic).psiElement
|
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");
|
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")
|
@TestMetadata("removeUnusedPrimaryConstructorParameter.kt")
|
||||||
public void testRemoveUnusedPrimaryConstructorParameter() throws Exception {
|
public void testRemoveUnusedPrimaryConstructorParameter() throws Exception {
|
||||||
runTest("idea/testData/quickfix/changeSignature/removeUnusedPrimaryConstructorParameter.kt");
|
runTest("idea/testData/quickfix/changeSignature/removeUnusedPrimaryConstructorParameter.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user