diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index d0518ba688e8..51747d7dc732 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -220,6 +220,16 @@ public class CompileDriver { if (!useOutOfProcessBuild()) { scope = addAdditionalRoots(scope, ALL_EXCEPT_SOURCE_PROCESSING); } + else { + final Application app = ApplicationManager.getApplication(); + if (!app.isUnitTestMode()) { + final boolean isDispatchThread = app.isDispatchThread(); + LOG.assertTrue(!isDispatchThread, "Calling isUpToDate() from Event Dispatch Thread may cause deadlocks"); + if (isDispatchThread) { + return false; + } + } + } final CompilerTask task = new CompilerTask(myProject, "Classes up-to-date check", true, false); final DependencyCache cache = useOutOfProcessBuild()? null : createDependencyCache(); 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 20f02fc5b320..4fee3f47ab08 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java @@ -190,15 +190,35 @@ public class StatisticsWeigher extends CompletionWeigher { return info == null ? StatisticsInfo.EMPTY : info; } + /** + * For different prefixes we want to prefer different completion items, + * so we decorate their basic stat-infos depending on prefix. + * For example, consider that an item "fooBar" was chosen with a prefix "foo" + * Then we'll register "fooBar" for each of the sub-prefixes: "", "f", "fo" and "foo" + * and suggest "foobar" whenever we a user types any of those prefixes + * + * If a user has typed "fooB" for which there's no stat-info registered, we want to check + * all of its sub-prefixes: "", "f", "fo", "foo" and see if any of them is associated with a stat-info + * But if the item were "fobia" and the user has typed "fob", we don't want to claim + * that "fooBar" (which matches) is statistically better than "fobia" with prefix "fob" even though both begin with "fo" + * So we only check non-partial sub-prefixes, then ones that had been really typed by the user before completing + * + * @param forWriting controls whether this stat-info will be used for incrementing usage count or for its retrieval (for sorting) + */ public static StatisticsInfo composeStatsWithPrefix(StatisticsInfo info, final String fullPrefix, boolean forWriting) { ArrayList infos = new ArrayList((fullPrefix.length() + 3) * info.getConjuncts().size()); for (StatisticsInfo conjunct : info.getConjuncts()) { if (forWriting) { + // some completion contributors may need pure statistical information to speed up searching for frequently chosen items infos.add(conjunct); } for (int i = 0; i <= fullPrefix.length(); i++) { + // if we're incrementing usage count, register all sub-prefixes with "partial" mark + // if we're sorting and any sub-prefix was used as non-partial to choose this completion item, prefer it infos.add(composeWithPrefix(conjunct, fullPrefix.substring(0, i), forWriting)); } + // if we're incrementing usage count, the full prefix is registered as non-partial + // if we're sorting and the current prefix was used as partial sub-prefix to choose this completion item, prefer it infos.add(composeWithPrefix(conjunct, fullPrefix, !forWriting)); } return StatisticsInfo.createComposite(infos);