From dc875194eb551372a31e0336856ddae1dd719a21 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 24 Aug 2015 17:17:24 +0300 Subject: [PATCH] Better Statistician for completion --- .../idea/completion/CompletionSession.kt | 32 +++++++++++++++++++ .../kotlin/idea/completion/CompletionUtils.kt | 2 ++ .../kotlin/idea/completion/Statisticians.kt | 12 ++++--- 3 files changed, 42 insertions(+), 4 deletions(-) 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 02552f663e4..b31ea34f735 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 @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.completion.* import com.intellij.codeInsight.completion.impl.CamelHumpMatcher +import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.patterns.ElementPattern @@ -32,6 +33,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolveScope import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper import org.jetbrains.kotlin.idea.core.* +import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.frontendService @@ -217,6 +219,16 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC } public fun complete(): Boolean { + val statisticsContext = calcContextForStatisticsInfo() + if (statisticsContext != null) { + collector.addLookupElementPostProcessor { lookupElement -> + // we should put data into the original element because of DecoratorCompletionStatistician + val unwrapped = sequence(lookupElement) { (it as? LookupElementDecorator<*>)?.delegate }.last() + unwrapped.putUserData(STATISTICS_INFO_CONTEXT_KEY, statisticsContext) + lookupElement + } + } + doComplete() flushToResultSet() return !collector.isResultEmpty @@ -242,6 +254,26 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC return sorter } + protected fun calcContextForStatisticsInfo(): String? { + if (expectedInfos.isEmpty()) return null + + var context = expectedInfos + .map { it.fuzzyType?.type?.constructor?.declarationDescriptor?.importableFqName } + .filterNotNull() + .singleOrNull() + ?.let { "expectedType=$it" } + + if (context == null) { + context = expectedInfos + .map { it.expectedName } + .filterNotNull() + .singleOrNull() + ?.let { "expectedName=$it" } + } + + return context + } + protected val referenceVariants: Collection by lazy { if (descriptorKindFilter != null) { referenceVariantsHelper.getReferenceVariants( 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 de376cc9fa7..3cc4487cc1f 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 @@ -61,6 +61,8 @@ fun LookupElement.assignPriority(priority: ItemPriority): LookupElement { return this } +val STATISTICS_INFO_CONTEXT_KEY = Key("STATISTICS_INFO_CONTEXT_KEY") + val NOT_IMPORTED_KEY = Key("NOT_IMPORTED_KEY") fun LookupElement.suppressAutoInsertion() = AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(this) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt index 98d283d60e0..b5a64aa541c 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.completion.CompletionLocation import com.intellij.codeInsight.completion.CompletionStatistician import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.psi.PsiElement import com.intellij.psi.statistics.StatisticsInfo import com.intellij.psi.util.ProximityLocation @@ -38,12 +39,15 @@ class KotlinCompletionStatistician : CompletionStatistician() { override fun serialize(element: LookupElement, location: CompletionLocation): StatisticsInfo? { val o = (element.`object` as? DeclarationLookupObject) ?: return null + assert(element !is LookupElementDecorator<*>, "LookupElementDecorator's should be unwrapped by DecoratorCompletionStatistician") + val context = element.getUserData(STATISTICS_INFO_CONTEXT_KEY) ?: "" + if (o.descriptor != null) { - return KotlinStatisticsInfo.forDescriptor(o.descriptor!!) + return KotlinStatisticsInfo.forDescriptor(o.descriptor!!, context) } else { val fqName = o.importableFqName ?: return StatisticsInfo.EMPTY - return StatisticsInfo("", fqName.asString()) + return StatisticsInfo(context, fqName.asString()) } } } @@ -67,7 +71,7 @@ object KotlinStatisticsInfo { parameterNameRenderingPolicy = ParameterNameRenderingPolicy.NONE } - fun forDescriptor(descriptor: DeclarationDescriptor): StatisticsInfo { + fun forDescriptor(descriptor: DeclarationDescriptor, context: String = ""): StatisticsInfo { if (descriptor is ClassDescriptor) { return descriptor.importableFqName?.let { StatisticsInfo("", it.asString()) } ?: StatisticsInfo.EMPTY } @@ -80,6 +84,6 @@ object KotlinStatisticsInfo { else -> null } ?: return StatisticsInfo.EMPTY val signature = SIGNATURE_RENDERER.render(descriptor) - return StatisticsInfo("", "$containerFqName###$signature") + return StatisticsInfo(context, "$containerFqName###$signature") } }