"Remove parameter" quick fix: Remove unused type parameter used as type projection #KT-23511

This commit is contained in:
Toshiaki Kameyama
2018-05-23 19:27:11 +09:00
committed by asedunov
parent 3e38bbcb07
commit 20535feb31
4 changed files with 44 additions and 27 deletions
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAn
import org.jetbrains.kotlin.idea.intentions.RemoveEmptyPrimaryConstructorIntention import org.jetbrains.kotlin.idea.intentions.RemoveEmptyPrimaryConstructorIntention
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.*
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 import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixAction<KtParameter>(parameter) { class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixAction<KtParameter>(parameter) {
@@ -43,13 +40,11 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA
val parameterList = parameter.parent as? KtParameterList ?: return val parameterList = parameter.parent as? KtParameterList ?: return
val parameterDescriptor = parameter.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return val parameterDescriptor = parameter.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
val parameterSize = parameterList.parameters.size val parameterSize = parameterList.parameters.size
val redundantTypeParameter = redundantTypeParameter(parameter) val typeParameters = typeParameters(parameter)
val primaryConstructor = parameterList.parent as? KtPrimaryConstructor val primaryConstructor = parameterList.parent as? KtPrimaryConstructor
ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, parameter) ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, parameter)
if (redundantTypeParameter != null) { runRemoveUnusedTypeParameters(typeParameters)
runRemoveTypeParameter(redundantTypeParameter)
}
if (parameterSize > 1) { if (parameterSize > 1) {
val nextParameter = parameterList.parameters.getOrNull(parameterDescriptor.index) val nextParameter = parameterList.parameters.getOrNull(parameterDescriptor.index)
@@ -69,26 +64,28 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA
} }
} }
private fun redundantTypeParameter(parameter: KtParameter): KtTypeParameter? { private fun typeParameters(parameter: KtParameter): List<KtTypeParameter> {
val typeParameter = parameter.typeReference?.typeElement?.getChildOfType<KtNameReferenceExpression>()?.reference?.resolve() val parameterParent = parameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true }
as? KtTypeParameter ?: return null return parameter.typeReference?.typeElement
val parameterParent = ?.collectDescendantsOfType<KtNameReferenceExpression> { true }
parameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true } ?.mapNotNull {
val typeParameterParent = val typeParameter = it.reference?.resolve() as? KtTypeParameter ?: return@mapNotNull null
typeParameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true } val parent = typeParameter.getParentOfTypesAndPredicate(false, KtNamedFunction::class.java, KtClass::class.java) { true }
return if (parameterParent == typeParameterParent) typeParameter else null if (parent == parameterParent) typeParameter else null
} ?: emptyList()
} }
private fun runRemoveTypeParameter(typeParameter: KtTypeParameter) { private fun runRemoveUnusedTypeParameters(typeParameters: List<KtTypeParameter>) {
if (ReferencesSearch.search(typeParameter).findFirst() != null) return val unusedTypeParams = typeParameters.filter { ReferencesSearch.search(it).findFirst() == null }
if (unusedTypeParams.isEmpty()) return
val typeParameterList = typeParameter.parent as? KtTypeParameterList ?: return
val typeParameters = typeParameterList.parameters
runWriteAction { runWriteAction {
if (typeParameters.size == 1) unusedTypeParams.forEach { typeParameter ->
typeParameterList.delete() val typeParameterList = typeParameter.parent as? KtTypeParameterList ?: return@forEach
else if (typeParameterList.parameters.size == 1)
EditCommaSeparatedListHelper.removeItem(typeParameter) typeParameterList.delete()
else
EditCommaSeparatedListHelper.removeItem(typeParameter)
}
} }
} }
@@ -96,8 +93,7 @@ class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixA
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
val parameterOwner = parameter.parent.parent val parameterOwner = parameter.parent.parent
if (parameterOwner is KtFunctionLiteral || if (parameterOwner is KtFunctionLiteral || (parameterOwner is KtNamedFunction && parameterOwner.name == null)) return null
(parameterOwner is KtNamedFunction && parameterOwner.name == null)) return null
return RemoveUnusedFunctionParameterFix(parameter) return RemoveUnusedFunctionParameterFix(parameter)
} }
} }
@@ -0,0 +1,8 @@
// "Remove parameter 'x'" "true"
interface TypeHolder<T, U>
fun <T, U> baz(<caret>x: TypeHolder<T, U>) {}
fun test(holder: TypeHolder<String, Int>) {
baz(holder)
}
@@ -0,0 +1,8 @@
// "Remove parameter 'x'" "true"
interface TypeHolder<T, U>
fun baz(<caret>) {}
fun test(holder: TypeHolder<String, Int>) {
baz()
}
@@ -1739,6 +1739,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter6.kt"); 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") @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");