Create From Usage: Add support of star projections/incorrect type arguments

#EA-62661 Fixed
This commit is contained in:
Alexey Sedunov
2015-03-10 14:22:59 +03:00
parent ab5a691612
commit f0b0fd07c5
11 changed files with 67 additions and 10 deletions
@@ -231,3 +231,7 @@ private fun JetType.substitute(substitution: JetTypeSubstitution, variance: Vari
} }
fun JetExpression.getExpressionForTypeGuess() = getAssignmentByLHS()?.getRight() ?: this fun JetExpression.getExpressionForTypeGuess() = getAssignmentByLHS()?.getRight() ?: this
fun JetCallElement.getTypeInfoForTypeArguments(): List<TypeInfo> {
return getTypeArguments().map { it.getTypeReference()?.let { TypeInfo(it, Variance.INVARIANT) } }.filterNotNull()
}
@@ -96,7 +96,7 @@ object CreateFunctionOrPropertyFromCallActionFactory : JetIntentionActionsFactor
it.getArgumentName()?.getReferenceExpression()?.getReferencedName() it.getArgumentName()?.getReferenceExpression()?.getReferencedName()
) )
} }
val typeParameters = callExpr.getTypeArguments().map { TypeInfo(it.getTypeReference(), Variance.INVARIANT) } val typeParameters = callExpr.getTypeInfoForTypeArguments()
val returnType = TypeInfo(fullCallExpr, Variance.OUT_VARIANCE) val returnType = TypeInfo(fullCallExpr, Variance.OUT_VARIANCE)
FunctionInfo(calleeExpr.getReferencedName(), receiverType, returnType, possibleContainers, parameters, typeParameters) FunctionInfo(calleeExpr.getReferencedName(), receiverType, returnType, possibleContainers, parameters, typeParameters)
} }
@@ -24,15 +24,14 @@ import org.jetbrains.kotlin.psi.JetCallExpression
import org.jetbrains.kotlin.psi.JetSimpleNameExpression import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.psi.JetQualifiedExpression import org.jetbrains.kotlin.psi.JetQualifiedExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.JetAnnotationEntry import org.jetbrains.kotlin.psi.JetAnnotationEntry
import java.util.Collections import java.util.Collections
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
public object CreateClassFromConstructorCallActionFactory: JetSingleIntentionActionFactory() { public object CreateClassFromConstructorCallActionFactory: JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? { override fun createAction(diagnostic: Diagnostic): IntentionAction? {
@@ -76,12 +75,7 @@ public object CreateClassFromConstructorCallActionFactory: JetSingleIntentionAct
val (expectedTypeInfo, filter) = fullCallExpr.getInheritableTypeInfo(context, moduleDescriptor, targetParent) val (expectedTypeInfo, filter) = fullCallExpr.getInheritableTypeInfo(context, moduleDescriptor, targetParent)
if (!filter(classKind)) return null if (!filter(classKind)) return null
val typeArgumentInfos = if (inAnnotationEntry) { val typeArgumentInfos = if (inAnnotationEntry) Collections.emptyList() else callExpr.getTypeInfoForTypeArguments()
Collections.emptyList()
}
else {
callExpr.getTypeArguments().map { TypeInfo(it.getTypeReference(), Variance.INVARIANT) }
}
val classInfo = ClassInfo( val classInfo = ClassInfo(
kind = classKind, kind = classKind,
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.JetDelegatorToSuperClass
import org.jetbrains.kotlin.psi.JetConstructorCalleeExpression import org.jetbrains.kotlin.psi.JetConstructorCalleeExpression
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.builtins.*
public object CreateClassFromTypeReferenceActionFactory: JetIntentionActionsFactory() { public object CreateClassFromTypeReferenceActionFactory: JetIntentionActionsFactory() {
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> { override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
@@ -68,6 +69,8 @@ public object CreateClassFromTypeReferenceActionFactory: JetIntentionActionsFact
} }
} }
val anyType = KotlinBuiltIns.getInstance().getAnyType()
val createPackageAction = refExpr.getCreatePackageFixIfApplicable(targetParent) val createPackageAction = refExpr.getCreatePackageFixIfApplicable(targetParent)
val createClassActions = possibleKinds.map { val createClassActions = possibleKinds.map {
val classInfo = ClassInfo( val classInfo = ClassInfo(
@@ -75,7 +78,9 @@ public object CreateClassFromTypeReferenceActionFactory: JetIntentionActionsFact
name = name, name = name,
targetParent = targetParent, targetParent = targetParent,
expectedTypeInfo = TypeInfo.Empty, expectedTypeInfo = TypeInfo.Empty,
typeArguments = typeArguments.map { TypeInfo(it, Variance.INVARIANT) } typeArguments = typeArguments.map {
if (it != null) TypeInfo(it, Variance.INVARIANT) else TypeInfo(anyType, Variance.INVARIANT)
}
) )
CreateClassFromUsageFix(userType, classInfo) CreateClassFromUsageFix(userType, classInfo)
} }
@@ -0,0 +1,7 @@
// "Create class 'Foo'" "true"
fun test() = Foo<String>(2, "2")
class Foo<T>(i: Int, t: T) {
}
@@ -0,0 +1,3 @@
// "Create class 'Foo'" "true"
fun test() = <caret>Foo<String, *>(2, "2")
@@ -0,0 +1,8 @@
// "Create class 'A'" "true"
package p
fun foo(): A<*, String> = throw Throwable("")
class A<T, U> {
}
@@ -0,0 +1,4 @@
// "Create class 'A'" "true"
package p
fun foo(): <caret>A<*, String> = throw Throwable("")
@@ -0,0 +1,9 @@
// "Create function 'foo'" "true"
fun test(): Int {
return foo<String>(2, "2")
}
fun <T> foo(i: Int, t: T): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,5 @@
// "Create function 'foo'" "true"
fun test(): Int {
return <caret>foo<String, *>(2, "2")
}
@@ -958,6 +958,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createClass/callExpression/typeArguments"), Pattern.compile("^before(\\w+)\\.kt$"), true); JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createClass/callExpression/typeArguments"), Pattern.compile("^before(\\w+)\\.kt$"), true);
} }
@TestMetadata("beforeCallWithStarProjection.kt")
public void testCallWithStarProjection() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createClass/callExpression/typeArguments/beforeCallWithStarProjection.kt");
doTest(fileName);
}
@TestMetadata("beforeClassMember.kt") @TestMetadata("beforeClassMember.kt")
public void testClassMember() throws Exception { public void testClassMember() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createClass/callExpression/typeArguments/beforeClassMember.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createClass/callExpression/typeArguments/beforeClassMember.kt");
@@ -1385,6 +1391,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("beforeClassNotQualifierWithStarProjection.kt")
public void testClassNotQualifierWithStarProjection() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createClass/typeReference/beforeClassNotQualifierWithStarProjection.kt");
doTest(fileName);
}
@TestMetadata("beforeClassNotQualifierWithTypeArgs.kt") @TestMetadata("beforeClassNotQualifierWithTypeArgs.kt")
public void testClassNotQualifierWithTypeArgs() throws Exception { public void testClassNotQualifierWithTypeArgs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createClass/typeReference/beforeClassNotQualifierWithTypeArgs.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createClass/typeReference/beforeClassNotQualifierWithTypeArgs.kt");
@@ -1844,6 +1856,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments"), Pattern.compile("^before(\\w+)\\.kt$"), true); JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments"), Pattern.compile("^before(\\w+)\\.kt$"), true);
} }
@TestMetadata("beforeCallWithStarProjection.kt")
public void testCallWithStarProjection() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeCallWithStarProjection.kt");
doTest(fileName);
}
@TestMetadata("beforeClassMember.kt") @TestMetadata("beforeClassMember.kt")
public void testClassMember() throws Exception { public void testClassMember() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeClassMember.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeClassMember.kt");