RemoveExplicitTypeIntention: fix false positive for type aliases
#KT-33902 Fixed
This commit is contained in:
@@ -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"
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user