RemoveExplicitTypeIntention: fix false positive for type aliases

#KT-33902 Fixed
This commit is contained in:
Dmitry Gridin
2019-10-25 15:35:31 +07:00
parent 6ea82a0c7d
commit 587b0de2b8
6 changed files with 51 additions and 12 deletions
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.refactoring.addTypeArgumentsIfNeeded
import org.jetbrains.kotlin.idea.refactoring.getQualifiedTypeArgumentList
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -68,7 +69,7 @@ class RemoveExplicitTypeIntention : SelfTargetingRangeIntention<KtCallableDeclar
val initializer = (element as? KtDeclarationWithInitializer)?.initializer
if (!redundantTypeSpecification(element, initializer)) return null
if (!redundantTypeSpecification(element.typeReference, initializer)) return null
return when {
initializer != null -> TextRange(element.startOffset, initializer.startOffset - 1)
@@ -78,18 +79,27 @@ class RemoveExplicitTypeIntention : SelfTargetingRangeIntention<KtCallableDeclar
}
}
fun redundantTypeSpecification(element: KtCallableDeclaration, initializer: KtExpression?): Boolean {
if (initializer == null) return true
tailrec fun redundantTypeSpecification(typeReference: KtTypeReference?, initializer: KtExpression?): Boolean {
if (initializer == null || typeReference == null) return true
if (initializer !is KtLambdaExpression && initializer !is KtNamedFunction) return true
val functionType = element.typeReference?.typeElement as? KtFunctionType ?: return true
if (functionType.receiver != null) return false
if (functionType.parameters.isEmpty()) return true
val valueParameters = when (initializer) {
is KtLambdaExpression -> initializer.valueParameters
is KtNamedFunction -> initializer.valueParameters
else -> emptyList()
val typeElement = typeReference.typeElement ?: return true
return when (typeElement) {
is KtFunctionType -> {
if (typeElement.receiver != null) return false
if (typeElement.parameters.isEmpty()) return true
val valueParameters = when (initializer) {
is KtLambdaExpression -> initializer.valueParameters
is KtNamedFunction -> initializer.valueParameters
else -> emptyList()
}
valueParameters.isNotEmpty() && valueParameters.none { it.typeReference == null }
}
is KtUserType -> {
val typeAlias = typeElement.referenceExpression?.mainReference?.resolve() as? KtTypeAlias ?: return true
return redundantTypeSpecification(typeAlias.getTypeReference(), initializer)
}
else -> true
}
return valueParameters.isNotEmpty() && valueParameters.none { it.typeReference == null }
}
}
}
@@ -68,7 +68,7 @@ open class RemovePsiElementSimpleFix(element: PsiElement, private val text: Stri
object RemoveVariableFactory : KotlinSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<PsiElement>? {
val expression = diagnostic.psiElement.getNonStrictParentOfType<KtProperty>() ?: return null
if (!RemoveExplicitTypeIntention.redundantTypeSpecification(expression, expression.initializer)) return null
if (!RemoveExplicitTypeIntention.redundantTypeSpecification(expression.typeReference, expression.initializer)) return null
return object : RemovePsiElementSimpleFix(expression, "Remove variable '${expression.name}'") {
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val initializer = expression.initializer
@@ -0,0 +1,9 @@
// IS_APPLICABLE: false
typealias ValidationRule2 = (String, String) -> String
typealias ValidationRule3 = ValidationRule2
typealias ValidationRule4 = ValidationRule3
fun getValidator(): ValidationRule4<caret> = { text, eventType ->
"abc"
}
@@ -0,0 +1,5 @@
typealias ValidationRule2 = String
typealias ValidationRule3 = ValidationRule2
typealias ValidationRule4 = ValidationRule3
fun getValidator(): ValidationRule4<caret> = "abc"
@@ -0,0 +1,5 @@
typealias ValidationRule2 = String
typealias ValidationRule3 = ValidationRule2
typealias ValidationRule4 = ValidationRule3
fun getValidator() = "abc"
@@ -13367,6 +13367,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/removeExplicitType/lambdaInitializer5.kt");
}
@TestMetadata("lambdaInitializerWithAlias.kt")
public void testLambdaInitializerWithAlias() throws Exception {
runTest("idea/testData/intentions/removeExplicitType/lambdaInitializerWithAlias.kt");
}
@TestMetadata("lambdaInitializerWithAlias2.kt")
public void testLambdaInitializerWithAlias2() throws Exception {
runTest("idea/testData/intentions/removeExplicitType/lambdaInitializerWithAlias2.kt");
}
@TestMetadata("needTypeArgument.kt")
public void testNeedTypeArgument() throws Exception {
runTest("idea/testData/intentions/removeExplicitType/needTypeArgument.kt");