2b81c113041cb63065f2ee3f284c7612ec5b7714
[idea/community.git] / plugins / stats-collector / src / com / intellij / stats / completion / LookupCompletedTracker.kt
1 /*
2  * Copyright 2000-2017 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.intellij.stats.completion
18
19 import com.intellij.codeInsight.lookup.LookupAdapter
20 import com.intellij.codeInsight.lookup.LookupElement
21 import com.intellij.codeInsight.lookup.LookupEvent
22 import com.intellij.codeInsight.lookup.impl.LookupImpl
23 import com.intellij.completion.FeatureManagerImpl
24 import com.intellij.stats.personalization.UserFactorDescriptions
25 import com.intellij.stats.personalization.UserFactorStorage
26
27 /**
28  * @author Vitaliy.Bibaev
29  */
30 class LookupCompletedTracker : LookupAdapter() {
31     override fun lookupCanceled(event: LookupEvent?) {
32         val lookup = event?.lookup as? LookupImpl ?: return
33         val element = lookup.currentItem ?: return
34         if (isSelectedByTyping(lookup, element)) {
35             processTypedSelect(lookup, element)
36         }
37     }
38
39     override fun itemSelected(event: LookupEvent?) {
40         val lookup = event?.lookup as? LookupImpl ?: return
41         val element = event.item ?: return
42         processExplicitSelect(lookup, element)
43     }
44
45     private fun isSelectedByTyping(lookup: LookupImpl, element: LookupElement): Boolean =
46             element.lookupString == lookup.itemPattern(element)
47
48     private fun processElementSelected(lookup: LookupImpl, element: LookupElement) {
49         val relevanceObjects =
50                 lookup.getRelevanceObjects(listOf(element), false)
51         val relevanceMap = relevanceObjects[element]?.associate { it.first to it.second } ?: return
52         val project = lookup.project
53         val featureManager = FeatureManagerImpl.getInstance()
54         featureManager.binaryFactors.filter { !featureManager.isUserFeature(it.name) }.forEach { feature ->
55             UserFactorStorage.applyOnBoth(project, UserFactorDescriptions.binaryFeatureDescriptor(feature))
56             { updater ->
57                 updater.update(relevanceMap[feature.name])
58             }
59         }
60
61         featureManager.doubleFactors.filter { !featureManager.isUserFeature(it.name) }.forEach { feature ->
62             UserFactorStorage.applyOnBoth(project, UserFactorDescriptions.doubleFeatureDescriptor(feature))
63             { updater ->
64                 updater.update(relevanceMap[feature.name])
65             }
66         }
67
68         featureManager.categorialFactors.filter { !featureManager.isUserFeature(it.name) }.forEach { feature ->
69             UserFactorStorage.applyOnBoth(project, UserFactorDescriptions.categoriealFeatureDescriptor(feature))
70             { updater ->
71                 updater.update(relevanceMap[feature.name])
72             }
73         }
74     }
75
76     private fun processExplicitSelect(lookup: LookupImpl, element: LookupElement) {
77         processElementSelected(lookup, element)
78
79         UserFactorStorage.applyOnBoth(lookup.project, UserFactorDescriptions.COMPLETION_FINISH_TYPE) { updater ->
80             updater.fireExplicitCompletionPerformed()
81         }
82
83         val prefixLength = lookup.getPrefixLength(element)
84         UserFactorStorage.applyOnBoth(lookup.project, UserFactorDescriptions.PREFIX_LENGTH_ON_COMPLETION) { updater ->
85             updater.fireCompletionPerformed(prefixLength)
86         }
87
88         val itemPosition = lookup.selectedIndex
89         if (itemPosition != -1) {
90             UserFactorStorage.applyOnBoth(lookup.project, UserFactorDescriptions.SELECTED_ITEM_POSITION) { updater ->
91                 updater.fireCompletionPerformed(itemPosition)
92             }
93         }
94
95         if (prefixLength > 1) {
96             val pattern = lookup.itemPattern(element)
97             val isMmemonicsUsed = !element.lookupString.startsWith(pattern)
98             UserFactorStorage.applyOnBoth(lookup.project, UserFactorDescriptions.MNEMONICS_USAGE) { updater ->
99                 updater.fireCompletionFinished(isMmemonicsUsed)
100             }
101         }
102     }
103
104     private fun processTypedSelect(lookup: LookupImpl, element: LookupElement) {
105         processElementSelected(lookup, element)
106
107         UserFactorStorage.applyOnBoth(lookup.project, UserFactorDescriptions.COMPLETION_FINISH_TYPE) { updater ->
108             updater.fireTypedSelectPerformed()
109         }
110     }
111 }