Change to star projection: do not suggest when type paramer is generic type

#KT-30794 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-07-21 21:37:18 +09:00
committed by Dmitry Gridin
parent 10e42a55c9
commit 3742993dea
13 changed files with 99 additions and 1 deletions
@@ -20,13 +20,16 @@ import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypes
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
class ChangeToStarProjectionFix(element: KtTypeElement) : KotlinQuickFixAction<KtTypeElement>(element) {
@@ -48,7 +51,17 @@ class ChangeToStarProjectionFix(element: KtTypeElement) : KotlinQuickFixAction<K
if (typeElement is KtFunctionType) return null
if (binaryExpr?.operationReference?.isAsKeyword() == true) {
val parent = binaryExpr.getParentOfTypes(true, KtValueArgument::class.java, KtQualifiedExpression::class.java)
val parent = binaryExpr.getParentOfTypes(
true,
KtValueArgument::class.java,
KtQualifiedExpression::class.java,
KtCallableDeclaration::class.java
)
if (parent is KtCallableDeclaration
&& parent.typeReference.typeArguments().any { it.projectionKind != KtProjectionKind.STAR }
&& typeReference.typeArguments().isNotEmpty()
&& binaryExpr.isUsedAsExpression(binaryExpr.analyze(BodyResolveMode.PARTIAL_WITH_CFA))
) return null
val type = when (parent) {
is KtValueArgument -> {
val callExpr = parent.getStrictParentOfType<KtCallExpression>()
@@ -75,5 +88,9 @@ class ChangeToStarProjectionFix(element: KtTypeElement) : KotlinQuickFixAction<K
val elementType = getReferencedNameElementType()
return elementType == KtTokens.AS_KEYWORD || elementType == KtTokens.AS_SAFE
}
private fun KtTypeReference?.typeArguments(): List<KtTypeProjection> {
return (this?.typeElement as? KtUserType)?.typeArguments.orEmpty()
}
}
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "false"
// ACTION: Convert to block body
// ACTION: Introduce local variable
fun <T> test(list: List<*>): List<T> = list as List<T><caret>
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "false"
fun <T> test(list: List<*>): List<T> {
return list as List<T><caret>
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "true"
fun <T> test(list: List<*>): List<*> {
return list as List<T><caret>
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "true"
fun <T> test(list: List<*>): List<*> {
return list as List<*><caret>
}
@@ -0,0 +1,5 @@
// "Change type arguments to <*>" "true"
fun <T> test(list: List<*>): List<T> {
list as List<T><caret>
return list as List<T>
}
@@ -0,0 +1,5 @@
// "Change type arguments to <*>" "true"
fun <T> test(list: List<*>): List<T> {
list as List<*><caret>
return list as List<T>
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "false"
fun <T> test(list: List<*>) {
val a: List<T> = list as List<T><caret>
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "true"
fun <T> test6(list: List<*>) {
val a: List<*> = list as List<T><caret>
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "true"
fun <T> test6(list: List<*>) {
val a: List<*> = list as List<*><caret>
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "true"
fun <T> test7(list: List<*>) {
val a = list as List<T><caret>
}
@@ -0,0 +1,4 @@
// "Change type arguments to <*>" "true"
fun <T> test7(list: List<*>) {
val a = list as List<*><caret>
}
@@ -1186,6 +1186,41 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/addStarProjections/cast/extensionReceiver5.kt");
}
@TestMetadata("genericTypeParameter.kt")
public void testGenericTypeParameter() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/genericTypeParameter.kt");
}
@TestMetadata("genericTypeParameter2.kt")
public void testGenericTypeParameter2() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/genericTypeParameter2.kt");
}
@TestMetadata("genericTypeParameter3.kt")
public void testGenericTypeParameter3() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/genericTypeParameter3.kt");
}
@TestMetadata("genericTypeParameter4.kt")
public void testGenericTypeParameter4() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/genericTypeParameter4.kt");
}
@TestMetadata("genericTypeParameter5.kt")
public void testGenericTypeParameter5() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/genericTypeParameter5.kt");
}
@TestMetadata("genericTypeParameter6.kt")
public void testGenericTypeParameter6() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/genericTypeParameter6.kt");
}
@TestMetadata("genericTypeParameter7.kt")
public void testGenericTypeParameter7() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/genericTypeParameter7.kt");
}
@TestMetadata("uncheckedCastOnTypeParameter.kt")
public void testUncheckedCastOnTypeParameter() throws Exception {
runTest("idea/testData/quickfix/addStarProjections/cast/uncheckedCastOnTypeParameter.kt");