Skip to content

Commit a194b12

Browse files
committed
CompletionPhase
1 parent 2015c37 commit a194b12

File tree

6 files changed

+104
-8
lines changed

6 files changed

+104
-8
lines changed

platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ private void doComplete(final int invocationCount, CompletionInitializationConte
267267

268268
final LookupImpl lookup = obtainLookup(editor);
269269

270+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.synchronous);
271+
270272
final Semaphore freezeSemaphore = new Semaphore();
271273
freezeSemaphore.down();
272274
final CompletionProgressIndicator indicator = new CompletionProgressIndicator(editor, parameters, this, freezeSemaphore,
@@ -467,12 +469,14 @@ protected void completionFinished(final int offset1,
467469
final LookupElement[] items) {
468470
if (items.length == 0) {
469471
LookupManager.getInstance(indicator.getProject()).hideActiveLookup();
470-
handleEmptyLookup(indicator.getProject(), indicator.getEditor(), indicator.getParameters(), indicator);
472+
CompletionServiceImpl.setCompletionPhase(
473+
handleEmptyLookup(indicator.getProject(), indicator.getEditor(), indicator.getParameters(), indicator));
471474
return;
472475
}
473476

474477
final AutoCompletionDecision decision = shouldAutoComplete(indicator, items);
475478
if (decision == AutoCompletionDecision.SHOW_LOOKUP) {
479+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.itemsCalculated);
476480
indicator.getLookup().setCalculating(false);
477481
indicator.showLookup();
478482
if (isAutocompleteCommonPrefixOnInvocation() && items.length > 1) {
@@ -490,6 +494,7 @@ else if (decision instanceof AutoCompletionDecision.InsertItem) {
490494
// the insert handler may have started a live template with completion
491495
if (CompletionService.getCompletionService().getCurrentCompletion() == null) {
492496
indicator.liveAfterDeath(null);
497+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.insertedSingleItem);
493498
} else {
494499
LOG.assertTrue(!indicator.isZombie(), indicator);
495500
}
@@ -591,12 +596,13 @@ private boolean isAutocompleteCommonPrefixOnInvocation() {
591596
return invokedExplicitly && CodeInsightSettings.getInstance().AUTOCOMPLETE_COMMON_PREFIX;
592597
}
593598

594-
protected void handleEmptyLookup(Project project, Editor editor, final CompletionParameters parameters, final CompletionProgressIndicator indicator) {
595-
if (ApplicationManager.getApplication().isUnitTestMode()) return;
599+
protected CompletionPhase handleEmptyLookup(Project project, Editor editor, final CompletionParameters parameters, final CompletionProgressIndicator indicator) {
600+
if (ApplicationManager.getApplication().isUnitTestMode()) return CompletionPhase.noCompletion;
596601
if (!invokedExplicitly) {
597-
return;
602+
return CompletionPhase.noCompletion;
598603
}
599604

605+
CompletionPhase result = CompletionPhase.noCompletion;
600606
for (final CompletionContributor contributor : CompletionContributor.forParameters(parameters)) {
601607
final String text = contributor.handleEmptyLookup(parameters, editor);
602608
if (StringUtil.isNotEmpty(text)) {
@@ -609,13 +615,15 @@ public void hintShown(final Project project, final LightweightHint hint, final i
609615
connection.subscribe(EditorHintListener.TOPIC, listener);
610616
HintManager.getInstance().showErrorHint(editor, text);
611617
connection.disconnect();
618+
result = CompletionPhase.noSuggestionsHint;
612619
break;
613620
}
614621
}
615622
DaemonCodeAnalyzer codeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
616623
if (codeAnalyzer != null) {
617624
codeAnalyzer.updateVisibleHighlighters(editor);
618625
}
626+
return result;
619627
}
620628

621629
private static void lookupItemSelected(final CompletionProgressIndicator indicator, @NotNull final LookupElement item, final char completionChar,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2000-2011 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+
package com.intellij.codeInsight.completion;
17+
18+
/**
19+
* @author peter
20+
*/
21+
public enum CompletionPhase {
22+
noCompletion,
23+
autoPopupAlarm,
24+
synchronous,
25+
bgCalculation,
26+
itemsCalculated,
27+
restarted,
28+
insertedSingleItem,
29+
noSuggestionsHint,
30+
possiblyDisturbingAutoPopup,
31+
emptyAutoPopup,
32+
33+
}

platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ public int getSelectionEndOffset() {
146146
}
147147

148148
void notifyBackgrounded() {
149+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.bgCalculation);
149150
myState.setBackgrounded();
150151
}
151152

@@ -480,6 +481,8 @@ private void finishCompletionProcess() {
480481
ApplicationManager.getApplication().assertIsDispatchThread();
481482
Disposer.dispose(myQueue);
482483
unregisterItself(false);
484+
485+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.noCompletion);
483486
}
484487

485488
@TestOnly
@@ -491,6 +494,12 @@ public static void cleanupForNextTest() {
491494
}
492495

493496
private void unregisterItself(boolean afterDeath) {
497+
if (afterDeath) {
498+
CompletionServiceImpl.assertPhase(CompletionPhase.noSuggestionsHint, CompletionPhase.insertedSingleItem);
499+
} else {
500+
CompletionServiceImpl.assertPhase(CompletionPhase.bgCalculation, CompletionPhase.itemsCalculated, CompletionPhase.synchronous, CompletionPhase.restarted);
501+
}
502+
494503
myState.handleDeath(afterDeath);
495504
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
496505
assert currentCompletion == this : currentCompletion + "!=" + this;
@@ -522,14 +531,17 @@ public void run() {
522531
LOG.assertTrue(current == null, current + "!=" + CompletionProgressIndicator.this);
523532

524533
if (!isAutopopupCompletion()) {
525-
myHandler.handleEmptyLookup(getProject(), myEditor, myParameters, CompletionProgressIndicator.this);
534+
CompletionServiceImpl.setCompletionPhase(myHandler.handleEmptyLookup(getProject(), myEditor, myParameters, CompletionProgressIndicator.this));
535+
} else {
536+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.noCompletion);
526537
}
527538
}
528539
else {
529540
if (myState.isFocusLookupWhenDone()) {
530541
myLookup.setFocused(true);
531542
}
532543
updateLookup();
544+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.itemsCalculated);
533545
}
534546
}
535547
}, myQueue.getModalityState());
@@ -542,13 +554,15 @@ public boolean hideAutopopupIfMeaningless() {
542554
if (items.isEmpty() && !myLookup.isCalculating()) {
543555
myLookup.hideLookup(false);
544556
LOG.assertTrue(CompletionServiceImpl.getCompletionService().getCurrentCompletion() == null);
557+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.emptyAutoPopup);
545558
return true;
546559
}
547560

