diff --git a/idea/src/org/jetbrains/jet/plugin/completion/ExpectedInfos.kt b/idea/src/org/jetbrains/jet/plugin/completion/ExpectedInfos.kt index af0679326eb..e4fd85bc3fd 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/ExpectedInfos.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/ExpectedInfos.kt @@ -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? { 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? { + private fun calculateForEqAndAssignment(expressionWithType: JetExpression): Collection? { 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? { + 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? { + 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? { + 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? { val expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType] ?: return null return listOf(ExpectedInfo(expectedType, null, null)) diff --git a/idea/testData/completion/weighers/smart/NameSimilarityForAssignment.kt b/idea/testData/completion/weighers/smart/NameSimilarityForAssignment.kt new file mode 100644 index 00000000000..cf6058786dd --- /dev/null +++ b/idea/testData/completion/weighers/smart/NameSimilarityForAssignment.kt @@ -0,0 +1,11 @@ +var fooBar = "" + +class C { + var bar = "" + + fun foo(s: String) { + bar = + } +} + +// ORDER: fooBar, s diff --git a/idea/testData/completion/weighers/smart/NameSimilarityForExpressionBody.kt b/idea/testData/completion/weighers/smart/NameSimilarityForExpressionBody.kt new file mode 100644 index 00000000000..2ef60e4697b --- /dev/null +++ b/idea/testData/completion/weighers/smart/NameSimilarityForExpressionBody.kt @@ -0,0 +1,5 @@ +val fooBar = "" + +fun foo(s: String): String = + +// ORDER: foo, fooBar, s diff --git a/idea/testData/completion/weighers/smart/NameSimilarityForGetterExpressionBody.kt b/idea/testData/completion/weighers/smart/NameSimilarityForGetterExpressionBody.kt new file mode 100644 index 00000000000..acf0a537440 --- /dev/null +++ b/idea/testData/completion/weighers/smart/NameSimilarityForGetterExpressionBody.kt @@ -0,0 +1,11 @@ +class C(val x: X) { + val foo: String + get() = x. +} + +class X { + val s = "" + fun getFoo() = "" +} + +// ORDER: getFoo, s, toString diff --git a/idea/testData/completion/weighers/smart/NameSimilarityForGetterReturn.kt b/idea/testData/completion/weighers/smart/NameSimilarityForGetterReturn.kt new file mode 100644 index 00000000000..4ae4af8c8d0 --- /dev/null +++ b/idea/testData/completion/weighers/smart/NameSimilarityForGetterReturn.kt @@ -0,0 +1,13 @@ +class C(val x: X) { + val foo: String + get() { + return x. + } +} + +class X { + val s = "" + fun getFoo() = "" +} + +// ORDER: getFoo, s, toString diff --git a/idea/testData/completion/weighers/smart/NameSimilarityForInitializer.kt b/idea/testData/completion/weighers/smart/NameSimilarityForInitializer.kt new file mode 100644 index 00000000000..894ddf1e0f2 --- /dev/null +++ b/idea/testData/completion/weighers/smart/NameSimilarityForInitializer.kt @@ -0,0 +1,9 @@ +var fooBar = "" + +class C { + fun foo(s: String) { + val bar: String = + } +} + +// ORDER: fooBar, s diff --git a/idea/testData/completion/weighers/smart/NameSimilarityForReturn.kt b/idea/testData/completion/weighers/smart/NameSimilarityForReturn.kt new file mode 100644 index 00000000000..4714826dde5 --- /dev/null +++ b/idea/testData/completion/weighers/smart/NameSimilarityForReturn.kt @@ -0,0 +1,7 @@ +val fooBar = "" + +fun foo(s: String): String { + return +} + +// ORDER: foo, fooBar, s diff --git a/idea/tests/org/jetbrains/jet/completion/weighers/SmartCompletionWeigherTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/weighers/SmartCompletionWeigherTestGenerated.java index 3356b04c4c5..43d5e9e822e 100644 --- a/idea/tests/org/jetbrains/jet/completion/weighers/SmartCompletionWeigherTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/weighers/SmartCompletionWeigherTestGenerated.java @@ -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");