diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index e766c09ef526..44e4d5f6e24a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -76,25 +76,14 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement private final CodeCompletionHandlerBase myHandler; private final LookupImpl myLookup; private final MergingUpdateQueue myQueue; - private boolean myDisposed; - private boolean myShownLookup; - private volatile int myCount; private final Update myUpdate = new Update("update") { public void run() { updateLookup(); myQueue.setMergingTimeSpan(100); } }; - private LightweightHint myHint; private final Semaphore myFreezeSemaphore; - private Boolean myToRestart; - private boolean myRestartScheduled; - - private boolean myModifiersReleased; - - private Runnable myRestorePrefix; - private boolean myBackgrounded; - private OffsetMap myOffsetMap; + private final OffsetMap myOffsetMap; private final CopyOnWriteArrayList>> myRestartingPrefixConditions = ContainerUtil.createEmptyCOWList(); private final LookupAdapter myLookupListener = new LookupAdapter() { public void itemSelected(LookupEvent event) { @@ -117,7 +106,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } }; private final Semaphore myDuringCompletionSemaphore = new Semaphore(); - private volatile boolean myFocusLookupWhenDone; + private final CompletionState myState; public CompletionProgressIndicator(final Editor editor, CompletionParameters parameters, CodeCompletionHandlerBase handler, Semaphore freezeSemaphore, final OffsetMap offsetMap, LookupImpl lookup) { @@ -129,7 +118,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement myLookup = lookup; myLookup.setArranger(new CompletionLookupArranger(parameters)); - myShownLookup = lookup.isShown(); + myState = new CompletionState(lookup.isShown()); myLookup.addLookupListener(myLookupListener); myLookup.setCalculating(true); @@ -157,13 +146,11 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } void notifyBackgrounded() { - ApplicationManager.getApplication().assertIsDispatchThread(); - myBackgrounded = true; + myState.setBackgrounded(); } boolean isBackgrounded() { - ApplicationManager.getApplication().assertIsDispatchThread(); - return myBackgrounded; + return myState.isBackgrounded(); } void duringCompletion(CompletionInitializationContext initContext) { @@ -204,7 +191,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void setFocusLookupWhenDone(boolean focusLookup) { - myFocusLookupWhenDone = focusLookup; + myState.setFocusLookupWhenDone(focusLookup); if (!focusLookup && isAutopopupCompletion()) { myLookup.setAdvertisementText("Press " + CompletionContributor.getActionShortcut(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE) + " to choose the first suggestion"); } @@ -258,7 +245,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement if (isOutdated()) { return; } - if (isAutopopupCompletion() && !myShownLookup) { + if (isAutopopupCompletion() && !myState.isShownLookup()) { return; } if (!isBackgrounded()) { @@ -275,11 +262,11 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } private boolean isOutdated() { - if (!myDisposed) { + if (!myState.isCompletionDisposed()) { CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); LOG.assertTrue(this == current, current + " != " + this); } - return myDisposed || myEditor.isDisposed() || getProject().isDisposed(); + return myState.isCompletionDisposed() || myEditor.isDisposed() || getProject().isDisposed(); } private void trackModifiers() { @@ -300,8 +287,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement private void processModifier(KeyEvent e) { final int code = e.getKeyCode(); if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_META || code == KeyEvent.VK_ALT || code == KeyEvent.VK_SHIFT) { - myModifiersReleased = true; - if (myRestorePrefix != null) { + myState.setModifiersReleased(true); + if (myState.isWaitingAfterAutoInsertion()) { cleanup(); } contentComponent.removeKeyListener(this); @@ -331,14 +318,14 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void liveAfterDeath(@Nullable final LightweightHint hint) { - LOG.assertTrue(myDisposed); + myState.assertDisposed(); - if (myModifiersReleased || ApplicationManager.getApplication().isUnitTestMode()) { + if (myState.isModifiersReleased() || ApplicationManager.getApplication().isUnitTestMode()) { return; } registerItself(); - myHint = hint; + myState.setCompletionHint(hint); if (hint != null) { hint.addHintListener(new HintListener() { public void hintHidden(final EventObject event) { @@ -383,11 +370,11 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement ApplicationManager.getApplication().assertIsDispatchThread(); if (isOutdated()) return; - if (!myShownLookup) { + if (!myState.isShownLookup()) { if (hideAutopopupIfMeaningless()) { return; } - myShownLookup = true; + myState.setShownLookup(true); if (StringUtil.isEmpty(myLookup.getAdvertisementText()) && !isAutopopupCompletion()) { final String text = DefaultCompletionContributor.getDefaultAdvertisementText(myParameters); @@ -422,10 +409,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } myLookup.addItem(item); - myCount++; + final int count = myState.incCount(); if (unitTestMode) return; - if (myCount == 1) { + if (count == 1) { ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { try { @@ -444,8 +431,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement public void closeAndFinish(boolean hideLookup) { LOG.assertTrue(this == CompletionServiceImpl.getCompletionService().getCurrentCompletion()); - if (myHint != null) { - myHint.hide(); + if (myState.getCompletionHint() != null) { + myState.getCompletionHint().hide(); } Lookup lookup = LookupManager.getActiveLookup(myEditor); @@ -458,16 +445,15 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement LookupManager.getInstance(getProject()).hideActiveLookup(); } } else { - LOG.assertTrue(myDisposed); + myState.assertDisposed(); } } private void finishCompletionProcess() { - myToRestart = false; + myState.setToRestart(false); cancel(); - LOG.assertTrue(!myDisposed); - myDisposed = true; + myState.setCompletionDisposed(true); ApplicationManager.getApplication().assertIsDispatchThread(); Disposer.dispose(myQueue); @@ -483,10 +469,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } private void cleanup() { - ApplicationManager.getApplication().assertIsDispatchThread(); - LOG.assertTrue(myDisposed); - myHint = null; - myRestorePrefix = null; + myState.handleDeath(); unregisterItself(); } @@ -504,7 +487,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement public void run() { if (isOutdated()) return; if (!isBackgrounded()) return; - if (isCanceled() && !myRestartScheduled) return; + if (isCanceled() && !myState.isRestartScheduled()) return; myLookup.setCalculating(false); @@ -512,7 +495,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement return; } - if (myCount == 0) { + if (myState.hasNoVariants()) { LookupManager.getInstance(getProject()).hideActiveLookup(); final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); @@ -523,7 +506,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } else { - if (myFocusLookupWhenDone) { + if (myState.isFocusLookupWhenDone()) { myLookup.setFocused(true); } updateLookup(); @@ -554,12 +537,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void cancelByWriteAction() { - if (myToRestart != null) { - LOG.assertTrue(myToRestart == Boolean.FALSE); //explicit completionFinished was invoked before this write action - return; - } - - myToRestart = true; + myState.setToRestart(true); cancel(); scheduleRestart(); @@ -594,11 +572,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement protected void run(Result result) throws Throwable { setMergeCommand(); - if (myRestorePrefix != null) { - myRestorePrefix.run(); - myRestorePrefix = null; - } - + myState.restorePrefix(); getLookup().restorePrefix(); } }.execute(); @@ -610,8 +584,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void rememberDocumentState() { - LOG.assertTrue(myDisposed); - if (myModifiersReleased) { + myState.assertDisposed(); + if (myState.isModifiersReleased()) { return; } @@ -620,7 +594,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement final int selStart = myEditor.getSelectionModel().getSelectionStart(); final int selEnd = myEditor.getSelectionModel().getSelectionEnd(); - myRestorePrefix = new Runnable() { + myState.setRestorePrefix(new Runnable() { @Override public void run() { DocumentEx document = (DocumentEx) myEditor.getDocument(); @@ -635,7 +609,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement document.setInBulkUpdate(false); } } - }; + }); } public boolean isRepeatedInvocation(CompletionType completionType, Editor editor) { @@ -667,7 +641,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void prefixUpdated() { - if (myToRestart == Boolean.TRUE) { + if (myState.isToRestart()) { scheduleRestart(); return; } @@ -688,9 +662,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void scheduleRestart() { - myRestartScheduled = true; - - ApplicationManager.getApplication().assertIsDispatchThread(); + myState.setRestartScheduled(true); final Project project = getProject(); ApplicationManager.getApplication().invokeLater(new Runnable() { @@ -712,4 +684,9 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } }); } + + @Override + public String toString() { + return myState.toString(); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionState.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionState.java new file mode 100644 index 000000000000..f7f5ab27733c --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionState.java @@ -0,0 +1,152 @@ +package com.intellij.codeInsight.completion; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.ui.LightweightHint; + +/** + * @author peter + */ +public class CompletionState { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CompletionState"); + private boolean myCompletionDisposed; + private boolean myShownLookup; + private LightweightHint myCompletionHint; + private Boolean myToRestart; + private boolean myRestartScheduled; + private boolean myModifiersReleased; + private Runnable myRestorePrefix; + private boolean myBackgrounded; + private volatile boolean myFocusLookupWhenDone; + private volatile int myCount; + + public CompletionState(boolean shownLookup) { + myShownLookup = shownLookup; + } + + public boolean isCompletionDisposed() { + return myCompletionDisposed; + } + + public void setCompletionDisposed(boolean completionDisposed) { + LOG.assertTrue(!myCompletionDisposed); + myCompletionDisposed = completionDisposed; + } + + public boolean isShownLookup() { + return myShownLookup; + } + + public void setShownLookup(boolean shownLookup) { + myShownLookup = shownLookup; + } + + public LightweightHint getCompletionHint() { + return myCompletionHint; + } + + public void setCompletionHint(LightweightHint completionHint) { + myCompletionHint = completionHint; + } + + public boolean isToRestart() { + return myToRestart == Boolean.TRUE; + } + + public void setToRestart(boolean toRestart) { + if (toRestart) { + if (myToRestart != null) { + LOG.assertTrue(myToRestart == Boolean.FALSE); //explicit completionFinished was invoked before this write action + return; + } + } + + myToRestart = toRestart; + } + + public boolean isRestartScheduled() { + return myRestartScheduled; + } + + public void setRestartScheduled(boolean restartScheduled) { + ApplicationManager.getApplication().assertIsDispatchThread(); + + myRestartScheduled = restartScheduled; + } + + public boolean isModifiersReleased() { + return myModifiersReleased; + } + + public void setModifiersReleased(boolean modifiersReleased) { + myModifiersReleased = modifiersReleased; + } + + public boolean isWaitingAfterAutoInsertion() { + return myRestorePrefix != null; + } + + public void setRestorePrefix(Runnable restorePrefix) { + myRestorePrefix = restorePrefix; + } + + public boolean isBackgrounded() { + ApplicationManager.getApplication().assertIsDispatchThread(); + return myBackgrounded; + } + + public void setBackgrounded() { + ApplicationManager.getApplication().assertIsDispatchThread(); + myBackgrounded = true; + } + + public boolean isFocusLookupWhenDone() { + return myFocusLookupWhenDone; + } + + public void setFocusLookupWhenDone(boolean focusLookupWhenDone) { + myFocusLookupWhenDone = focusLookupWhenDone; + } + + public void assertDisposed() { + LOG.assertTrue(myCompletionDisposed); + } + + public void restorePrefix() { + if (myRestorePrefix != null) { + myRestorePrefix.run(); + myRestorePrefix = null; + } + } + + public void handleDeath() { + ApplicationManager.getApplication().assertIsDispatchThread(); + assertDisposed(); + setCompletionHint(null); + setRestorePrefix(null); + } + + int incCount() { + return ++myCount; + } + + boolean hasNoVariants() { + return myCount == 0; + } + + @Override + public String toString() { + return "CompletionState{" + + "myCompletionDisposed=" + myCompletionDisposed + + ", myShownLookup=" + myShownLookup + + ", myCompletionHint=" + myCompletionHint + + ", myToRestart=" + myToRestart + + ", myRestartScheduled=" + myRestartScheduled + + ", myModifiersReleased=" + myModifiersReleased + + ", myRestorePrefix=" + myRestorePrefix + + ", myBackgrounded=" + myBackgrounded + + ", myFocusLookupWhenDone=" + myFocusLookupWhenDone + + ", myCount=" + myCount + + '}'; + } +}