diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt index 99234ffd610..fb58239b6ed 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt @@ -34,10 +34,15 @@ import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings import org.jetbrains.kotlin.idea.core.refactoring.EmptyValidator import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester +import org.jetbrains.kotlin.idea.imports.importableFqName +import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf +import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered @@ -141,37 +146,48 @@ class ParameterNameAndTypeCompletion( private abstract class NameAndType(val parameterName: String) { abstract fun createTypeLookupElement(lookupElementFactory: LookupElementFactory): LookupElement? + abstract val typeIdString: String // types with equal id-string are considered as equal (used to avoid duplicated items) } - private class NameAndDescriptorType(parameterName: String, private val type: ClassifierDescriptor) : NameAndType(parameterName) { + private class NameAndDescriptorType(parameterName: String, private val classifier: ClassifierDescriptor) : NameAndType(parameterName) { override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory) - = lookupElementFactory.createLookupElement(type, false) + = lookupElementFactory.createLookupElement(classifier, false) + + override val typeIdString: String + get() = DescriptorUtils.getFqName(classifier).render() } - private class NameAndJavaType(parameterName: String, private val type: PsiClass) : NameAndType(parameterName) { + private class NameAndJavaType(parameterName: String, private val psiClass: PsiClass) : NameAndType(parameterName) { override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory) - = lookupElementFactory.createLookupElementForJavaClass(type) + = lookupElementFactory.createLookupElementForJavaClass(psiClass) + + override val typeIdString: String + get() = psiClass.getQualifiedName()!! } private class NameAndArbitraryType(parameterName: String, private val type: JetType) : NameAndType(parameterName) { override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory) = lookupElementFactory.createLookupElementForType(type) + + override val typeIdString: String + get() = IdeDescriptorRenderers.SOURCE_CODE.renderType(type) } private class MyLookupElement private constructor( private val parameterName: String, + private val typeIdString: String, typeLookupElement: LookupElement ) : LookupElementDecorator(typeLookupElement) { companion object { fun create(nameAndType: NameAndType, factory: LookupElementFactory): LookupElement? { val lookupElement = nameAndType.createTypeLookupElement(factory) ?: return null - return MyLookupElement(nameAndType.parameterName, lookupElement).suppressAutoInsertion() + return MyLookupElement(nameAndType.parameterName, nameAndType.typeIdString, lookupElement).suppressAutoInsertion() } } override fun equals(other: Any?) - = other is MyLookupElement && parameterName == other.parameterName && getDelegate() == other.getDelegate() + = other is MyLookupElement && parameterName == other.parameterName && typeIdString == other.typeIdString override fun hashCode() = parameterName.hashCode() override fun getLookupString() = parameterName diff --git a/idea/idea-completion/testData/basic/common/parameterNameAndType/NoFromFileAndFromClassesDuplication.kt b/idea/idea-completion/testData/basic/common/parameterNameAndType/NoFromFileAndFromClassesDuplication.kt new file mode 100644 index 00000000000..bb94818861d --- /dev/null +++ b/idea/idea-completion/testData/basic/common/parameterNameAndType/NoFromFileAndFromClassesDuplication.kt @@ -0,0 +1,17 @@ +package ppp + +import java.io.* + +class MyPrintStream + +fun f1(printStream: PrintStream){} +fun f2(printStream: PrintStream?){} +fun f3(printStream: MyPrintStream){} + +fun f(printStr) + +// EXIST_JAVA_ONLY: { lookupString: "printStream", itemText: "printStream: PrintStream", tailText: " (java.io)" } +// EXIST_JAVA_ONLY: { lookupString: "printStream", itemText: "printStream: PrintStream?", tailText: " (java.io)" } +// EXIST: { lookupString: "printStream", itemText: "printStream: MyPrintStream", tailText: " (ppp)" } +// EXIST: { lookupString: "myPrintStream", itemText: "myPrintStream: MyPrintStream", tailText: " (ppp)" } +// NOTHING_ELSE diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 21b2f750e17..ed9e7571c6a 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -1428,6 +1428,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("NoFromFileAndFromClassesDuplication.kt") + public void testNoFromFileAndFromClassesDuplication() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NoFromFileAndFromClassesDuplication.kt"); + doTest(fileName); + } + @TestMetadata("NotForCatchParameter.kt") public void testNotForCatchParameter() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NotForCatchParameter.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index d18cf0a6757..af75c7ff4d0 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -1428,6 +1428,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("NoFromFileAndFromClassesDuplication.kt") + public void testNoFromFileAndFromClassesDuplication() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NoFromFileAndFromClassesDuplication.kt"); + doTest(fileName); + } + @TestMetadata("NotForCatchParameter.kt") public void testNotForCatchParameter() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NotForCatchParameter.kt");