Optimization: look for callables at first when prefix starts uppercase and the opposite otherwise
This commit is contained in:
@@ -175,6 +175,10 @@ class DescriptorKindFilter(
|
||||
abstract class DescriptorKindExclude {
|
||||
abstract fun excludes(descriptor: DeclarationDescriptor): Boolean
|
||||
|
||||
/**
|
||||
* Bit-mask of descriptor kind's that are fully excluded by this [DescriptorKindExclude].
|
||||
* That is, [excludes] returns true for all descriptor of these kinds.
|
||||
*/
|
||||
abstract val fullyExcludedDescriptorKinds: Int
|
||||
|
||||
override fun toString() = this.javaClass.simpleName
|
||||
@@ -190,8 +194,8 @@ abstract class DescriptorKindExclude {
|
||||
override fun excludes(descriptor: DeclarationDescriptor)
|
||||
= descriptor !is CallableDescriptor || descriptor.extensionReceiverParameter == null
|
||||
|
||||
override val fullyExcludedDescriptorKinds: Int
|
||||
get() = DescriptorKindFilter.ALL_KINDS_MASK and (DescriptorKindFilter.FUNCTIONS_MASK or DescriptorKindFilter.VARIABLES_MASK).inv()
|
||||
override val fullyExcludedDescriptorKinds
|
||||
= DescriptorKindFilter.ALL_KINDS_MASK and (DescriptorKindFilter.FUNCTIONS_MASK or DescriptorKindFilter.VARIABLES_MASK).inv()
|
||||
}
|
||||
|
||||
object EnumEntry : DescriptorKindExclude() {
|
||||
|
||||
+42
-11
@@ -26,9 +26,7 @@ import com.intellij.patterns.StandardPatterns
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.util.ProcessingContext
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.completion.handlers.createKeywordConstructLookupElement
|
||||
import org.jetbrains.kotlin.idea.completion.smart.ExpectedInfoMatch
|
||||
import org.jetbrains.kotlin.idea.completion.smart.SMART_COMPLETION_ITEM_PRIORITY_KEY
|
||||
@@ -39,6 +37,8 @@ import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
|
||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -158,7 +158,7 @@ class BasicCompletionSession(
|
||||
}
|
||||
|
||||
private val ALL = object : CompletionKind {
|
||||
override val descriptorKindFilter: DescriptorKindFilter? by lazy {
|
||||
override val descriptorKindFilter: DescriptorKindFilter by lazy {
|
||||
var filter = callTypeAndReceiver.callType.descriptorKindFilter
|
||||
|
||||
if (filter.kindMask.and(DescriptorKindFilter.PACKAGES_MASK) != 0) {
|
||||
@@ -201,9 +201,20 @@ class BasicCompletionSession(
|
||||
val contextVariableTypesForSmartCompletion = withCollectRequiredContextVariableTypes(::completeWithSmartCompletion)
|
||||
|
||||
val contextVariableTypesForReferenceVariants = withCollectRequiredContextVariableTypes { lookupElementFactory ->
|
||||
val (imported, notImported) = referenceVariantsWithNonInitializedVarExcluded!!
|
||||
collector.addDescriptorElements(imported, lookupElementFactory)
|
||||
collector.addDescriptorElements(notImported, lookupElementFactory, notImported = true)
|
||||
if (prefix.isEmpty() || callTypeAndReceiver.receiver != null) {
|
||||
addReferenceVariantElements(lookupElementFactory, descriptorKindFilter)
|
||||
}
|
||||
else if (prefix[0].isLowerCase()) {
|
||||
addReferenceVariantElements(lookupElementFactory, USUALLY_START_LOWER_CASE.intersect(descriptorKindFilter))
|
||||
flushToResultSet()
|
||||
addReferenceVariantElements(lookupElementFactory, USUALLY_START_UPPER_CASE.intersect(descriptorKindFilter))
|
||||
}
|
||||
else {
|
||||
addReferenceVariantElements(lookupElementFactory, USUALLY_START_UPPER_CASE.intersect(descriptorKindFilter))
|
||||
flushToResultSet()
|
||||
addReferenceVariantElements(lookupElementFactory, USUALLY_START_LOWER_CASE.intersect(descriptorKindFilter))
|
||||
}
|
||||
referenceVariantsCollector!!.collectingFinished()
|
||||
}
|
||||
|
||||
KEYWORDS_ONLY.doComplete()
|
||||
@@ -253,7 +264,11 @@ class BasicCompletionSession(
|
||||
}
|
||||
|
||||
val staticMembersCompletion = StaticMembersCompletion(
|
||||
prefixMatcher, resolutionFacade, lookupElementFactory, referenceVariants!!.imported, isJvmModule)
|
||||
prefixMatcher,
|
||||
resolutionFacade,
|
||||
lookupElementFactory,
|
||||
referenceVariantsCollector!!.allCollected.imported,
|
||||
isJvmModule)
|
||||
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||
staticMembersCompletion.completeFromImports(file, collector)
|
||||
}
|
||||
@@ -526,7 +541,7 @@ class BasicCompletionSession(
|
||||
}
|
||||
|
||||
private val SUPER_QUALIFIER = object : CompletionKind {
|
||||
override val descriptorKindFilter: DescriptorKindFilter?
|
||||
override val descriptorKindFilter: DescriptorKindFilter
|
||||
get() = DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS
|
||||
|
||||
override fun doComplete() {
|
||||
@@ -536,7 +551,7 @@ class BasicCompletionSession(
|
||||
.mapNotNull { it.constructor.declarationDescriptor as? ClassDescriptor }
|
||||
|
||||
if (callTypeAndReceiver.receiver != null) {
|
||||
val referenceVariantsSet = referenceVariants!!.imported.toSet()
|
||||
val referenceVariantsSet = referenceVariantsCollector!!.collectReferenceVariants(descriptorKindFilter).imported.toSet()
|
||||
superClasses = superClasses.filter { it in referenceVariantsSet }
|
||||
}
|
||||
|
||||
@@ -594,4 +609,20 @@ class BasicCompletionSession(
|
||||
).collect(classifierDescriptorCollector, javaClassCollector)
|
||||
}
|
||||
|
||||
}
|
||||
private fun addReferenceVariantElements(lookupElementFactory: LookupElementFactory, descriptorKindFilter: DescriptorKindFilter) {
|
||||
val (imported, notImported) = referenceVariantsCollector!!.collectReferenceVariants(descriptorKindFilter).excludeNonInitializedVariable()
|
||||
collector.addDescriptorElements(imported, lookupElementFactory)
|
||||
collector.addDescriptorElements(notImported, lookupElementFactory, notImported = true)
|
||||
}
|
||||
}
|
||||
|
||||
private val USUALLY_START_UPPER_CASE = DescriptorKindFilter(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.FUNCTIONS_MASK,
|
||||
listOf(NonSamConstructorFunctionExclude, DescriptorKindExclude.Extensions /* needed for faster getReferenceVariants */))
|
||||
private val USUALLY_START_LOWER_CASE = DescriptorKindFilter(DescriptorKindFilter.CALLABLES_MASK or DescriptorKindFilter.PACKAGES_MASK,
|
||||
listOf(SamConstructorDescriptorKindExclude))
|
||||
|
||||
private object NonSamConstructorFunctionExclude : DescriptorKindExclude() {
|
||||
override fun excludes(descriptor: DeclarationDescriptor) = descriptor is FunctionDescriptor && descriptor !is SamConstructorDescriptor
|
||||
|
||||
override val fullyExcludedDescriptorKinds: Int get() = 0
|
||||
}
|
||||
|
||||
+13
-14
@@ -269,29 +269,28 @@ abstract class CompletionSession(
|
||||
return context
|
||||
}
|
||||
|
||||
protected val referenceVariants: ReferenceVariants? by lazy {
|
||||
if (nameExpression != null && descriptorKindFilter != null)
|
||||
ReferenceVariantsCollector(referenceVariantsHelper, indicesHelper(true), prefixMatcher,
|
||||
nameExpression, callTypeAndReceiver, resolutionFacade, bindingContext,
|
||||
importableFqNameClassifier, configuration
|
||||
).collectReferenceVariants(descriptorKindFilter!!)
|
||||
else
|
||||
null
|
||||
protected val referenceVariantsCollector = if (nameExpression != null) {
|
||||
ReferenceVariantsCollector(referenceVariantsHelper, indicesHelper(true), prefixMatcher,
|
||||
nameExpression, callTypeAndReceiver, resolutionFacade, bindingContext,
|
||||
importableFqNameClassifier, configuration)
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
|
||||
protected val referenceVariantsWithNonInitializedVarExcluded: ReferenceVariants? by lazy {
|
||||
referenceVariants?.let { ReferenceVariants(referenceVariantsHelper.excludeNonInitializedVariable(it.imported, position), it.notImportedExtensions) }
|
||||
protected fun ReferenceVariants.excludeNonInitializedVariable(): ReferenceVariants {
|
||||
return ReferenceVariants(referenceVariantsHelper.excludeNonInitializedVariable(imported, position), notImportedExtensions)
|
||||
}
|
||||
|
||||
protected fun referenceVariantsWithSingleFunctionTypeParameter(): ReferenceVariants? {
|
||||
val variants = referenceVariants ?: return null
|
||||
val filter: (DeclarationDescriptor) -> Boolean = { it is FunctionDescriptor && LookupElementFactory.hasSingleFunctionTypeParameter(it) }
|
||||
val variants = referenceVariantsCollector?.allCollected ?: return null
|
||||
val filter = { descriptor: DeclarationDescriptor -> descriptor is FunctionDescriptor && LookupElementFactory.hasSingleFunctionTypeParameter(descriptor) }
|
||||
return ReferenceVariants(variants.imported.filter(filter), variants.notImportedExtensions.filter(filter))
|
||||
}
|
||||
|
||||
protected fun getRuntimeReceiverTypeReferenceVariants(lookupElementFactory: LookupElementFactory): Pair<ReferenceVariants, LookupElementFactory>? {
|
||||
val evaluator = file.getCopyableUserData(KtCodeFragment.RUNTIME_TYPE_EVALUATOR) ?: return null
|
||||
val referenceVariants = referenceVariants ?: return null
|
||||
val referenceVariants = referenceVariantsCollector?.allCollected ?: return null
|
||||
|
||||
val explicitReceiver = callTypeAndReceiver.receiver as? KtExpression ?: return null
|
||||
val type = bindingContext.getType(explicitReceiver) ?: return null
|
||||
@@ -337,7 +336,7 @@ abstract class CompletionSession(
|
||||
|
||||
protected fun processTopLevelCallables(processor: (CallableDescriptor) -> Unit) {
|
||||
val shadowedFilter = ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, nameExpression!!, callTypeAndReceiver)
|
||||
?.createNonImportedDeclarationsFilter<CallableDescriptor>(referenceVariants!!.imported)
|
||||
?.createNonImportedDeclarationsFilter<CallableDescriptor>(referenceVariantsCollector!!.allCollected.imported)
|
||||
indicesHelper(true).processTopLevelCallables({ prefixMatcher.prefixMatches(it) }) {
|
||||
if (shadowedFilter != null) {
|
||||
shadowedFilter(listOf(it)).singleOrNull()?.let(processor)
|
||||
|
||||
+28
-4
@@ -32,10 +32,11 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
|
||||
import java.util.*
|
||||
|
||||
data class ReferenceVariants(val imported: Collection<DeclarationDescriptor>, val notImportedExtensions: Collection<CallableDescriptor>)
|
||||
|
||||
internal class ReferenceVariantsCollector(
|
||||
class ReferenceVariantsCollector(
|
||||
private val referenceVariantsHelper: ReferenceVariantsHelper,
|
||||
private val indicesHelper: KotlinIndicesHelper,
|
||||
private val prefixMatcher: PrefixMatcher,
|
||||
@@ -50,8 +51,32 @@ internal class ReferenceVariantsCollector(
|
||||
private val prefix = prefixMatcher.prefix
|
||||
private val descriptorNameFilter = prefixMatcher.asStringNameFilter()
|
||||
|
||||
private val collectedImported = LinkedHashSet<DeclarationDescriptor>()
|
||||
private val collectedNotImportedExtensions = LinkedHashSet<CallableDescriptor>()
|
||||
private var isCollectingFinished = false
|
||||
|
||||
val allCollected: ReferenceVariants
|
||||
get() {
|
||||
assert(isCollectingFinished)
|
||||
return ReferenceVariants(collectedImported, collectedNotImportedExtensions)
|
||||
}
|
||||
|
||||
fun collectingFinished() {
|
||||
assert(!isCollectingFinished)
|
||||
isCollectingFinished = true
|
||||
}
|
||||
|
||||
fun collectReferenceVariants(descriptorKindFilter: DescriptorKindFilter): ReferenceVariants {
|
||||
assert(!isCollectingFinished)
|
||||
val variants = doCollectReferenceVariants(descriptorKindFilter)
|
||||
collectedImported.addAll(variants.imported)
|
||||
collectedNotImportedExtensions.addAll(variants.notImportedExtensions)
|
||||
return variants
|
||||
}
|
||||
|
||||
private fun doCollectReferenceVariants(descriptorKindFilter: DescriptorKindFilter): ReferenceVariants {
|
||||
val completeExtensionsFromIndices = descriptorKindFilter.kindMask.and(DescriptorKindFilter.CALLABLES_MASK) != 0
|
||||
&& DescriptorKindExclude.Extensions !in descriptorKindFilter.excludes
|
||||
&& callTypeAndReceiver !is CallTypeAndReceiver.IMPORT_DIRECTIVE
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val descriptorKindFilter = if (completeExtensionsFromIndices)
|
||||
@@ -131,8 +156,7 @@ internal class ReferenceVariantsCollector(
|
||||
return true
|
||||
}
|
||||
|
||||
override val fullyExcludedDescriptorKinds: Int
|
||||
get() = 0
|
||||
override val fullyExcludedDescriptorKinds: Int get() = 0
|
||||
}
|
||||
|
||||
private fun isDataClassComponentFunction(descriptor: DeclarationDescriptor): Boolean {
|
||||
@@ -141,4 +165,4 @@ internal class ReferenceVariantsCollector(
|
||||
DataClassDescriptorResolver.isComponentLike(descriptor.name) &&
|
||||
descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -86,9 +86,12 @@ class SmartCompletionSession(
|
||||
val filter = smartCompletion!!.descriptorFilter
|
||||
val contextVariableTypesForReferenceVariants = filter?.let {
|
||||
withCollectRequiredContextVariableTypes { lookupElementFactory ->
|
||||
val (imported, notImported) = referenceVariantsWithNonInitializedVarExcluded ?: return@withCollectRequiredContextVariableTypes
|
||||
imported.forEach { collector.addElements(filter(it, lookupElementFactory)) }
|
||||
notImported.forEach { collector.addElements(filter(it, lookupElementFactory), notImported = true) }
|
||||
if (referenceVariantsCollector != null) {
|
||||
val (imported, notImported) = referenceVariantsCollector.collectReferenceVariants(descriptorKindFilter).excludeNonInitializedVariable()
|
||||
imported.forEach { collector.addElements(filter(it, lookupElementFactory)) }
|
||||
notImported.forEach { collector.addElements(filter(it, lookupElementFactory), notImported = true) }
|
||||
referenceVariantsCollector.collectingFinished()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +123,8 @@ class SmartCompletionSession(
|
||||
if (filter != null) {
|
||||
val staticMembersCompletion: StaticMembersCompletion?
|
||||
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||
staticMembersCompletion = StaticMembersCompletion(prefixMatcher, resolutionFacade, lookupElementFactory, referenceVariants!!.imported, isJvmModule)
|
||||
val alreadyCollected = referenceVariantsCollector!!.allCollected.imported
|
||||
staticMembersCompletion = StaticMembersCompletion(prefixMatcher, resolutionFacade, lookupElementFactory, alreadyCollected, isJvmModule)
|
||||
val decoratedFactory = staticMembersCompletion.decoratedLookupElementFactory(ItemPriority.STATIC_MEMBER_FROM_IMPORTS)
|
||||
staticMembersCompletion.membersFromImports(file)
|
||||
.flatMap { filter(it, decoratedFactory) }
|
||||
|
||||
Reference in New Issue
Block a user