From 20535feb31d3d6e27fd379c05efb0f81d84ecc2a Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 23 May 2018 19:27:11 +0900 Subject: [PATCH] "Remove parameter" quick fix: Remove unused type parameter used as type projection #KT-23511 --- .../RemoveUnusedFunctionParameterFix.kt | 50 +++++++++---------- ...removeUnusedParameterWithTypeParameter7.kt | 8 +++ ...UnusedParameterWithTypeParameter7.kt.after | 8 +++ .../idea/quickfix/QuickFixTestGenerated.java | 5 ++ 4 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt create mode 100644 idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUnusedFunctionParameterFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUnusedFunctionParameterFix.kt index 330f81962c1..775897d38b3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUnusedFunctionParameterFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUnusedFunctionParameterFix.kt @@ -25,10 +25,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAn import org.jetbrains.kotlin.idea.intentions.RemoveEmptyPrimaryConstructorIntention 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.psi.psiUtil.* import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixAction(parameter) { @@ -43,13 +40,11 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA val parameterList = parameter.parent as? KtParameterList ?: return val parameterDescriptor = parameter.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return val parameterSize = parameterList.parameters.size - val redundantTypeParameter = redundantTypeParameter(parameter) + val typeParameters = typeParameters(parameter) val primaryConstructor = parameterList.parent as? KtPrimaryConstructor ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, parameter) - if (redundantTypeParameter != null) { - runRemoveTypeParameter(redundantTypeParameter) - } + runRemoveUnusedTypeParameters(typeParameters) if (parameterSize > 1) { val nextParameter = parameterList.parameters.getOrNull(parameterDescriptor.index) @@ -69,26 +64,28 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA } } - private fun redundantTypeParameter(parameter: KtParameter): KtTypeParameter? { - val typeParameter = parameter.typeReference?.typeElement?.getChildOfType()?.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 typeParameters(parameter: KtParameter): List { + val parameterParent = parameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true } + return parameter.typeReference?.typeElement + ?.collectDescendantsOfType { true } + ?.mapNotNull { + val typeParameter = it.reference?.resolve() as? KtTypeParameter ?: return@mapNotNull null + val parent = typeParameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true } + if (parent == parameterParent) typeParameter else null + } ?: emptyList() } - private fun runRemoveTypeParameter(typeParameter: KtTypeParameter) { - if (ReferencesSearch.search(typeParameter).findFirst() != null) return - - val typeParameterList = typeParameter.parent as? KtTypeParameterList ?: return - val typeParameters = typeParameterList.parameters + private fun runRemoveUnusedTypeParameters(typeParameters: List) { + val unusedTypeParams = typeParameters.filter { ReferencesSearch.search(it).findFirst() == null } + if (unusedTypeParams.isEmpty()) return runWriteAction { - if (typeParameters.size == 1) - typeParameterList.delete() - else - EditCommaSeparatedListHelper.removeItem(typeParameter) + unusedTypeParams.forEach { typeParameter -> + val typeParameterList = typeParameter.parent as? KtTypeParameterList ?: return@forEach + if (typeParameterList.parameters.size == 1) + typeParameterList.delete() + else + EditCommaSeparatedListHelper.removeItem(typeParameter) + } } } @@ -96,8 +93,7 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { val parameter = Errors.UNUSED_PARAMETER.cast(diagnostic).psiElement val parameterOwner = parameter.parent.parent - if (parameterOwner is KtFunctionLiteral || - (parameterOwner is KtNamedFunction && parameterOwner.name == null)) return null + if (parameterOwner is KtFunctionLiteral || (parameterOwner is KtNamedFunction && parameterOwner.name == null)) return null return RemoveUnusedFunctionParameterFix(parameter) } } diff --git a/idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt b/idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt new file mode 100644 index 00000000000..9537a260010 --- /dev/null +++ b/idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt @@ -0,0 +1,8 @@ +// "Remove parameter 'x'" "true" +interface TypeHolder + +fun baz(x: TypeHolder) {} + +fun test(holder: TypeHolder) { + baz(holder) +} \ No newline at end of file diff --git a/idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt.after b/idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt.after new file mode 100644 index 00000000000..8aa95e82d81 --- /dev/null +++ b/idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt.after @@ -0,0 +1,8 @@ +// "Remove parameter 'x'" "true" +interface TypeHolder + +fun baz() {} + +fun test(holder: TypeHolder) { + baz() +} \ 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 4d4d758b6d8..910ebf48861 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -1739,6 +1739,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter6.kt"); } + @TestMetadata("removeUnusedParameterWithTypeParameter7.kt") + public void testRemoveUnusedParameterWithTypeParameter7() throws Exception { + runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter7.kt"); + } + @TestMetadata("removeUnusedPrimaryConstructorParameter.kt") public void testRemoveUnusedPrimaryConstructorParameter() throws Exception { runTest("idea/testData/quickfix/changeSignature/removeUnusedPrimaryConstructorParameter.kt");