2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com
.intellij
.codeInsight
.completion
;
19 import com
.intellij
.codeInsight
.lookup
.*;
20 import com
.intellij
.codeInsight
.lookup
.impl
.LookupImpl
;
21 import com
.intellij
.codeInsight
.lookup
.impl
.LookupItemWeightComparable
;
22 import com
.intellij
.openapi
.util
.Key
;
23 import com
.intellij
.psi
.PsiElement
;
24 import com
.intellij
.psi
.WeighingService
;
25 import com
.intellij
.psi
.statistics
.StatisticsInfo
;
26 import com
.intellij
.psi
.statistics
.StatisticsManager
;
28 import java
.util
.Collections
;
29 import java
.util
.Comparator
;
30 import java
.util
.List
;
32 public class CompletionLookupArranger
extends LookupArranger
{
33 public static final Key
<LookupItemWeightComparable
> RELEVANCE_KEY
= Key
.create("RELEVANCE_KEY");
34 private static final Key
<Comparable
> SORTING_KEY
= Key
.create("SORTING_KEY");
35 private static final String SELECTED
= "selected";
36 static final String IGNORED
= "ignored";
37 private final CompletionLocation myLocation
;
38 public static final Key
<Comparable
[]> WEIGHT
= Key
.create("WEIGHT");
40 public CompletionLookupArranger(final CompletionParameters parameters
) {
41 myLocation
= new CompletionLocation(parameters
);
45 public void sortItems(List
<LookupElement
> items
) {
46 Collections
.sort(items
, new Comparator
<LookupElement
>() {
47 public int compare(LookupElement o1
, LookupElement o2
) {
48 //noinspection unchecked
49 return getSortingWeight(o1
).compareTo(getSortingWeight(o2
));
54 public void itemSelected(LookupElement item
, final Lookup lookup
) {
55 final StatisticsManager manager
= StatisticsManager
.getInstance();
56 manager
.incUseCount(CompletionService
.STATISTICS_KEY
, item
, myLocation
);
57 final List
<LookupElement
> items
= lookup
.getItems();
58 final LookupImpl lookupImpl
= (LookupImpl
)lookup
;
59 final int count
= Math
.min(lookupImpl
.getPreferredItemsCount(), lookupImpl
.getList().getSelectedIndex());
60 for (int i
= 0; i
< count
; i
++) {
61 final LookupElement element
= items
.get(i
);
62 StatisticsInfo info
= StatisticsManager
.serialize(CompletionService
.STATISTICS_KEY
, element
, myLocation
);
63 if (info
!= null && info
!= StatisticsInfo
.EMPTY
&& manager
.getUseCount(info
) == 0) {
64 manager
.incUseCount(new StatisticsInfo(composeContextWithValue(info
), item
== element ? SELECTED
: IGNORED
));
70 public int suggestPreselectedItem(List
<LookupElement
> sorted
) {
71 final CompletionPreselectSkipper
[] skippers
= CompletionPreselectSkipper
.EP_NAME
.getExtensions();
73 nextItem
: for (int i
= 0; i
< sorted
.size(); i
++){
74 LookupElement item
= sorted
.get(i
);
75 final Object obj
= item
.getObject();
76 if (obj
instanceof PsiElement
&& !((PsiElement
)obj
).isValid()) continue;
78 for (final CompletionPreselectSkipper skipper
: skippers
) {
79 if (skipper
.skipElement(item
, myLocation
)) {
86 return sorted
.size() - 1;
89 public static String
composeContextWithValue(final StatisticsInfo info
) {
90 return info
.getContext() + "###" + info
.getValue();
93 public Comparable
[] getRelevanceWeight(final LookupElement item
) {
94 if (item
.getUserData(WEIGHT
) != null) return item
.getUserData(WEIGHT
);
96 final Comparable
[] result
= new Comparable
[]{WeighingService
.weigh(CompletionService
.RELEVANCE_KEY
, item
, myLocation
)};
98 item
.putUserData(WEIGHT
, result
);
103 public Comparable
getSortingWeight(final LookupElement item
) {
104 if (item
.getUserData(SORTING_KEY
) != null) return item
.getUserData(SORTING_KEY
);
106 final Comparable result
= WeighingService
.weigh(CompletionService
.SORTING_KEY
, item
, myLocation
);
108 item
.putUserData(SORTING_KEY
, result
);
114 public static int doCompare(final double priority1
, final double priority2
, final Comparable
[] weight1
, final Comparable
[] weight2
) {
115 if (priority1
!= priority2
) {
116 final double v
= priority1
- priority2
;
117 if (v
> 0) return -1;
121 for (int i
= 0; i
< weight1
.length
; i
++) {
122 final Comparable w1
= weight1
[i
];
123 final Comparable w2
= weight2
[i
];
124 if (w1
!= null || w2
!= null) {
125 if (w1
== null) return 1;
126 if (w2
== null) return -1;
127 //noinspection unchecked
128 final int res
= w1
.compareTo(w2
);
129 if (res
!= 0) return -res
;
137 public LookupItemWeightComparable
getRelevance(LookupElement item
) {
138 if (item
.getUserData(RELEVANCE_KEY
) != null) return item
.getUserData(RELEVANCE_KEY
);
140 final double priority
= item
instanceof LookupItem ?
((LookupItem
)item
).getPriority() : 0;
141 final LookupItemWeightComparable result
= new LookupItemWeightComparable(priority
, getRelevanceWeight(item
));
143 item
.putUserData(RELEVANCE_KEY
, result
);