Create from usage: Assume String return type for function whch is called inside of string template

#KT-6083 Fixed
This commit is contained in:
Alexey Sedunov
2015-02-19 14:33:44 +03:00
parent 0ae69e0d3e
commit 41d51e0a13
10 changed files with 93 additions and 10 deletions
@@ -22,13 +22,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.JetScope
import java.util.LinkedHashSet import java.util.LinkedHashSet
import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.psi.JetTypeConstraint
import org.jetbrains.kotlin.psi.JetMultiDeclarationEntry
import org.jetbrains.kotlin.psi.JetParameter
import org.jetbrains.kotlin.psi.JetVariableDeclaration
import org.jetbrains.kotlin.psi.JetNamedDeclaration
import com.intellij.refactoring.psi.SearchUtils import com.intellij.refactoring.psi.SearchUtils
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
import java.util.HashSet import java.util.HashSet
@@ -41,16 +35,14 @@ import org.jetbrains.kotlin.types.JetTypeImpl
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.psi.JetDeclaration
import org.jetbrains.kotlin.psi.JetPropertyDelegate
import org.jetbrains.kotlin.psi.JetProperty
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.idea.util.makeNotNullable import org.jetbrains.kotlin.idea.util.makeNotNullable
import org.jetbrains.kotlin.psi.JetAnnotationEntry
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.callUtil.*
private fun JetType.contains(inner: JetType): Boolean { private fun JetType.contains(inner: JetType): Boolean {
return JetTypeChecker.DEFAULT.equalTypes(this, inner) || getArguments().any { inner in it.getType() } return JetTypeChecker.DEFAULT.equalTypes(this, inner) || getArguments().any { inner in it.getType() }
@@ -183,6 +175,9 @@ fun JetExpression.guessTypes(
val typeArguments = listOf(TypeProjectionImpl(receiverType), TypeProjectionImpl(property.getType())) val typeArguments = listOf(TypeProjectionImpl(receiverType), TypeProjectionImpl(property.getType()))
array(TypeUtils.substituteProjectionsForParameters(delegateClass, typeArguments)) array(TypeUtils.substituteProjectionsForParameters(delegateClass, typeArguments))
} }
parent is JetStringTemplateEntryWithExpression && parent.getExpression() == this -> {
array(KotlinBuiltIns.getInstance().getStringType())
}
else -> array() // can't infer anything else -> array() // can't infer anything
} }
} }
@@ -0,0 +1,9 @@
// "Create function 'foo'" "true"
fun test() {
println("a = ${foo()}")
}
fun foo(): String {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,11 @@
// "Create function 'foo'" "true"
class A {
fun foo(): String {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun test() {
println("a = ${A().foo()}")
}
@@ -0,0 +1,5 @@
// "Create function 'foo'" "true"
fun test() {
println("a = ${<caret>foo()}")
}
@@ -0,0 +1,7 @@
// "Create function 'foo'" "true"
class A
fun test() {
println("a = ${A().<caret>foo()}")
}
@@ -0,0 +1,10 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class A {
val foo: String
}
fun test() {
println("a = ${A().foo}")
}
@@ -0,0 +1,8 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized
fun test() {
println("a = $foo")
}
val foo: String
@@ -0,0 +1,8 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class A
fun test() {
println("a = ${A().<caret>foo}")
}
@@ -0,0 +1,6 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized
fun test() {
println("a = $<caret>foo")
}
@@ -1522,6 +1522,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("beforeCallInStringTemplateRuntime.kt")
public void testCallInStringTemplateRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeCallInStringTemplateRuntime.kt");
doTest(fileName);
}
@TestMetadata("beforeCallWithLambdaArg.kt") @TestMetadata("beforeCallWithLambdaArg.kt")
public void testCallWithLambdaArg() throws Exception { public void testCallWithLambdaArg() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeCallWithLambdaArg.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeCallWithLambdaArg.kt");
@@ -1690,6 +1696,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("beforeQualifiedCallInStringTemplateRuntime.kt")
public void testQualifiedCallInStringTemplateRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeQualifiedCallInStringTemplateRuntime.kt");
doTest(fileName);
}
@TestMetadata("beforeThisInClass.kt") @TestMetadata("beforeThisInClass.kt")
public void testThisInClass() throws Exception { public void testThisInClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeThisInClass.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeThisInClass.kt");
@@ -2549,6 +2561,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("beforeQualifiedRefInStringTemplateRuntime.kt")
public void testQualifiedRefInStringTemplateRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/beforeQualifiedRefInStringTemplateRuntime.kt");
doTest(fileName);
}
@TestMetadata("beforeRefInStringTemplateRuntime.kt")
public void testRefInStringTemplateRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/beforeRefInStringTemplateRuntime.kt");
doTest(fileName);
}
@TestMetadata("beforeThisInClass.kt") @TestMetadata("beforeThisInClass.kt")
public void testThisInClass() throws Exception { public void testThisInClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/beforeThisInClass.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/beforeThisInClass.kt");