diff --git a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt index 6d80e65e942..cef221a33ab 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt @@ -70,13 +70,12 @@ fun buildSmartCompletionData(expression: JetSimpleNameExpression, resolveSession if (receiver == null) { for (expectedType in expectedTypes) { - //TODO: there can be duplicates here for multiple expected types - typeInstantiationItems(expectedType, resolveSession, bindingContext).toCollection(additionalElements) - //TODO: there can be duplicates here for multiple expected types staticMembers(expressionWithType, expectedType, resolveSession, bindingContext).toCollection(additionalElements) } + additionalElements.addTypeInstantiationItems(expectedTypes, resolveSession, bindingContext) + thisItems(expressionWithType, expectedTypes, bindingContext).toCollection(additionalElements) } @@ -204,18 +203,24 @@ private fun calcItemsToSkip(expression: JetExpression, resolveSession: ResolveSe return listOf() } -private fun typeInstantiationItems(expectedType: ExpectedTypeInfo, resolveSession: ResolveSessionForBodies, bindingContext: BindingContext): Iterable { - val typeConstructor: TypeConstructor = expectedType.`type`.getConstructor() - val classifier: ClassifierDescriptor? = typeConstructor.getDeclarationDescriptor() - if (!(classifier is ClassDescriptor)) return listOf() +private fun MutableCollection.addTypeInstantiationItems(expectedTypes: Collection, resolveSession: ResolveSessionForBodies, bindingContext: BindingContext) { + val expectedTypesGrouped: Map> = expectedTypes.groupBy { TypeUtils.makeNotNullable(it.`type`) } + for ((jetType, types) in expectedTypesGrouped) { + val tail = mergeTails(types.map { it.tail }) + addTypeInstantiationItems(jetType, tail, resolveSession, bindingContext) + } +} +private fun MutableCollection.addTypeInstantiationItems(jetType: JetType, tail: Tail?, resolveSession: ResolveSessionForBodies, bindingContext: BindingContext) { + val classifier = jetType.getConstructor().getDeclarationDescriptor() + if (!(classifier is ClassDescriptor)) return //TODO: check for constructor's visibility val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, classifier) var lookupString = lookupElement.getLookupString() - val typeArgs = expectedType.`type`.getArguments() + val typeArgs = jetType.getArguments() var itemText = lookupString + DescriptorRenderer.TEXT.renderTypeArguments(typeArgs) val insertHandler: InsertHandler @@ -286,13 +291,13 @@ private fun typeInstantiationItems(expectedType: ExpectedTypeInfo, resolveSessio } } - val lookupElementWithTail = decorateLookupElement(lookupElementDecorated, expectedType.tail) + val lookupElementWithTail = decorateLookupElement(lookupElementDecorated, tail) if (suppressAutoInsertion) { - return listOf(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(lookupElementWithTail)) + add(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(lookupElementWithTail)) } else{ - return listOf(lookupElementWithTail) + add(lookupElementWithTail) } } diff --git a/idea/testData/completion/handlers/smart/MergeTail1.kt b/idea/testData/completion/handlers/smart/MergeTail1.kt new file mode 100644 index 00000000000..d12af75fec9 --- /dev/null +++ b/idea/testData/completion/handlers/smart/MergeTail1.kt @@ -0,0 +1,8 @@ +class C{} + +fun foo(c: C){} +fun foo(c: C, i: Int){} + +fun foo() { + foo( +} diff --git a/idea/testData/completion/handlers/smart/MergeTail1.kt.after b/idea/testData/completion/handlers/smart/MergeTail1.kt.after new file mode 100644 index 00000000000..47cb79ab943 --- /dev/null +++ b/idea/testData/completion/handlers/smart/MergeTail1.kt.after @@ -0,0 +1,8 @@ +class C{} + +fun foo(c: C){} +fun foo(c: C, i: Int){} + +fun foo() { + foo(C() +} diff --git a/idea/testData/completion/handlers/smart/MergeTail2.kt b/idea/testData/completion/handlers/smart/MergeTail2.kt new file mode 100644 index 00000000000..80f3c048360 --- /dev/null +++ b/idea/testData/completion/handlers/smart/MergeTail2.kt @@ -0,0 +1,8 @@ +class C{} + +fun foo(c: C){} +fun foo(c: C?, i: Int){} + +fun foo() { + foo( +} diff --git a/idea/testData/completion/handlers/smart/MergeTail2.kt.after b/idea/testData/completion/handlers/smart/MergeTail2.kt.after new file mode 100644 index 00000000000..78d52e476ec --- /dev/null +++ b/idea/testData/completion/handlers/smart/MergeTail2.kt.after @@ -0,0 +1,8 @@ +class C{} + +fun foo(c: C){} +fun foo(c: C?, i: Int){} + +fun foo() { + foo(C() +} diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java index f2397236fe0..7b640ed2482 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java @@ -16,11 +16,17 @@ package org.jetbrains.jet.completion.handlers; -import org.jetbrains.jet.JetTestUtils; -import org.jetbrains.jet.test.TestMetadata; +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestSuite; import java.io.File; import java.util.regex.Pattern; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; + +import org.jetbrains.jet.completion.handlers.AbstractSmartCompletionHandlerTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @@ -180,6 +186,16 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion doTest("idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt"); } + @TestMetadata("MergeTail1.kt") + public void testMergeTail1() throws Exception { + doTest("idea/testData/completion/handlers/smart/MergeTail1.kt"); + } + + @TestMetadata("MergeTail2.kt") + public void testMergeTail2() throws Exception { + doTest("idea/testData/completion/handlers/smart/MergeTail2.kt"); + } + @TestMetadata("TabReplaceComma1.kt") public void testTabReplaceComma1() throws Exception { doTest("idea/testData/completion/handlers/smart/TabReplaceComma1.kt");