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 81b779316ab..b12684ae2b1 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 @@ -25,7 +25,10 @@ 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.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtObjectDeclaration import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter @@ -94,11 +97,25 @@ class StaticMembersCompletion( indicesHelper.getJavaStaticMembers(descriptorKindFilter, nameFilter).filterTo(result) { it !in alreadyAdded } //TODO: substitution } - indicesHelper.getObjectMembers(descriptorKindFilter, nameFilter).filterTo(result) { it !in alreadyAdded } //TODO: substitution + indicesHelper.getObjectMembers(descriptorKindFilter, nameFilter) filter@ { declaration, objectDeclaration -> + !declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD) && objectDeclaration.isTopLevelOrCompanion() + }.filterTo(result) { + it !in alreadyAdded //TODO: substitution + } return result } + private fun KtObjectDeclaration.isTopLevelOrCompanion(): Boolean { + if (isCompanion()) { + val owner = parent.parent as? KtClass ?: return false + return owner.isTopLevel() + } + else { + return isTopLevel() + } + } + fun completeFromImports(file: KtFile, collector: LookupElementsCollector) { val factory = decoratedLookupElementFactory(ItemPriority.STATIC_MEMBER_FROM_IMPORTS) membersFromImports(file) diff --git a/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.dependency.kt b/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.dependency.kt index 0474c72871a..1202273a589 100644 --- a/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.dependency.kt +++ b/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.dependency.kt @@ -2,13 +2,13 @@ package test object KotlinObject { fun funFromObject() { } - private fun privateFun(){} + private fun funPrivate(){} } class KotlinClass { companion object SomeName { fun funFromCompanionObject() { } - private fun privateFun(){} + private fun funPrivate(){} } } @@ -16,4 +16,28 @@ class AnotherKotlinClass { private companion object { fun funFromPrivateCompanionObject() { } } + + object Nested { + fun fromNested(){} + } +} + +interface I { + fun fromInterface() +} + +object DefaultI : I { + override fun fromInterface() { + } +} + + +fun foo() { + val o = object : Runnable { + override fun run() { + fromAnonymous() + } + + fun fromAnonymous(){} + } } diff --git a/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.kt b/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.kt index 4290d2fbd73..78c467de784 100644 --- a/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.kt +++ b/idea/idea-completion/testData/basic/multifile/ObjectMembers/ObjectMembers.kt @@ -1,11 +1,14 @@ package first fun testFun() { - funFromO + f } // INVOCATION_COUNT: 2 // EXIST: { allLookupStrings: "funFromObject", itemText: "KotlinObject.funFromObject", tailText: "() (test)", typeText: "Unit", attributes: "" } // EXIST: { allLookupStrings: "funFromCompanionObject", itemText: "KotlinClass.funFromCompanionObject", tailText: "() (test)", typeText: "Unit", attributes: "" } -// ABSENT: privateFun +// ABSENT: funPrivate // ABSENT: funFromPrivateCompanionObject +// ABSENT: fromNested +// ABSENT: fromInterface +// ABSENT: fromAnonymous diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index d28686e27fe..e1feb28e1b7 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.core import com.intellij.codeInsight.CodeInsightSettings import com.intellij.openapi.progress.ProgressManager +import com.intellij.psi.PsiFile import com.intellij.psi.PsiModifier import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.PsiShortNamesCache @@ -196,7 +197,11 @@ public class KotlinIndicesHelper( .filter(descriptorFilter) } - public fun getObjectMembers(descriptorKindFilter: DescriptorKindFilter, nameFilter: (String) -> Boolean): Collection { + public fun getObjectMembers( + descriptorKindFilter: DescriptorKindFilter, + nameFilter: (String) -> Boolean, + filter: (KtCallableDeclaration, KtObjectDeclaration) -> Boolean + ): Collection { val result = LinkedHashSet() fun addFromIndex(index: StringStubIndexExtension) { @@ -205,8 +210,10 @@ public class KotlinIndicesHelper( if (!nameFilter(name)) continue for (declaration in index.get(name, project, scope)) { - if (declaration.parent.parent !is KtObjectDeclaration) continue + val objectDeclaration = declaration.parent.parent as? KtObjectDeclaration ?: continue + if (objectDeclaration.isObjectLiteral()) continue if (!visibilityFilterMayIncludeAccessible && declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) continue + if (!filter(declaration, objectDeclaration)) continue declaration.resolveToDescriptorsWithHack().filterTo(result) { descriptorKindFilter.accepts(it) && descriptorFilter(it) } } } @@ -235,6 +242,7 @@ public class KotlinIndicesHelper( for (method in shortNamesCache.getMethodsByName(name, scope)) { if (!method.hasModifierProperty(PsiModifier.STATIC)) continue if (!visibilityFilterMayIncludeAccessible && method.hasModifierProperty(PsiModifier.PRIVATE)) continue + if (method.containingClass?.parent !is PsiFile) continue // only top-level classes val descriptor = method.getJavaMethodDescriptor(resolutionFacade) ?: continue val container = descriptor.containingDeclaration as? ClassDescriptor ?: continue if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) {