From fc59ce102b1b7367f9aeff397dfb6c743d9e6dcc Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 29 Aug 2012 15:56:01 +0200 Subject: [PATCH] cache lookup element statistic info and don't try to calculate it after insertion when everything could have become invalid (EA-38180) --- .../completion/CompletionSortingTestCase.java | 3 +- .../completion/CodeCompletionHandlerBase.java | 3 +- .../completion/CompletionLookupArranger.java | 15 +++--- .../completion/StatisticsWeigher.java | 54 +++++++++++-------- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java index ed2113bae6b5..fbbf0fae59ed 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java @@ -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(); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 43f39b09af1b..43cfc76ce348 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -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(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java index 251d862edee2..abd708206b89 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -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 toIncrement = new ArrayList(); - 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.emptyList()); } - StatisticsUpdate update = new StatisticsUpdate(toIncrement); + StatisticsUpdate update = new StatisticsUpdate(StatisticsWeigher.composeStatsWithPrefix(base, lookup.itemPattern(item))); ourPendingUpdate = update; Disposer.register(update, new Disposable() { @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java index 86092ef5fa5c..baf889f7877f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java @@ -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 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 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 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 composeStatsWithPrefix(StatisticsInfo info, final String fullPrefix) { ArrayList infos = new ArrayList(fullPrefix.length() + 1); infos.add(info); for (int i = 1; i <= fullPrefix.length(); i++) {