cache lookup element statistic info and don't try to calculate it after insertion when everything could have become invalid (EA-38180)

This commit is contained in:
peter
2012-08-29 17:19:29 +02:00
parent bf233f4377
commit fc59ce102b
4 changed files with 41 additions and 34 deletions
@@ -5,7 +5,6 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
@@ -77,7 +76,7 @@ public abstract class CompletionSortingTestCase extends LightFixtureCompletionTe
protected static void imitateItemSelection(final LookupImpl lookup, final int index) {
final LookupElement item = lookup.getItems().get(index);
lookup.setCurrentItem(item);
CompletionLookupArranger.collectStatisticChanges(CompletionServiceImpl.getCompletionService().getCurrentCompletion(), item);
CompletionLookupArranger.collectStatisticChanges(item, lookup);
CompletionLookupArranger.applyLastCompletionStatisticsUpdate();
}
}
@@ -593,7 +593,8 @@ public class CodeCompletionHandlerBase {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_BASIC);
}
final CompletionLookupArranger.StatisticsUpdate update = CompletionLookupArranger.collectStatisticChanges(indicator, item);
final CompletionLookupArranger.StatisticsUpdate update =
CompletionLookupArranger.collectStatisticChanges(item, indicator.getParameters().getLookup());
final Editor editor = indicator.getEditor();
@@ -138,6 +138,8 @@ public class CompletionLookupArranger extends LookupArranger {
@Override
public void addElement(Lookup lookup, LookupElement element, LookupElementPresentation presentation) {
StatisticsWeigher.clearBaseStatisticsInfo(element);
final String invariant = presentation.getItemText() + "###" + getTailTextOrSpace(presentation) + "###" + presentation.getTypeText();
element.putUserData(PRESENTATION_INVARIANT, invariant);
@@ -366,18 +368,15 @@ public class CompletionLookupArranger extends LookupArranger {
return element instanceof LiveTemplateLookupElement && ((LiveTemplateLookupElement)element).sudden;
}
public static StatisticsUpdate collectStatisticChanges(CompletionProgressIndicator indicator, LookupElement item) {
public static StatisticsUpdate collectStatisticChanges(LookupElement item, final Lookup lookup) {
applyLastCompletionStatisticsUpdate();
CompletionLocation location = new CompletionLocation(indicator.getParameters());
final StatisticsInfo main = StatisticsManager.serialize(CompletionService.STATISTICS_KEY, item, location);
final List<StatisticsInfo> toIncrement = new ArrayList<StatisticsInfo>();
if (main != null && main != StatisticsInfo.EMPTY) {
toIncrement.addAll(StatisticsWeigher.composeStatsWithPrefix(main, location, item));
final StatisticsInfo base = StatisticsWeigher.getBaseStatisticsInfo(item, null);
if (base == StatisticsInfo.EMPTY) {
return new StatisticsUpdate(Collections.<StatisticsInfo>emptyList());
}
StatisticsUpdate update = new StatisticsUpdate(toIncrement);
StatisticsUpdate update = new StatisticsUpdate(StatisticsWeigher.composeStatsWithPrefix(base, lookup.itemPattern(item)));
ourPendingUpdate = update;
Disposer.register(update, new Disposable() {
@Override
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Key;
import com.intellij.psi.statistics.StatisticsInfo;
import com.intellij.psi.statistics.StatisticsManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -32,14 +33,14 @@ import java.util.List;
*/
public class StatisticsWeigher extends CompletionWeigher {
private static final StatisticsManager ourStatManager = StatisticsManager.getInstance();
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.StatisticsWeigher.LookupStatisticsWeigher");
private static final Key<StatisticsInfo> BASE_STATISTICS_INFO = Key.create("Base statistics info");
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
throw new UnsupportedOperationException();
}
public static class LookupStatisticsWeigher extends LookupElementWeigher {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.StatisticsWeigher.LookupStatisticsWeigher");
private static final Key<StatisticsInfo> BASE_INFO = Key.create("Base statistics info");
private final CompletionLocation myLocation;
public LookupStatisticsWeigher(CompletionLocation location) {
@@ -49,38 +50,45 @@ public class StatisticsWeigher extends CompletionWeigher {
@Override
public Integer weigh(@NotNull LookupElement item) {
final StatisticsInfo info = getBaseStatisticsInfo(item);
final StatisticsInfo info = getBaseStatisticsInfo(item, myLocation);
if (info == StatisticsInfo.EMPTY) {
return 0;
}
int max = 0;
for (StatisticsInfo statisticsInfo : composeStatsWithPrefix(info, myLocation, item)) {
for (StatisticsInfo statisticsInfo : composeStatsWithPrefix(info, myLocation.getCompletionParameters().getLookup().itemPattern(item))) {
max = Math.max(max, ourStatManager.getUseCount(statisticsInfo));
}
return max;
}
@NotNull
private StatisticsInfo getBaseStatisticsInfo(LookupElement item) {
StatisticsInfo info = BASE_INFO.get(item);
if (info == null) {
BASE_INFO.set(item, info = calcBaseInfo(item));
}
return info;
}
@NotNull
private StatisticsInfo calcBaseInfo(LookupElement item) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
LOG.assertTrue(!ApplicationManager.getApplication().isDispatchThread());
}
StatisticsInfo info = StatisticsManager.serialize(CompletionService.STATISTICS_KEY, item, myLocation);
return info == null ? StatisticsInfo.EMPTY : info;
}
}
public static List<StatisticsInfo> composeStatsWithPrefix(StatisticsInfo info, CompletionLocation location, LookupElement item) {
String fullPrefix = location.getCompletionParameters().getLookup().itemPattern(item);
public static void clearBaseStatisticsInfo(LookupElement item) {
item.putUserData(BASE_STATISTICS_INFO, null);
}
@NotNull
public static StatisticsInfo getBaseStatisticsInfo(LookupElement item, @Nullable CompletionLocation location) {
StatisticsInfo info = BASE_STATISTICS_INFO.get(item);
if (info == null) {
if (location == null) {
return StatisticsInfo.EMPTY;
}
BASE_STATISTICS_INFO.set(item, info = calcBaseInfo(item, location));
}
return info;
}
@NotNull
private static StatisticsInfo calcBaseInfo(LookupElement item, @NotNull CompletionLocation location) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
LOG.assertTrue(!ApplicationManager.getApplication().isDispatchThread());
}
StatisticsInfo info = StatisticsManager.serialize(CompletionService.STATISTICS_KEY, item, location);
return info == null ? StatisticsInfo.EMPTY : info;
}
public static List<StatisticsInfo> composeStatsWithPrefix(StatisticsInfo info, final String fullPrefix) {
ArrayList<StatisticsInfo> infos = new ArrayList<StatisticsInfo>(fullPrefix.length() + 1);
infos.add(info);
for (int i = 1; i <= fullPrefix.length(); i++) {