diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt index eb38be9e9d4..8bc74b494db 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper -import org.jetbrains.kotlin.idea.core.isInExcludedPackage import org.jetbrains.kotlin.idea.project.ProjectStructureUtil import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.psi.JetFile @@ -42,12 +41,11 @@ class AllClassesCompletion(private val parameters: CompletionParameters, //TODO: this is a temporary hack until we have built-ins in indices val builtIns = JavaToKotlinClassMap.INSTANCE.allKotlinClasses() val filteredBuiltIns = builtIns - .filter { kindFilter(it.getKind()) && prefixMatcher.prefixMatches(it.getName().asString()) && !isInExcludedPackage(it) } + .filter { kindFilter(it.getKind()) && prefixMatcher.prefixMatches(it.getName().asString()) } filteredBuiltIns.forEach { classDescriptorCollector(it) } kotlinIndicesHelper - .getClassDescriptors({ prefixMatcher.prefixMatches(it) }, kindFilter) - .filter { !isInExcludedPackage(it) } + .getKotlinClasses({ prefixMatcher.prefixMatches(it) }, kindFilter) .forEach { classDescriptorCollector(it) } if (!ProjectStructureUtil.isJsKotlinModule(parameters.getOriginalFile() as JetFile)) { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index 0536e5f1642..a4051bab04b 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -165,7 +165,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC } protected val indicesHelper: KotlinIndicesHelper - get() = KotlinIndicesHelper(project, resolutionFacade, searchScope, moduleDescriptor, isVisibleFilter) + get() = KotlinIndicesHelper(project, resolutionFacade, searchScope, moduleDescriptor, isVisibleFilter, true) protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean { if (descriptor is TypeParameterDescriptor && !isTypeParameterVisible(descriptor)) return false @@ -247,17 +247,16 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC protected fun getTopLevelCallables(): Collection { val descriptors = indicesHelper.getTopLevelCallables({ prefixMatcher.prefixMatches(it) }) - return filterShadowedNonImportedAndExcluded(descriptors, reference!!) + return filterShadowedNonImported(descriptors, reference!!) } protected fun getTopLevelExtensions(): Collection { val descriptors = indicesHelper.getCallableTopLevelExtensions({ prefixMatcher.prefixMatches(it) }, reference!!.expression, bindingContext) - return filterShadowedNonImportedAndExcluded(descriptors, reference) + return filterShadowedNonImported(descriptors, reference) } - private fun filterShadowedNonImportedAndExcluded(descriptors: Collection, reference: JetSimpleNameReference): Collection { - val notExcluded = descriptors.filter { !isInExcludedPackage(it) } - return ShadowedDeclarationsFilter(bindingContext, moduleDescriptor, project).filterNonImported(notExcluded, referenceVariants, reference.expression) + private fun filterShadowedNonImported(descriptors: Collection, reference: JetSimpleNameReference): Collection { + return ShadowedDeclarationsFilter(bindingContext, moduleDescriptor, project).filterNonImported(descriptors, referenceVariants, reference.expression) } protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) { 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 0dba554ed58..09f9f8b248b 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 @@ -19,10 +19,13 @@ package org.jetbrains.kotlin.idea.core import com.intellij.codeInsight.CodeInsightSettings import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PsiShortNamesCache import com.intellij.psi.stubs.StringStubIndexExtension import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper +import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.stubindex.* import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance @@ -49,8 +52,15 @@ public class KotlinIndicesHelper( private val resolutionFacade: ResolutionFacade, private val scope: GlobalSearchScope, private val moduleDescriptor: ModuleDescriptor, - private val visibilityFilter: (DeclarationDescriptor) -> Boolean + visibilityFilter: (DeclarationDescriptor) -> Boolean, + applyExcludeSettings: Boolean ) { + private val descriptorFilter = + if (applyExcludeSettings) + { d -> visibilityFilter(d) && !isExcludedFromAutoImport(d) } + else + visibilityFilter + public fun getTopLevelCallablesByName(name: String): Collection { val declarations = HashSet() declarations.addTopLevelNonExtensionCallablesByName(JetFunctionShortNameIndex.getInstance(), name) @@ -62,7 +72,7 @@ public class KotlinIndicesHelper( else { (resolutionFacade.resolveToDescriptor(it) as? CallableDescriptor).singletonOrEmptyList() } - }.filter { it.getExtensionReceiverParameter() == null && visibilityFilter(it) } + }.filter { it.getExtensionReceiverParameter() == null && descriptorFilter(it) } } private fun MutableSet.addTopLevelNonExtensionCallablesByName( @@ -78,7 +88,7 @@ public class KotlinIndicesHelper( .map { FqName(it) } .filter { nameFilter(it.shortName().asString()) } .toSet() - .flatMap { findTopLevelCallables(it).filter(visibilityFilter) } + .flatMap { findTopLevelCallables(it).filter(descriptorFilter) } } public fun getCallableTopLevelExtensions(nameFilter: (String) -> Boolean, expression: JetSimpleNameExpression, bindingContext: BindingContext): Collection { @@ -148,7 +158,7 @@ public class KotlinIndicesHelper( val result = LinkedHashSet() fun processDescriptor(descriptor: CallableDescriptor) { - if (visibilityFilter(descriptor)) { + if (descriptorFilter(descriptor)) { for ((receiverValue, callType) in receiverValues) { result.addAll(descriptor.substituteExtensionIfCallable(receiverValue, callType, bindingContext, dataFlowInfo, moduleDescriptor)) } @@ -172,7 +182,14 @@ public class KotlinIndicesHelper( return result } - public fun getClassDescriptors(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection { + public fun getJvmClassesByName(name: String): Collection + = PsiShortNamesCache.getInstance(project).getClassesByName(name, scope) + .map { resolutionFacade.psiClassToDescriptor(it) } + .filterNotNull() + .filter(descriptorFilter) + .toSet() + + public fun getKotlinClasses(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection { return JetFullClassNameIndex.getInstance().getAllKeys(project).asSequence() .map { FqName(it) } .filter { nameFilter(it.shortName().asString()) } @@ -190,7 +207,7 @@ public class KotlinIndicesHelper( // Note: Can't search with psi element as analyzer could be built over temp files return ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(moduleDescriptor, classFQName) { kindFilter(it.getKind()) } - .filter(visibilityFilter) + .filter(descriptorFilter) } private fun findTopLevelCallables(fqName: FqName): Collection { @@ -198,11 +215,12 @@ public class KotlinIndicesHelper( .filterIsInstance() .filter { it.getExtensionReceiverParameter() == null } } + + private fun isExcludedFromAutoImport(descriptor: DeclarationDescriptor): Boolean { + val fqName = descriptor.importableFqName?.asString() ?: return false + + return CodeInsightSettings.getInstance().EXCLUDED_PACKAGES + .any { excluded -> fqName == excluded || (fqName.startsWith(excluded) && fqName[excluded.length()] == '.') } + } } -public fun isInExcludedPackage(descriptor: DeclarationDescriptor): Boolean { - val fqName = DescriptorUtils.getFqName(descriptor).asString() - - return CodeInsightSettings.getInstance().EXCLUDED_PACKAGES - .any { excluded -> fqName == excluded || fqName.startsWith(excluded + ".") } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt index e19b1d325f9..ed285d81bb6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt @@ -24,8 +24,6 @@ import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.PsiShortNamesCache import com.intellij.psi.util.PsiModificationTracker import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility @@ -37,7 +35,6 @@ import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper import org.jetbrains.kotlin.idea.core.isVisible -import org.jetbrains.kotlin.idea.core.psiClassToDescriptor import org.jetbrains.kotlin.idea.project.ProjectStructureUtil import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetPsiUtil @@ -48,8 +45,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.utils.CachedValueProperty import java.util.ArrayList -import com.intellij.codeInsight.* -import org.jetbrains.kotlin.idea.core.isInExcludedPackage /** * Check possibility and perform fix for unresolved references. @@ -140,31 +135,23 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction() val moduleDescriptor = resolutionFacade.findModuleDescriptor(element) - val indicesHelper = KotlinIndicesHelper(file.getProject(), resolutionFacade, searchScope, moduleDescriptor, ::isVisible) + val indicesHelper = KotlinIndicesHelper(file.getProject(), resolutionFacade, searchScope, moduleDescriptor, ::isVisible, true) if (!element.isImportDirectiveExpression() && !JetPsiUtil.isSelectorInQualified(element)) { if (ProjectStructureUtil.isJsKotlinModule(file)) { - result.addAll(indicesHelper.getClassDescriptors({ it == referenceName }, { true })) + result.addAll(indicesHelper.getKotlinClasses({ it == referenceName }, { true })) } else { - getClasses(referenceName, file, searchScope).filterTo(result, ::isVisible) + result.addAll(indicesHelper.getJvmClassesByName(referenceName)) } result.addAll(indicesHelper.getTopLevelCallablesByName(referenceName)) } result.addAll(indicesHelper.getCallableTopLevelExtensions({ it == referenceName }, element, bindingContext)) - return result.filter { it -> !isInExcludedPackage(it) } + return result } - private fun getClasses(name: String, file: JetFile, searchScope: GlobalSearchScope): Collection - = getShortNamesCache(file).getClassesByName(name, searchScope) - .map { element.getResolutionFacade().psiClassToDescriptor(it) } - .filterNotNull() - .toSet() - - private fun getShortNamesCache(jetFile: JetFile): PsiShortNamesCache = PsiShortNamesCache.getInstance(jetFile.getProject()) - companion object { private val ERRORS = setOf(Errors.UNRESOLVED_REFERENCE, Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER)