Smart completion: item preference by name works for more cases

This commit is contained in:
valentin
2014-09-24 18:58:31 +04:00
parent 0462d152eb
commit b4909cc849
8 changed files with 143 additions and 3 deletions
@@ -61,6 +61,17 @@ import org.jetbrains.jet.lang.psi.JetFunctionLiteralArgument
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression
import org.jetbrains.jet.lang.psi.JetProperty
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import org.jetbrains.jet.lang.psi.JetFunction
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor
import org.jetbrains.jet.lang.psi.JetReturnExpression
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getTargetFunctionDescriptor
import org.jetbrains.jet.plugin.completion.smart.toList
import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
enum class Tail {
COMMA
@@ -74,12 +85,15 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
public fun calculate(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
return calculateForArgument(expressionWithType)
?: calculateForFunctionLiteralArgument(expressionWithType)
?: calculateForEq(expressionWithType)
?: calculateForEqAndAssignment(expressionWithType)
?: calculateForIf(expressionWithType)
?: calculateForElvis(expressionWithType)
?: calculateForBlockExpression(expressionWithType)
?: calculateForWhenEntryValue(expressionWithType)
?: calculateForExclOperand(expressionWithType)
?: calculateForInitializer(expressionWithType)
?: calculateForExpressionBody(expressionWithType)
?: calculateForReturn(expressionWithType)
?: getFromBindingContext(expressionWithType)
}
@@ -172,11 +186,11 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
return expectedInfos
}
private fun calculateForEq(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
private fun calculateForEqAndAssignment(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val binaryExpression = expressionWithType.getParent() as? JetBinaryExpression
if (binaryExpression != null) {
val operationToken = binaryExpression.getOperationToken()
if (operationToken == JetTokens.EQEQ || operationToken == JetTokens.EXCLEQ) {
if (operationToken == JetTokens.EQ || operationToken == JetTokens.EQEQ || operationToken == JetTokens.EXCLEQ) {
val otherOperand = if (expressionWithType == binaryExpression.getRight()) binaryExpression.getLeft() else binaryExpression.getRight()
if (otherOperand != null) {
val expressionType = bindingContext[BindingContext.EXPRESSION_TYPE, otherOperand] ?: return null
@@ -256,6 +270,40 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
return listOf(ExpectedInfo(KotlinBuiltIns.getInstance().getBooleanType(), null, null))
}
private fun calculateForInitializer(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val property = expressionWithType.getParent() as? JetProperty ?: return null
if (expressionWithType != property.getInitializer()) return null
val propertyDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptor ?: return null
return listOf(ExpectedInfo(propertyDescriptor.getType(), propertyDescriptor.getName().asString(), null))
}
private fun calculateForExpressionBody(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val declaration = expressionWithType.getParent() as? JetDeclarationWithBody ?: return null
if (expressionWithType != declaration.getBodyExpression() || declaration.hasBlockBody()) return null
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] as? FunctionDescriptor ?: return null
return functionReturnValueExpectedInfo(descriptor).toList()
}
private fun calculateForReturn(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val returnExpression = expressionWithType.getParent() as? JetReturnExpression ?: return null
val descriptor = returnExpression.getTargetFunctionDescriptor(bindingContext) ?: return null
return functionReturnValueExpectedInfo(descriptor).toList()
}
private fun functionReturnValueExpectedInfo(descriptor: FunctionDescriptor): ExpectedInfo? {
return when (descriptor) {
is SimpleFunctionDescriptor -> ExpectedInfo(descriptor.getReturnType() ?: return null, descriptor.getName().asString(), null)
is PropertyGetterDescriptor -> {
if (descriptor !is PropertyGetterDescriptor) return null
val property = descriptor.getCorrespondingProperty()
ExpectedInfo(property.getType(), property.getName().asString(), null)
}
else -> null
}
}
private fun getFromBindingContext(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType] ?: return null
return listOf(ExpectedInfo(expectedType, null, null))
@@ -0,0 +1,11 @@
var fooBar = ""
class C {
var bar = ""
fun foo(s: String) {
bar = <caret>
}
}
// ORDER: fooBar, s
@@ -0,0 +1,5 @@
val fooBar = ""
fun foo(s: String): String = <caret>
// ORDER: foo, fooBar, s
@@ -0,0 +1,11 @@
class C(val x: X) {
val foo: String
get() = x.<caret>
}
class X {
val s = ""
fun getFoo() = ""
}
// ORDER: getFoo, s, toString
@@ -0,0 +1,13 @@
class C(val x: X) {
val foo: String
get() {
return x.<caret>
}
}
class X {
val s = ""
fun getFoo() = ""
}
// ORDER: getFoo, s, toString
@@ -0,0 +1,9 @@
var fooBar = ""
class C {
fun foo(s: String) {
val bar: String = <caret>
}
}
// ORDER: fooBar, s
@@ -0,0 +1,7 @@
val fooBar = ""
fun foo(s: String): String {
return <caret>
}
// ORDER: foo, fooBar, s
@@ -62,6 +62,12 @@ public class SmartCompletionWeigherTestGenerated extends AbstractSmartCompletion
doTest(fileName);
}
@TestMetadata("NameSimilarityForAssignment.kt")
public void testNameSimilarityForAssignment() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForAssignment.kt");
doTest(fileName);
}
@TestMetadata("NameSimilarityForBlock.kt")
public void testNameSimilarityForBlock() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForBlock.kt");
@@ -104,6 +110,36 @@ public class SmartCompletionWeigherTestGenerated extends AbstractSmartCompletion
doTest(fileName);
}
@TestMetadata("NameSimilarityForExpressionBody.kt")
public void testNameSimilarityForExpressionBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForExpressionBody.kt");
doTest(fileName);
}
@TestMetadata("NameSimilarityForGetterExpressionBody.kt")
public void testNameSimilarityForGetterExpressionBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForGetterExpressionBody.kt");
doTest(fileName);
}
@TestMetadata("NameSimilarityForGetterReturn.kt")
public void testNameSimilarityForGetterReturn() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForGetterReturn.kt");
doTest(fileName);
}
@TestMetadata("NameSimilarityForInitializer.kt")
public void testNameSimilarityForInitializer() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForInitializer.kt");
doTest(fileName);
}
@TestMetadata("NameSimilarityForReturn.kt")
public void testNameSimilarityForReturn() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForReturn.kt");
doTest(fileName);
}
@TestMetadata("NameSimilarityForThen.kt")
public void testNameSimilarityForThen() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/smart/NameSimilarityForThen.kt");