diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt index ac4408ed60c..2dfea3f2124 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt @@ -34,6 +34,11 @@ import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler import org.jetbrains.jet.renderer.DescriptorRenderer import org.jetbrains.jet.plugin.completion.handlers.BaseDeclarationInsertHandler import org.jetbrains.jet.plugin.completion.handlers.JetPropertyInsertHandler +import com.intellij.psi.PsiClass +import org.jetbrains.jet.asJava.KotlinLightClass +import org.jetbrains.jet.lang.resolve.java.JavaResolverPsiUtils +import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler +import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement public object DescriptorLookupConverter { public fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor): LookupElement { @@ -44,7 +49,21 @@ public object DescriptorLookupConverter { return createLookupElement(analyzer, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor)) } + public fun createLookupElementForJavaClass(psiClass: PsiClass): LookupElement { + return JavaPsiClassReferenceElement(psiClass).setInsertHandler(JetJavaClassInsertHandler) + } + private fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor, declaration: PsiElement?): LookupElement { + if (descriptor is ClassifierDescriptor && + declaration is PsiClass && + declaration !is KotlinLightClass && + !JavaResolverPsiUtils.isCompiledKotlinClass(declaration)) { + // for java classes we create special lookup elements + // because they must be equal to ones created in TypesCompletion + // otherwise we may have duplicates + return createLookupElementForJavaClass(declaration) + } + val name = descriptor.getName().asString() var element = LookupElementBuilder.create(DeclarationLookupObject(descriptor, analyzer, declaration), name) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt index 4f801940a34..bc74ae8ed2f 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt @@ -21,13 +21,13 @@ import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.codeInsight.lookup.LookupElementPresentation import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns import org.jetbrains.jet.plugin.completion.handlers.* import org.jetbrains.jet.plugin.project.ResolveSessionForBodies import com.intellij.codeInsight.completion.PrefixMatcher import java.util.ArrayList import com.intellij.codeInsight.completion.CompletionResultSet +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor class LookupElementsCollector(private val prefixMatcher: PrefixMatcher, private val resolveSession: ResolveSessionForBodies, @@ -57,12 +57,13 @@ class LookupElementsCollector(private val prefixMatcher: PrefixMatcher, if (!descriptorFilter(descriptor)) return run { - var lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, descriptor) - if (suppressAutoInsertion && - elements.isEmpty() && isResultEmpty /* without these checks we would get duplicated items */) { - lookupElement = lookupElement.suppressAutoInsertion() + val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, descriptor) + if (suppressAutoInsertion) { + addElementWithAutoInsertionSuppressed(lookupElement) + } + else { + addElement(lookupElement) } - addElement(lookupElement) } // add special item for function with one argument of function type with more than one parameter @@ -96,6 +97,15 @@ class LookupElementsCollector(private val prefixMatcher: PrefixMatcher, } } + public fun addElementWithAutoInsertionSuppressed(element: LookupElement) { + if (isResultEmpty && elements.isEmpty()) { /* without these checks we may get duplicated items */ + addElement(element.suppressAutoInsertion()) + } + else { + addElement(element) + } + } + public fun addElements(elements: Iterable) { elements.forEach { addElement(it) } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt index ceefd195a0a..caa7fb7333e 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt @@ -17,10 +17,7 @@ package org.jetbrains.jet.plugin.completion import com.intellij.codeInsight.completion.* -import com.intellij.codeInsight.lookup.LookupElement -import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.psi.PsiClass -import com.intellij.util.Consumer import org.jetbrains.jet.asJava.KotlinLightClass import org.jetbrains.jet.lang.descriptors.ClassKind import org.jetbrains.jet.lang.psi.JetFile @@ -29,7 +26,6 @@ import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns import org.jetbrains.jet.plugin.caches.JetFromJavaDescriptorHelper -import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler import org.jetbrains.jet.plugin.project.ProjectStructureUtil import org.jetbrains.jet.plugin.project.ResolveSessionForBodies import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper @@ -53,42 +49,26 @@ class TypesCompletion(val parameters: CompletionParameters, val resolveSession: /** * Add java elements with performing conversion to kotlin elements if necessary. */ - private fun addAdaptedJavaCompletion(result: LookupElementsCollector) { - JavaClassNameCompletionContributor.addAllClasses(parameters, true, prefixMatcher, object : Consumer { - override fun consume(lookupElement: LookupElement?) { - if (lookupElement is JavaPsiClassReferenceElement) { - val psiClass = lookupElement.getObject() - - if (addJavaClassAsJetLookupElement(psiClass, result)) return - - result.addElement(object : LookupElementDecorator(lookupElement) { - override fun handleInsert(context: InsertionContext) { - JetJavaClassInsertHandler.handleInsert(context, lookupElement) - } - }.suppressAutoInsertion()) + private fun addAdaptedJavaCompletion(collector: LookupElementsCollector) { + AllClassesGetter.processJavaClasses(parameters, prefixMatcher, true, { psiClass -> + if (psiClass!! !is KotlinLightClass) { // Kotlin non-compiled class should have already been added as kotlin element before + if (JavaResolverPsiUtils.isCompiledKotlinClass(psiClass)) { + addLookupElementForCompiledKotlinClass(psiClass, collector) + } + else { + collector.addElementWithAutoInsertionSuppressed(DescriptorLookupConverter.createLookupElementForJavaClass(psiClass)) } } }) } - private fun addJavaClassAsJetLookupElement(aClass: PsiClass, result: LookupElementsCollector): Boolean { - if (aClass is KotlinLightClass) { - // Do nothing. Kotlin not-compiled class should have already been added as kotlin element before. - return true - } - - if (JavaResolverPsiUtils.isCompiledKotlinClass(aClass)) { - if (JetFromJavaDescriptorHelper.getCompiledClassKind(aClass) != ClassKind.CLASS_OBJECT) { - val qualifiedName = aClass.getQualifiedName() - if (qualifiedName != null) { - result.addDescriptorElements(ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), FqName(qualifiedName)), - suppressAutoInsertion = true) - } + private fun addLookupElementForCompiledKotlinClass(aClass: PsiClass, collector: LookupElementsCollector) { + if (JetFromJavaDescriptorHelper.getCompiledClassKind(aClass) != ClassKind.CLASS_OBJECT) { + val qualifiedName = aClass.getQualifiedName() + if (qualifiedName != null) { + val descriptors = ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), FqName(qualifiedName)) + collector.addDescriptorElements(descriptors, suppressAutoInsertion = true) } - - return true } - - return false } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetJavaClassInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetJavaClassInsertHandler.kt index 75ac98b67f9..aad37f77af8 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetJavaClassInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetJavaClassInsertHandler.kt @@ -28,7 +28,7 @@ import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper * Handler for inserting java class completion. * - Should place import directive if necessary. */ -public object JetJavaClassInsertHandler : InsertHandler { +object JetJavaClassInsertHandler : InsertHandler { override fun handleInsert(context: InsertionContext, item: JavaPsiClassReferenceElement) { PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments() diff --git a/idea/testData/completion/basic/java/NoImportedJavaClassDuplication.kt b/idea/testData/completion/basic/java/NoDuplicationForImportedJavaClass.kt similarity index 86% rename from idea/testData/completion/basic/java/NoImportedJavaClassDuplication.kt rename to idea/testData/completion/basic/java/NoDuplicationForImportedJavaClass.kt index 6f87bb1a5cd..4d224a78310 100644 --- a/idea/testData/completion/basic/java/NoImportedJavaClassDuplication.kt +++ b/idea/testData/completion/basic/java/NoDuplicationForImportedJavaClass.kt @@ -2,6 +2,6 @@ import java.io.InputStreamReader val x = InputStreamReader -// INVOCATION_COUNT: 1 +// INVOCATION_COUNT: 2 // EXIST: { lookupString:"InputStreamReader", tailText:" (java.io)" } // NUMBER: 1 \ No newline at end of file diff --git a/idea/testData/completion/basic/java/NoClassNameDuplicationForRuntimeClass.kt b/idea/testData/completion/basic/java/NoDuplicationForRuntimeClass.kt similarity index 100% rename from idea/testData/completion/basic/java/NoClassNameDuplicationForRuntimeClass.kt rename to idea/testData/completion/basic/java/NoDuplicationForRuntimeClass.kt diff --git a/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java index a0a4a44d3ca..38e26febc85 100644 --- a/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java @@ -17,13 +17,10 @@ package org.jetbrains.jet.completion; import com.intellij.testFramework.TestDataPath; -import junit.framework.Test; -import junit.framework.TestSuite; -import org.junit.runner.RunWith; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.test.InnerTestClasses; import org.jetbrains.jet.test.TestMetadata; -import org.jetbrains.jet.JUnit3RunnerWithInners; +import org.junit.runner.RunWith; import java.io.File; import java.util.regex.Pattern; @@ -846,15 +843,15 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } - @TestMetadata("NoClassNameDuplicationForRuntimeClass.kt") - public void testNoClassNameDuplicationForRuntimeClass() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/java/NoClassNameDuplicationForRuntimeClass.kt"); + @TestMetadata("NoDuplicationForImportedJavaClass.kt") + public void testNoDuplicationForImportedJavaClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/java/NoDuplicationForImportedJavaClass.kt"); doTest(fileName); } - @TestMetadata("NoImportedJavaClassDuplication.kt") - public void testNoImportedJavaClassDuplication() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/java/NoImportedJavaClassDuplication.kt"); + @TestMetadata("NoDuplicationForRuntimeClass.kt") + public void testNoDuplicationForRuntimeClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/java/NoDuplicationForRuntimeClass.kt"); doTest(fileName); } diff --git a/idea/tests/org/jetbrains/jet/completion/MultiFileJvmBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/MultiFileJvmBasicCompletionTestGenerated.java index 4b8302aad3b..d551bbd781c 100644 --- a/idea/tests/org/jetbrains/jet/completion/MultiFileJvmBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/MultiFileJvmBasicCompletionTestGenerated.java @@ -17,9 +17,13 @@ package org.jetbrains.jet.completion; import com.intellij.testFramework.TestDataPath; -import org.jetbrains.jet.JetTestUtils; -import org.jetbrains.jet.test.TestMetadata; +import junit.framework.Test; +import junit.framework.TestSuite; import org.junit.runner.RunWith; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; +import org.jetbrains.jet.JUnit3RunnerWithInners; import java.io.File; import java.util.regex.Pattern;