diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index a2c8030a99b..cff300670be 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -973,7 +973,7 @@ public class JetTypeMapper { public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind, List valueParameters) { if (f instanceof FunctionImportedFromObject) { - return mapSignature(((FunctionImportedFromObject) f).getFunctionFromObject()); + return mapSignature(((FunctionImportedFromObject) f).getCallableFromObject()); } BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt index 032ade25af7..ba3dbdf9f50 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt @@ -19,15 +19,17 @@ package org.jetbrains.kotlin.resolve import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.types.TypeSubstitutor -abstract class ImportedFromObjectCallableDescriptor(val containingObject: ClassDescriptor): CallableDescriptor +abstract class ImportedFromObjectCallableDescriptor(val callableFromObject: TCallable) : CallableDescriptor { + val containingObject = callableFromObject.containingDeclaration as ClassDescriptor +} // members imported from object should be wrapped to not require dispatch receiver -class FunctionImportedFromObject(val functionFromObject: FunctionDescriptor) : +class FunctionImportedFromObject(functionFromObject: FunctionDescriptor) : FunctionDescriptor by functionFromObject, - ImportedFromObjectCallableDescriptor(functionFromObject.containingDeclaration as ClassDescriptor) { + ImportedFromObjectCallableDescriptor(functionFromObject) { override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null - override fun substitute(substitutor: TypeSubstitutor) = functionFromObject.substitute(substitutor).wrap() + override fun substitute(substitutor: TypeSubstitutor) = callableFromObject.substitute(substitutor).wrap() private val _original by lazy { functionFromObject.original.wrap() @@ -43,12 +45,13 @@ class FunctionImportedFromObject(val functionFromObject: FunctionDescriptor) : } } -class PropertyImportedFromObject(val propertyFromObject: PropertyDescriptor) : +class PropertyImportedFromObject(propertyFromObject: PropertyDescriptor) : PropertyDescriptor by propertyFromObject, - ImportedFromObjectCallableDescriptor(propertyFromObject.containingDeclaration as ClassDescriptor) { + ImportedFromObjectCallableDescriptor(propertyFromObject) { + override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null - override fun substitute(substitutor: TypeSubstitutor) = propertyFromObject.substitute(substitutor)?.wrap() + override fun substitute(substitutor: TypeSubstitutor) = callableFromObject.substitute(substitutor)?.wrap() private val _original by lazy { propertyFromObject.original.wrap() diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt index c4d50651d5d..4e5598eca9c 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt @@ -214,6 +214,11 @@ class BasicCompletionSession( collector.addDescriptorElements(notImported, lookupElementFactory, notImported = true) } + val staticMembersCompletion = StaticMembersCompletion(collector, prefixMatcher, resolutionFacade, lookupElementFactory, referenceVariants!!.imported) + if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { + staticMembersCompletion.completeFromImports(position.containingFile as KtFile) + } + completeNonImported(lookupElementFactory) flushToResultSet() @@ -229,7 +234,7 @@ class BasicCompletionSession( } if (configuration.completeStaticMembers && callTypeAndReceiver is CallTypeAndReceiver.DEFAULT && prefix.isNotEmpty()) { - StaticMembersCompletion(collector, prefixMatcher, indicesHelper(false), lookupElementFactory).complete() + staticMembersCompletion.completeFromIndices(indicesHelper(false)) } } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt index 444d8c1435b..ee92b3a6334 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt @@ -16,10 +16,7 @@ package org.jetbrains.kotlin.idea.completion -import com.intellij.codeInsight.completion.CompletionProgressIndicator -import com.intellij.codeInsight.completion.CompletionService -import com.intellij.codeInsight.completion.InsertionContext -import com.intellij.codeInsight.completion.PrefixMatcher +import com.intellij.codeInsight.completion.* import com.intellij.codeInsight.lookup.* import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.util.Key @@ -31,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.KotlinIcons import org.jetbrains.kotlin.idea.completion.handlers.CastReceiverInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler +import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.name.Name @@ -70,6 +68,7 @@ enum class ItemPriority { IMPLEMENT, OVERRIDE, NAMED_PARAMETER, + STATIC_MEMBER_FROM_IMPORTS, STATIC_MEMBER } @@ -354,9 +353,14 @@ fun singleCharPattern(char: Char) = StandardPatterns.character().equalTo(char) fun LookupElement.decorateAsStaticMember( memberDescriptor: DeclarationDescriptor, - classDescriptor: ClassDescriptor, classNameAsLookupString: Boolean -): LookupElement { +): LookupElement? { + var container = memberDescriptor.containingDeclaration as? ClassDescriptor ?: return null + var classDescriptor = if (container.isCompanionObject) + container.containingDeclaration as? ClassDescriptor ?: return null + else + container + val qualifierPresentation = classDescriptor.getName().asString() val qualifierText = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(classDescriptor) @@ -384,15 +388,34 @@ fun LookupElement.decorateAsStaticMember( } override fun handleInsert(context: InsertionContext) { - val prefix = qualifierText + "." + val psiDocumentManager = PsiDocumentManager.getInstance(context.project) + val file = context.file as KtFile - val offset = context.startOffset - context.document.insertString(offset, prefix) - context.offsetMap.addOffset(CompletionInitializationContext.START_OFFSET, offset + prefix.length) + val classImportableFqName = container.importableFqName + val useImport = classImportableFqName != null && file.importDirectives.any { + !it.isAllUnder && it.importPath?.fqnPart()?.parent() == classImportableFqName + } - shortenReferences(context, offset, offset + prefix.length) - PsiDocumentManager.getInstance(context.project).doPostponedOperationsAndUnblockDocument(context.document) + var insertQualifier = true + if (useImport) { + psiDocumentManager.commitAllDocuments() + if (ImportInsertHelper.getInstance(context.project).importDescriptor(file, memberDescriptor) != ImportInsertHelper.ImportDescriptorResult.FAIL) { + insertQualifier = false + } + } + if (insertQualifier) { + val prefix = qualifierText + "." + + val offset = context.startOffset + context.document.insertString(offset, prefix) + context.offsetMap.addOffset(CompletionInitializationContext.START_OFFSET, offset + prefix.length) + + shortenReferences(context, offset, offset + prefix.length) + + } + + psiDocumentManager.doPostponedOperationsAndUnblockDocument(context.document) super.handleInsert(context) } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/StaticMembersCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/StaticMembersCompletion.kt index 35d561b1b45..c1e209a664f 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/StaticMembersCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/StaticMembersCompletion.kt @@ -20,41 +20,76 @@ import com.intellij.codeInsight.completion.PrefixMatcher import com.intellij.codeInsight.lookup.LookupElement import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper +import org.jetbrains.kotlin.idea.core.targetDescriptors +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered +import java.util.* class StaticMembersCompletion( private val collector: LookupElementsCollector, private val prefixMatcher: PrefixMatcher, - private val indicesHelper: KotlinIndicesHelper, - private val lookupElementFactory: LookupElementFactory + private val resolutionFacade: ResolutionFacade, + private val lookupElementFactory: LookupElementFactory, + alreadyAdded: Collection ) { + private val alreadyAdded = alreadyAdded.mapTo(HashSet()) { + if (it is ImportedFromObjectCallableDescriptor<*>) it.callableFromObject else it + } + + //TODO: include it in smart completion? + fun completeFromImports(file: KtFile) { + val containers = file.importDirectives + .filter { !it.isAllUnder } + .map { + it.targetDescriptors(resolutionFacade).map { it.containingDeclaration }.distinct().singleOrNull() as? ClassDescriptor + } + .filterNotNull() + .toSet() + + for (container in containers) { + val memberScope = if (container.kind == ClassKind.OBJECT) container.unsubstitutedMemberScope else container.staticScope + val members = memberScope.getDescriptorsFiltered(DescriptorKindFilter.CALLABLES exclude DescriptorKindExclude.Extensions, prefixMatcher.asNameFilter()) + for (member in members) { + if (member is CallableDescriptor) { + addFromDescriptor(member, ItemPriority.STATIC_MEMBER_FROM_IMPORTS) + } + } + } + } + //TODO: SAM-adapters - //TODO: different priority&behaviour when static import from the same class exist - //TODO: filter out those that are visible from bases/imports etc //TODO: filter out those that are accessible from SmartCompletion.additionalItems - fun complete() { + //TODO: what about enum members? + //TODO: filter out Kotlin functions from file facades + //TODO: better presentation for lookup elements from imports too + //TODO: better sorting + //TODO: from the same file + fun completeFromIndices(indicesHelper: KotlinIndicesHelper) { val descriptorKindFilter = DescriptorKindFilter.CALLABLES exclude DescriptorKindExclude.Extensions val nameFilter: (String) -> Boolean = { prefixMatcher.prefixMatches(it) } - for (member in indicesHelper.getJavaStaticMembers(descriptorKindFilter, nameFilter)) { - collector.addElement(createLookupElement(member) ?: continue) - } + indicesHelper.getJavaStaticMembers(descriptorKindFilter, nameFilter).forEach { addFromDescriptor(it, ItemPriority.STATIC_MEMBER) } - for (member in indicesHelper.getObjectMembers(descriptorKindFilter, nameFilter)) { - collector.addElement(createLookupElement(member) ?: continue) + indicesHelper.getObjectMembers(descriptorKindFilter, nameFilter).forEach { addFromDescriptor(it, ItemPriority.STATIC_MEMBER) } + } + + private fun addFromDescriptor(member: CallableDescriptor, itemPriority: ItemPriority) { + if (member !in alreadyAdded) { + collector.addElement(createLookupElement(member, itemPriority) ?: return) } } - private fun createLookupElement(descriptor: CallableDescriptor): LookupElement? { - var classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return null - if (classDescriptor.isCompanionObject) { - classDescriptor = classDescriptor.containingDeclaration as? ClassDescriptor ?: return null - } + private fun createLookupElement(descriptor: CallableDescriptor, itemPriority: ItemPriority): LookupElement? { return lookupElementFactory.createLookupElement(descriptor, useReceiverTypes = false) - .decorateAsStaticMember(descriptor, classDescriptor, classNameAsLookupString = false) - .assignPriority(ItemPriority.STATIC_MEMBER) - .suppressAutoInsertion() + .decorateAsStaticMember(descriptor, classNameAsLookupString = false) + ?.assignPriority(itemPriority) + ?.suppressAutoInsertion() } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/StaticMembers.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/StaticMembers.kt index 66d92659640..b6675b7d096 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/StaticMembers.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/StaticMembers.kt @@ -78,9 +78,7 @@ class StaticMembers( return } - collection.addLookupElements(descriptor, expectedInfos, matcher) { - descriptor -> createLookupElements(descriptor, classDescriptor) - } + collection.addLookupElements(descriptor, expectedInfos, matcher) { createLookupElements(it) } } classDescriptor.getStaticScope().getContributedDescriptors().forEach(::processMember) @@ -99,10 +97,10 @@ class StaticMembers( members.forEach(::processMember) } - private fun createLookupElements(memberDescriptor: DeclarationDescriptor, classDescriptor: ClassDescriptor): Collection { + private fun createLookupElements(memberDescriptor: DeclarationDescriptor): Collection { return lookupElementFactory.createLookupElementsInSmartCompletion(memberDescriptor, bindingContext, useReceiverTypes = false) .map { - it.decorateAsStaticMember(memberDescriptor, classDescriptor, classNameAsLookupString = true) + it.decorateAsStaticMember(memberDescriptor, classNameAsLookupString = true)!! .assignSmartCompletionPriority(SmartCompletionItemPriority.STATIC_MEMBER) } } diff --git a/idea/idea-completion/testData/basic/common/ImportedMemberFromObject.kt b/idea/idea-completion/testData/basic/common/ImportedMemberFromObject.kt index 405a79a5f7a..4e397d7cb9e 100644 --- a/idea/idea-completion/testData/basic/common/ImportedMemberFromObject.kt +++ b/idea/idea-completion/testData/basic/common/ImportedMemberFromObject.kt @@ -11,5 +11,5 @@ fun main() { uniqueN } -// EXIST: uniqueName +// EXIST: { allLookupStrings: "uniqueName", itemText: "uniqueName", tailText: "()", typeText: "Unit", attributes: "" } // NUMBER: 1 \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/staticMembers/ImportsFromObjectNoDuplicates.kt b/idea/idea-completion/testData/basic/common/staticMembers/ImportsFromObjectNoDuplicates.kt new file mode 100644 index 00000000000..561895b1c78 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/staticMembers/ImportsFromObjectNoDuplicates.kt @@ -0,0 +1,23 @@ +package a + +import a.O.xxxVal1 +import a.O.xxxFun1 + +object O { + fun xxxFun1() { } + fun xxxFun2() { } + + val xxxVal1 = 1 + val xxxVal2 = 2 +} + +fun main() { + xxx +} + +// INVOCATION_COUNT: 2 +// EXIST: { allLookupStrings: "xxxFun1", itemText: "xxxFun1" } +// EXIST: { allLookupStrings: "xxxFun2", itemText: "O.xxxFun2" } +// EXIST: { allLookupStrings: "getXxxVal1, xxxVal1", itemText: "xxxVal1" } +// EXIST: { allLookupStrings: "getXxxVal2, xxxVal2", itemText: "O.xxxVal2" } +// NOTHING_ELSE diff --git a/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticFieldsFromImports.kt b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticFieldsFromImports.kt new file mode 100644 index 00000000000..9c684b0328b --- /dev/null +++ b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticFieldsFromImports.kt @@ -0,0 +1,9 @@ +import java.awt.GridBagConstraints.NORTH + +fun foo() { + SOUT +} + +// INVOCATION_COUNT: 1 +// EXIST_JAVA_ONLY: { allLookupStrings: "SOUTH, getSOUTH", itemText: "GridBagConstraints.SOUTH", tailText: " (java.awt)", typeText: "Int", attributes: "" } +// ABSENT: { itemText: "SwingConstants.SOUTH" } diff --git a/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsFromImports.kt b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsFromImports.kt new file mode 100644 index 00000000000..4257467c025 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsFromImports.kt @@ -0,0 +1,10 @@ +import java.util.Collections.singletonList + +fun foo() { + singl +} + +// INVOCATION_COUNT: 1 +// EXIST_JAVA_ONLY: { allLookupStrings: "singleton", itemText: "Collections.singleton", tailText: "(T!) (java.util)", typeText: "(Mutable)Set!", attributes: "" } +// ABSENT: { itemText: "Collections.singletonList" } +// EXIST_JAVA_ONLY: { itemText: "singletonList", tailText: "(T!)", typeText: "(Mutable)List!", attributes: "" } diff --git a/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicates.kt b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicates.kt new file mode 100644 index 00000000000..6b4962303af --- /dev/null +++ b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicates.kt @@ -0,0 +1,9 @@ +import java.util.Collections.max + +fun foo() { + lastIndexOfSub +} + +// INVOCATION_COUNT: 2 +// EXIST_JAVA_ONLY: { allLookupStrings: "lastIndexOfSubList", itemText: "Collections.lastIndexOfSubList" } +// NOTHING_ELSE diff --git a/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicatesFromBases.kt b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicatesFromBases.kt new file mode 100644 index 00000000000..ba42f15ba72 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicatesFromBases.kt @@ -0,0 +1,11 @@ +import javax.swing.SwingUtilities + +class A : SwingUtilities { + fun foo() { + invoke + } +} + +// INVOCATION_COUNT: 2 +// ABSENT: { itemText: "SwingUtilities.invokeLater" } +// EXIST_JAVA_ONLY: { itemText: "invokeLater" } diff --git a/idea/idea-completion/testData/handlers/basic/staticMembers/ImportFromCompanionObject.kt b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportFromCompanionObject.kt new file mode 100644 index 00000000000..f839339af04 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportFromCompanionObject.kt @@ -0,0 +1,8 @@ +import kotlin.text.Regex.Companion.fromLiteral + +fun foo() { + escape +} + +// INVOCATION_COUNT: 1 +// ELEMENT_TEXT: "Regex.escapeReplacement" diff --git a/idea/idea-completion/testData/handlers/basic/staticMembers/ImportFromCompanionObject.kt.after b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportFromCompanionObject.kt.after new file mode 100644 index 00000000000..54345db9ea6 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportFromCompanionObject.kt.after @@ -0,0 +1,9 @@ +import kotlin.text.Regex.Companion.escapeReplacement +import kotlin.text.Regex.Companion.fromLiteral + +fun foo() { + escapeReplacement() +} + +// INVOCATION_COUNT: 1 +// ELEMENT_TEXT: "Regex.escapeReplacement" diff --git a/idea/idea-completion/testData/handlers/basic/staticMembers/ImportJavaStaticMethod.kt b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportJavaStaticMethod.kt new file mode 100644 index 00000000000..7fcf9b807af --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportJavaStaticMethod.kt @@ -0,0 +1,9 @@ +import javax.swing.SwingUtilities.invokeLater + +fun foo() { + invoke +} + +// INVOCATION_COUNT: 1 +// ELEMENT_TEXT: "SwingUtilities.invokeAndWait" +// TAIL_TEXT: " {...} ((() -> Unit)!) (javax.swing)" diff --git a/idea/idea-completion/testData/handlers/basic/staticMembers/ImportJavaStaticMethod.kt.after b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportJavaStaticMethod.kt.after new file mode 100644 index 00000000000..97d15ac6325 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/staticMembers/ImportJavaStaticMethod.kt.after @@ -0,0 +1,10 @@ +import javax.swing.SwingUtilities.invokeAndWait +import javax.swing.SwingUtilities.invokeLater + +fun foo() { + invokeAndWait { } +} + +// INVOCATION_COUNT: 1 +// ELEMENT_TEXT: "SwingUtilities.invokeAndWait" +// TAIL_TEXT: " {...} ((() -> Unit)!) (javax.swing)" 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 8b1a6b9a633..785ab521082 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 @@ -2103,17 +2103,47 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/staticMembers"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("ImportsFromObjectNoDuplicates.kt") + public void testImportsFromObjectNoDuplicates() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/ImportsFromObjectNoDuplicates.kt"); + doTest(fileName); + } + @TestMetadata("JavaStaticFields.kt") public void testJavaStaticFields() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticFields.kt"); doTest(fileName); } + @TestMetadata("JavaStaticFieldsFromImports.kt") + public void testJavaStaticFieldsFromImports() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticFieldsFromImports.kt"); + doTest(fileName); + } + @TestMetadata("JavaStaticMethods.kt") public void testJavaStaticMethods() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethods.kt"); doTest(fileName); } + + @TestMetadata("JavaStaticMethodsFromImports.kt") + public void testJavaStaticMethodsFromImports() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsFromImports.kt"); + doTest(fileName); + } + + @TestMetadata("JavaStaticMethodsNoDuplicates.kt") + public void testJavaStaticMethodsNoDuplicates() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicates.kt"); + doTest(fileName); + } + + @TestMetadata("JavaStaticMethodsNoDuplicatesFromBases.kt") + public void testJavaStaticMethodsNoDuplicatesFromBases() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicatesFromBases.kt"); + doTest(fileName); + } } @TestMetadata("idea/idea-completion/testData/basic/common/substitutedSignature") 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 47773537839..14887ff65c0 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 @@ -2103,17 +2103,47 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/staticMembers"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("ImportsFromObjectNoDuplicates.kt") + public void testImportsFromObjectNoDuplicates() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/ImportsFromObjectNoDuplicates.kt"); + doTest(fileName); + } + @TestMetadata("JavaStaticFields.kt") public void testJavaStaticFields() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticFields.kt"); doTest(fileName); } + @TestMetadata("JavaStaticFieldsFromImports.kt") + public void testJavaStaticFieldsFromImports() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticFieldsFromImports.kt"); + doTest(fileName); + } + @TestMetadata("JavaStaticMethods.kt") public void testJavaStaticMethods() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethods.kt"); doTest(fileName); } + + @TestMetadata("JavaStaticMethodsFromImports.kt") + public void testJavaStaticMethodsFromImports() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsFromImports.kt"); + doTest(fileName); + } + + @TestMetadata("JavaStaticMethodsNoDuplicates.kt") + public void testJavaStaticMethodsNoDuplicates() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicates.kt"); + doTest(fileName); + } + + @TestMetadata("JavaStaticMethodsNoDuplicatesFromBases.kt") + public void testJavaStaticMethodsNoDuplicatesFromBases() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/staticMembers/JavaStaticMethodsNoDuplicatesFromBases.kt"); + doTest(fileName); + } } @TestMetadata("idea/idea-completion/testData/basic/common/substitutedSignature") diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index b121378a943..60f9b471547 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -544,6 +544,18 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("ImportFromCompanionObject.kt") + public void testImportFromCompanionObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/staticMembers/ImportFromCompanionObject.kt"); + doTest(fileName); + } + + @TestMetadata("ImportJavaStaticMethod.kt") + public void testImportJavaStaticMethod() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/staticMembers/ImportJavaStaticMethod.kt"); + doTest(fileName); + } + @TestMetadata("JavaStaticMethod.kt") public void testJavaStaticMethod() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/staticMembers/JavaStaticMethod.kt"); diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt index a65405d4509..3da3600bce9 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt @@ -97,9 +97,9 @@ public fun ThisReceiver.asExpression(resolutionScope: LexicalScope, psiFactory: return expressionFactory.createExpression(psiFactory) } -public fun KtImportDirective.targetDescriptors(): Collection { +public fun KtImportDirective.targetDescriptors(resolutionFacade: ResolutionFacade = this.getResolutionFacade()): Collection { val nameExpression = importedReference?.getQualifiedElementSelector() as? KtSimpleNameExpression ?: return emptyList() - return nameExpression.mainReference.resolveToDescriptors(nameExpression.analyze()) + return nameExpression.mainReference.resolveToDescriptors(resolutionFacade.analyze(nameExpression)) } public fun Call.resolveCandidates(