548561
for (LookupElement item : items) {
549562
if ((item.getPrefixMatcher().getPrefix() + myLookup.getAdditionalPrefix()).equals(item.getLookupString())) {
550563
myLookup.hideLookup(true); // so that the autopopup attempts to restart after the next typed character
551564
LOG.assertTrue(CompletionServiceImpl.getCompletionService().getCurrentCompletion() == null);
565+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.possiblyDisturbingAutoPopup);
552566
return true;
553567
}
554568
}
@@ -676,6 +690,7 @@ public void prefixUpdated() {
676690
public void scheduleRestart() {
677691
ApplicationManager.getApplication().assertIsDispatchThread();
678692
myState.scheduleRestart();
693+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.restarted);
679694

680695
final Project project = getProject();
681696
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -684,6 +699,9 @@ public void run() {
684699
if (isOutdated()) {
685700
return;
686701
}
702+
if (CompletionServiceImpl.getCompletionPhase() != CompletionPhase.restarted) {
703+
return;
704+
}
687705

688706
closeAndFinish(false);
689707

platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionState.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.intellij.codeInsight.completion;
22

3+
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
34
import com.intellij.openapi.application.ApplicationManager;
45
import com.intellij.openapi.diagnostic.Logger;
56
import com.intellij.ui.LightweightHint;
@@ -155,7 +156,8 @@ boolean hasNoVariants() {
155156
@Override
156157
public String toString() {
157158
return "CompletionState{" +
158-
"myCompletionDisposed=" + myCompletionDisposed +
159+
"phase=" + CompletionServiceImpl.getCompletionPhase() +
160+
", myCompletionDisposed=" + myCompletionDisposed +
159161
", myShownLookup=" + myShownLookup +
160162
", myCompletionHint=" + myCompletionHint +
161163
", myToRestart=" + myToRestart +

platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.intellij.codeInsight.completion.impl;
1717

18+
import com.google.common.collect.Sets;
1819
import com.intellij.codeInsight.completion.*;
1920
import com.intellij.codeInsight.lookup.LookupElement;
2021
import com.intellij.openapi.application.ApplicationManager;
@@ -24,6 +25,7 @@
2425
import com.intellij.patterns.ElementPattern;
2526
import com.intellij.psi.PsiDocumentManager;
2627
import com.intellij.psi.PsiElement;
28+
import com.intellij.psi.impl.DebugUtil;
2729
import com.intellij.util.Consumer;
2830
import org.jetbrains.annotations.NotNull;
2931
import org.jetbrains.annotations.Nullable;
@@ -35,6 +37,8 @@ public class CompletionServiceImpl extends CompletionService{
3537
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.impl.CompletionServiceImpl");
3638
private Throwable myTrace = null;
3739
private CompletionProgressIndicator myCurrentCompletion;
40+
private static CompletionPhase ourPhase = CompletionPhase.noCompletion;
41+
private static String ourPhaseTrace;
3842

3943
public static CompletionServiceImpl getCompletionService() {
4044
return (CompletionServiceImpl)CompletionService.getCompletionService();
@@ -168,4 +172,23 @@ private static String handleCaseInsensitiveVariant(final String prefix, @NotNull
168172
return lookupString;
169173
}
170174

175+
public static void assertPhase(CompletionPhase... possibilities) {
176+
assert isPhase(possibilities) : ourPhase + "; set at " + ourPhaseTrace;
177+
}
178+
179+
public static boolean isPhase(CompletionPhase... possibilities) {
180+
ApplicationManager.getApplication().assertIsDispatchThread();
181+
return Sets.newHashSet(possibilities).contains(ourPhase);
182+
}
183+
184+
public static void setCompletionPhase(@NotNull CompletionPhase phase) {
185+
ApplicationManager.getApplication().assertIsDispatchThread();
186+
ourPhase = phase;
187+
ourPhaseTrace = DebugUtil.currentStackTrace();
188+
}
189+
190+
public static CompletionPhase getCompletionPhase() {
191+
// ApplicationManager.getApplication().assertIsDispatchThread();
192+
return ourPhase;
193+
}
171194
}

platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.intellij.codeInsight.AutoPopupController;
1919
import com.intellij.codeInsight.CodeInsightSettings;
2020
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
21+
import com.intellij.codeInsight.completion.CompletionPhase;
2122
import com.intellij.codeInsight.completion.CompletionProgressIndicator;
2223
import com.intellij.codeInsight.completion.CompletionType;
2324
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
@@ -93,9 +94,13 @@ public Result checkAutoPopup(char charTyped, final Project project, final Editor
9394

9495
final boolean isMainEditor = FileEditorManager.getInstance(project).getSelectedTextEditor() == editor;
9596

97+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.autoPopupAlarm);
98+
9699
final Runnable request = new Runnable() {
97100
@Override
98101
public void run() {
102+
if (CompletionServiceImpl.getCompletionPhase() != CompletionPhase.autoPopupAlarm) return;
103+
99104
if (project.isDisposed() || !file.isValid()) return;
100105
if (editor.isDisposed() || isMainEditor && FileEditorManager.getInstance(project).getSelectedTextEditor() != editor) return;
101106
if (ApplicationManager.getApplication().isWriteAccessAllowed()) return; //it will fail anyway
@@ -152,9 +157,16 @@ private static void finishAutopopupCompletion(Editor editor, boolean neglectLook
152157
}
153158

154159
final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
155-
if (currentCompletion != null) {
156-
currentCompletion.closeAndFinish(true);
160+
if (CompletionServiceImpl.isPhase(CompletionPhase.autoPopupAlarm, CompletionPhase.emptyAutoPopup, CompletionPhase.possiblyDisturbingAutoPopup)) {
161+
CompletionServiceImpl.setCompletionPhase(CompletionPhase.noCompletion);
162+
assert currentCompletion == null;
163+
} else {
164+
if (currentCompletion != null) {
165+
currentCompletion.closeAndFinish(true);
166+
}
167+
CompletionServiceImpl.assertPhase(CompletionPhase.noCompletion);
157168
}
169+
158170
state.stopAutoPopup();
159171
}
160172

0 commit comments

Comments
 (0)