下面列出了怎么用 com.intellij.codeInsight.completion.impl.CompletionServiceImpl 的API类实例代码及写法,或者点击链接到github查看源代码。
private void scheduleContributorsAfterAsyncCommit(CompletionInitializationContextImpl initContext, CompletionProgressIndicator indicator, OffsetsInFile hostCopyOffsets, boolean hasModifiers) {
CompletionPhase phase;
if (synchronous) {
phase = new CompletionPhase.BgCalculation(indicator);
indicator.makeSureLookupIsShown(0);
}
else {
phase = new CompletionPhase.CommittingDocuments(indicator, InjectedLanguageUtil.getTopLevelEditor(indicator.getEditor()));
}
CompletionServiceImpl.setCompletionPhase(phase);
AppUIExecutor.onUiThread().withDocumentsCommitted(initContext.getProject()).expireWith(phase).execute(() -> {
if (phase instanceof CompletionPhase.CommittingDocuments) {
((CompletionPhase.CommittingDocuments)phase).replaced = true;
}
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.BgCalculation(indicator));
startContributorThread(initContext, indicator, hostCopyOffsets, hasModifiers);
});
}
private void finishCompletionProcess(boolean disposeOffsetMap) {
cancel();
ApplicationManager.getApplication().assertIsDispatchThread();
Disposer.dispose(myQueue);
LookupManager.getInstance(getProject()).removePropertyChangeListener(myLookupManagerListener);
CompletionServiceImpl.assertPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class, CompletionPhase.Synchronous.class, CompletionPhase.CommittingDocuments.class);
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
LOG.assertTrue(currentCompletion == this, currentCompletion + "!=" + this);
CompletionPhase oldPhase = CompletionServiceImpl.getCompletionPhase();
if (oldPhase instanceof CompletionPhase.CommittingDocuments) {
LOG.assertTrue(((CompletionPhase.CommittingDocuments)oldPhase).indicator != null, oldPhase);
((CompletionPhase.CommittingDocuments)oldPhase).replaced = true;
}
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
if (disposeOffsetMap) {
disposeIndicator();
}
}
@TestOnly
public static void cleanupForNextTest() {
CompletionService completionService = ServiceManager.getService(CompletionService.class);
if (!(completionService instanceof CompletionServiceImpl)) {
return;
}
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
if (currentCompletion != null) {
currentCompletion.finishCompletionProcess(true);
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
}
else {
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
}
StatisticsUpdate.cancelLastCompletionStatisticsUpdate();
}
private boolean hideAutopopupIfMeaningless() {
if (!myLookup.isLookupDisposed() && isAutopopupCompletion() && !myLookup.isSelectionTouched() && !myLookup.isCalculating()) {
myLookup.refreshUi(true, false);
final List<LookupElement> items = myLookup.getItems();
for (LookupElement item : items) {
if (!isAlreadyInTheEditor(item)) {
return false;
}
if (item.isValid() && item.isWorthShowingInAutoPopup()) {
return false;
}
}
myLookup.hideLookup(false);
LOG.assertTrue(CompletionServiceImpl.getCompletionService().getCurrentCompletion() == null);
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
return true;
}
return false;
}
@Override
public void scheduleRestart() {
ApplicationManager.getApplication().assertIsDispatchThread();
/*if (myHandler.isTestingMode() && !TestModeFlags.is(CompletionAutoPopupHandler.ourTestingAutopopup)) {
closeAndFinish(false);
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
new CodeCompletionHandlerBase(myCompletionType, false, false, true).invokeCompletion(getProject(), myEditor, myInvocationCount);
return;
}*/
cancel();
final CompletionProgressIndicator current = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
if (this != current) {
LOG.error(current + "!=" + this);
}
hideAutopopupIfMeaningless();
CompletionPhase oldPhase = CompletionServiceImpl.getCompletionPhase();
if (oldPhase instanceof CompletionPhase.CommittingDocuments) {
((CompletionPhase.CommittingDocuments)oldPhase).replaced = true;
}
CompletionPhase.CommittingDocuments.scheduleAsyncCompletion(myEditor, myCompletionType, null, getProject(), this);
}
void handleEmptyLookup(boolean awaitSecondInvocation) {
if (isAutopopupCompletion() && ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
LOG.assertTrue(!isAutopopupCompletion());
CompletionParameters parameters = getParameters();
if (myHandler.invokedExplicitly && parameters != null) {
LightweightHint hint = showErrorHint(getProject(), getEditor(), getNoSuggestionsMessage(parameters));
if (awaitSecondInvocation) {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.NoSuggestionsHint(hint, this));
return;
}
}
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
}
private List<LookupElement> getExactMatches(List<? extends LookupElement> items) {
String selectedText = InjectedLanguageUtil.getTopLevelEditor(myProcess.getParameters().getEditor()).getSelectionModel().getSelectedText();
List<LookupElement> exactMatches = new SmartList<>();
for (int i = 0; i < items.size(); i++) {
LookupElement item = items.get(i);
boolean isSuddenLiveTemplate = isSuddenLiveTemplate(item);
if (isPrefixItem(item, true) && !isSuddenLiveTemplate || item.getLookupString().equals(selectedText)) {
if (item instanceof LiveTemplateLookupElement) {
// prefer most recent live template lookup item
return Collections.singletonList(item);
}
exactMatches.add(item);
}
else if (i == 0 && isSuddenLiveTemplate && items.size() > 1 && !CompletionServiceImpl.isStartMatch(items.get(1), this)) {
return Collections.singletonList(item);
}
}
return exactMatches;
}
@Nonnull
@Override
public Result checkAutoPopup(char charTyped, @Nonnull final Project project, @Nonnull final Editor editor, @Nonnull final PsiFile file) {
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (LOG.isDebugEnabled()) {
LOG.debug("checkAutoPopup: character=" + charTyped + ";");
LOG.debug("phase=" + CompletionServiceImpl.getCompletionPhase());
LOG.debug("lookup=" + lookup);
LOG.debug("currentCompletion=" + CompletionServiceImpl.getCompletionService().getCurrentCompletion());
}
if (lookup != null) {
if (editor.getSelectionModel().hasSelection()) {
lookup.performGuardedChange(() -> EditorModificationUtil.deleteSelectedText(editor));
}
return Result.STOP;
}
if (Character.isLetterOrDigit(charTyped) || charTyped == '_') {
AutoPopupController.getInstance(project).scheduleAutoPopup(editor);
return Result.STOP;
}
return Result.CONTINUE;
}
@Override
public Pair<List<LookupElement>, Integer> arrangeItems(@Nonnull Lookup lookup, boolean onExplicitAction) {
LinkedHashSet<LookupElement> result = new LinkedHashSet<>();
result.addAll(getPrefixItems(true));
result.addAll(getPrefixItems(false));
List<LookupElement> items = getMatchingItems();
for (LookupElement item : items) {
if (CompletionServiceImpl.isStartMatch(item, this)) {
result.add(item);
}
}
result.addAll(items);
ArrayList<LookupElement> list = new ArrayList<>(result);
int selected = !lookup.isSelectionTouched() && onExplicitAction ? 0 : list.indexOf(lookup.getCurrentItem());
return new Pair<>(list, selected >= 0 ? selected : 0);
}
@Override
public void scheduleAutoPopup(@Nonnull Editor editor, @Nonnull CompletionType completionType, @Nullable final Condition<? super PsiFile> condition) {
//if (ApplicationManager.getApplication().isUnitTestMode() && !TestModeFlags.is(CompletionAutoPopupHandler.ourTestingAutopopup)) {
// return;
//}
boolean alwaysAutoPopup = Boolean.TRUE.equals(editor.getUserData(ALWAYS_AUTO_POPUP));
if (!CodeInsightSettings.getInstance().AUTO_POPUP_COMPLETION_LOOKUP && !alwaysAutoPopup) {
return;
}
if (PowerSaveMode.isEnabled()) {
return;
}
if (!CompletionServiceImpl.isPhase(CompletionPhase.CommittingDocuments.class, CompletionPhase.NoCompletion.getClass())) {
return;
}
final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
if (currentCompletion != null) {
currentCompletion.closeAndFinish(true);
}
CompletionPhase.CommittingDocuments.scheduleAsyncCompletion(editor, completionType, condition, myProject, null);
}
/**
* PhpTypedHandler.scheduleAutoPopup but use SMART since BASIC is blocked
*/
public void scheduleAutoPopup(final Project project, final Editor editor, @Nullable final Condition<PsiFile> condition) {
if (ApplicationManager.getApplication().isUnitTestMode()/* && !CompletionAutoPopupHandler.ourTestingAutopopup*/) {
return;
}
if (!CodeInsightSettings.getInstance().AUTO_POPUP_COMPLETION_LOOKUP) {
return;
}
if (PowerSaveMode.isEnabled()) {
return;
}
if (!CompletionServiceImpl.isPhase(CompletionPhase.CommittingDocuments.class, CompletionPhase.NoCompletion.getClass())) {
return;
}
//
// final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
// if (currentCompletion != null) {
// currentCompletion.closeAndFinish(true);
// }
//
// final CompletionPhase.CommittingDocuments phase = new CompletionPhase.CommittingDocuments(null, editor);
// CompletionServiceImpl.setCompletionPhase(phase);
//
// CompletionAutoPopupHandler.runLaterWithCommitted(project, editor.getDocument(), new Runnable() {
// @Override
// public void run() {
// CompletionAutoPopupHandler.invokeCompletion(CompletionType.BASIC, true, project, editor, 0, false);
// }
// });
}
@Override
public int newCompletionStarted(int time, boolean repeated) {
CompletionServiceImpl.setCompletionPhase(NoCompletion);
if (repeated) {
indicator.restorePrefix(restorePrefix);
}
return indicator.nextInvocationCount(time, repeated);
}
private void trySynchronousCompletion(CompletionInitializationContextImpl initContext,
boolean hasModifiers,
long startingTime,
CompletionProgressIndicator indicator,
OffsetsInFile hostCopyOffsets) {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.Synchronous(indicator));
Future<?> future = startContributorThread(initContext, indicator, hostCopyOffsets, hasModifiers);
if (future == null) {
return;
}
int timeout = calcSyncTimeOut(startingTime);
indicator.makeSureLookupIsShown(timeout);
if (indicator.blockingWaitForFinish(timeout)) {
checkForExceptions(future);
try {
indicator.getLookup().refreshUi(true, false);
completionFinished(indicator, hasModifiers);
}
catch (Throwable e) {
indicator.closeAndFinish(true);
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
LOG.error(e);
}
return;
}
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.BgCalculation(indicator));
indicator.showLookup();
}
CompletionProgressIndicator(Editor editor, @Nonnull Caret caret, int invocationCount,
CodeCompletionHandlerBase handler, @Nonnull OffsetMap offsetMap, @Nonnull OffsetsInFile hostOffsets,
boolean hasModifiers, @Nonnull LookupImpl lookup) {
myEditor = editor;
myCaret = caret;
myHandler = handler;
myCompletionType = handler.completionType;
myInvocationCount = invocationCount;
myOffsetMap = offsetMap;
myHostOffsets = hostOffsets;
myLookup = lookup;
myStartCaret = myEditor.getCaretModel().getOffset();
myThreading = ApplicationManager.getApplication().isWriteAccessAllowed() || myHandler.isTestingCompletionQualityMode() ? new SyncCompletion() : new AsyncCompletion();
myAdvertiserChanges.offer(() -> myLookup.getAdvertiser().clearAdvertisements());
myArranger = new CompletionLookupArrangerImpl(this);
myLookup.setArranger(myArranger);
myLookup.addLookupListener(myLookupListener);
myLookup.setCalculating(true);
myLookupManagerListener = evt -> {
if (evt.getNewValue() != null) {
LOG.error("An attempt to change the lookup during completion, phase = " + CompletionServiceImpl.getCompletionPhase());
}
};
LookupManager.getInstance(getProject()).addPropertyChangeListener(myLookupManagerListener);
myQueue = new MergingUpdateQueue("completion lookup progress", ourShowPopupAfterFirstItemGroupingTime, true, myEditor.getContentComponent());
myQueue.setPassThrough(false);
ApplicationManager.getApplication().assertIsDispatchThread();
if (hasModifiers && !ApplicationManager.getApplication().isUnitTestMode()) {
trackModifiers();
}
}
public void closeAndFinish(boolean hideLookup) {
if (!myLookup.isLookupDisposed()) {
Lookup lookup = LookupManager.getActiveLookup(myEditor);
LOG.assertTrue(lookup == myLookup, "lookup changed: " + lookup + "; " + this);
}
myLookup.removeLookupListener(myLookupListener);
finishCompletionProcess(true);
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
if (hideLookup) {
myLookup.hideLookup(true);
}
}
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) {
myContentComponent.removeKeyListener(this);
final CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
if (phase instanceof CompletionPhase.BgCalculation) {
((CompletionPhase.BgCalculation)phase).modifiersChanged = true;
}
else if (phase instanceof CompletionPhase.InsertedSingleItem) {
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
}
}
}
static void truncatePrefix(final DataContext dataContext, LookupImpl lookup, final EditorActionHandler handler, final int hideOffset, final Caret caret) {
final Editor editor = lookup.getEditor();
if (!lookup.performGuardedChange(() -> handler.execute(editor, caret, dataContext))) {
return;
}
final CompletionProgressIndicator process = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
lookup.truncatePrefix(process == null || !process.isAutopopupCompletion(), hideOffset);
}
@Override
public void execute(@Nonnull Editor originalEditor, char charTyped, @Nonnull DataContext dataContext) {
final Project project = dataContext.getData(CommonDataKeys.PROJECT);
PsiFile file = project == null ? null : PsiUtilBase.getPsiFileInEditor(originalEditor, project);
if (file == null) {
if (myOriginalHandler != null) {
myOriginalHandler.execute(originalEditor, charTyped, dataContext);
}
return;
}
if (!EditorModificationUtil.checkModificationAllowed(originalEditor)) {
return;
}
CompletionPhase oldPhase = CompletionServiceImpl.getCompletionPhase();
if (oldPhase instanceof CompletionPhase.CommittingDocuments && oldPhase.indicator != null) {
oldPhase.indicator.scheduleRestart();
}
Editor editor = TypedHandler.injectedEditorIfCharTypedIsSignificant(charTyped, originalEditor, file);
if (editor != originalEditor) {
file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
}
if (originalEditor.isInsertMode() && beforeCharTyped(charTyped, project, originalEditor, editor, file)) {
return;
}
if (myOriginalHandler != null) {
myOriginalHandler.execute(originalEditor, charTyped, dataContext);
}
}
public static void performCompletion(@NotNull final String path,
@Nullable final String fileContent,
final int line,
final int column,
@NotNull final CompletionCallback completionCallback) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
final PsiFile targetPsiFile = findTargetFile(path);
final VirtualFile targetVirtualFile = targetPsiFile != null ? targetPsiFile.getVirtualFile() : null;
if (targetPsiFile != null && targetVirtualFile != null) {
final EditorFactory editorFactory = EditorFactory.getInstance();
final Project project = targetPsiFile.getProject();
final Document originalDocument = PsiDocumentManager.getInstance(project).getDocument(targetPsiFile);
if (originalDocument != null) {
PsiFile fileCopy = fileContent != null
? createDummyPsiFile(project, fileContent, targetPsiFile)
: createDummyPsiFile(project, targetPsiFile.getText(), targetPsiFile);
final Document document = fileCopy.getViewProvider().getDocument();
if (document != null) {
final Editor editor = editorFactory.createEditor(document, project, targetVirtualFile, false);
int offset = lineAndColumnToOffset(document, line, column);
editor.getCaretModel().moveToOffset(offset);
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
final CodeCompletionHandlerBase handler = new CodeCompletionHandlerBase(CompletionType.BASIC) {
@Override
protected void completionFinished(@NotNull CompletionProgressIndicator indicator,
boolean hasModifiers) {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated(indicator));
completionCallback.completionFinished(indicator.getParameters(), indicator, document);
}
};
handler.invokeCompletion(project, editor);
}
}, null, null);
}
}
}
}
});
}
private boolean isExpired() {
return CompletionServiceImpl.getCompletionPhase() != this || myTracker.hasAnythingHappened();
}
public static void scheduleAsyncCompletion(@Nonnull Editor _editor,
@Nonnull CompletionType completionType,
@Nullable Condition<? super PsiFile> condition,
@Nonnull Project project,
@Nullable CompletionProgressIndicator prevIndicator) {
Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(_editor);
int offset = topLevelEditor.getCaretModel().getOffset();
CommittingDocuments phase = new CommittingDocuments(prevIndicator, topLevelEditor);
CompletionServiceImpl.setCompletionPhase(phase);
phase.ignoreCurrentDocumentChange();
boolean autopopup = prevIndicator == null || prevIndicator.isAutopopupCompletion();
ReadAction.nonBlocking(() -> {
// retrieve the injected file from scratch since our typing might have destroyed the old one completely
PsiFile topLevelFile = PsiDocumentManager.getInstance(project).getPsiFile(topLevelEditor.getDocument());
Editor completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(topLevelEditor, topLevelFile, offset);
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(completionEditor.getDocument());
if (file == null || autopopup && shouldSkipAutoPopup(completionEditor, file) || condition != null && !condition.value(file)) {
return null;
}
loadContributorsOutsideEdt(completionEditor, file);
return completionEditor;
}).withDocumentsCommitted(project).expireWith(phase).expireWhen(() -> phase.isExpired()).finishOnUiThread(ModalityState.current(), completionEditor -> {
if (completionEditor != null) {
int time = prevIndicator == null ? 0 : prevIndicator.getInvocationCount();
CodeCompletionHandlerBase handler = CodeCompletionHandlerBase.createHandler(completionType, false, autopopup, false);
handler.invokeCompletion(project, completionEditor, time, false);
}
else if (phase == CompletionServiceImpl.getCompletionPhase()) {
CompletionServiceImpl.setCompletionPhase(NoCompletion);
}
}).submit(ourExecutor).onError(__ -> AppUIUtil.invokeOnEdt(() -> {
if (phase == CompletionServiceImpl.getCompletionPhase()) {
CompletionServiceImpl.setCompletionPhase(NoCompletion);
}
}));
}
@Override
public int newCompletionStarted(int time, boolean repeated) {
CompletionServiceImpl.assertPhase(NoCompletion.getClass()); // will fail and log valuable info
CompletionServiceImpl.setCompletionPhase(NoCompletion);
return time;
}
@Override
public int newCompletionStarted(int time, boolean repeated) {
CompletionServiceImpl.setCompletionPhase(NoCompletion);
return indicator.nextInvocationCount(time, repeated);
}
private void invokeCompletion(@Nonnull Project project, @Nonnull Editor editor, int time, boolean hasModifiers, @Nonnull Caret caret) {
markCaretAsProcessed(caret);
if (invokedExplicitly) {
StatisticsUpdate.applyLastCompletionStatisticsUpdate();
}
checkNoWriteAccess();
CompletionAssertions.checkEditorValid(editor);
int offset = editor.getCaretModel().getOffset();
if (editor.isViewer() || editor.getDocument().getRangeGuard(offset, offset) != null) {
editor.getDocument().fireReadOnlyModificationAttempt();
EditorModificationUtil.checkModificationAllowed(editor);
return;
}
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) {
return;
}
CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
boolean repeated = phase.indicator != null && phase.indicator.isRepeatedInvocation(completionType, editor);
final int newTime = phase.newCompletionStarted(time, repeated);
if (invokedExplicitly) {
time = newTime;
}
final int invocationCount = time;
if (CompletionServiceImpl.isPhase(CompletionPhase.InsertedSingleItem.class)) {
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
}
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass(), CompletionPhase.CommittingDocuments.class);
if (invocationCount > 1 && completionType == CompletionType.BASIC) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.SECOND_BASIC_COMPLETION);
}
long startingTime = System.currentTimeMillis();
Runnable initCmd = () -> {
CompletionInitializationContextImpl context =
withTimeout(calcSyncTimeOut(startingTime), () -> CompletionInitializationUtil.createCompletionInitializationContext(project, editor, caret, invocationCount, completionType));
boolean hasValidContext = context != null;
if (!hasValidContext) {
final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(caret, project);
context = new CompletionInitializationContextImpl(editor, caret, psiFile, completionType, invocationCount);
}
doComplete(context, hasModifiers, hasValidContext, startingTime);
};
try {
if (autopopup) {
CommandProcessor.getInstance().runUndoTransparentAction(initCmd);
}
else {
CommandProcessor.getInstance().executeCommand(project, initCmd, null, null, editor.getDocument());
}
}
catch (IndexNotReadyException e) {
if (invokedExplicitly) {
DumbService.getInstance(project).showDumbModeNotification("Code completion is not available here while indices are being built");
}
}
}
private static void checkNotSync(CompletionProgressIndicator indicator, List<LookupElement> allItems) {
if (CompletionServiceImpl.isPhase(CompletionPhase.Synchronous.class)) {
LOG.error("sync phase survived: " + allItems + "; indicator=" + CompletionServiceImpl.getCompletionPhase().indicator + "; myIndicator=" + indicator);
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
}
}
protected void completionFinished(final CompletionProgressIndicator indicator, boolean hasModifiers) {
List<LookupElement> items = indicator.getLookup().getItems();
if (items.isEmpty()) {
LookupManager.hideActiveLookup(indicator.getProject());
Caret nextCaret = getNextCaretToProcess(indicator.getEditor());
if (nextCaret != null) {
invokeCompletion(indicator.getProject(), indicator.getEditor(), indicator.getInvocationCount(), hasModifiers, nextCaret);
}
else {
indicator.handleEmptyLookup(true);
checkNotSync(indicator, items);
}
return;
}
LOG.assertTrue(!indicator.isRunning(), "running");
LOG.assertTrue(!indicator.isCanceled(), "canceled");
try {
CompletionParameters parameters = indicator.getParameters();
AutoCompletionDecision decision = parameters == null ? AutoCompletionDecision.CLOSE_LOOKUP : shouldAutoComplete(indicator, items, parameters);
if (decision == AutoCompletionDecision.SHOW_LOOKUP) {
indicator.getLookup().setCalculating(false);
indicator.showLookup();
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated(indicator));
}
else if (decision instanceof AutoCompletionDecision.InsertItem) {
final Runnable restorePrefix = rememberDocumentState(indicator.getEditor());
final LookupElement item = ((AutoCompletionDecision.InsertItem)decision).getElement();
CommandProcessor.getInstance().executeCommand(indicator.getProject(), () -> {
indicator.setMergeCommand();
indicator.getLookup().finishLookup(Lookup.AUTO_INSERT_SELECT_CHAR, item);
}, "Autocompletion", null);
// the insert handler may have started a live template with completion
if (CompletionService.getCompletionService().getCurrentCompletion() == null &&
// ...or scheduled another autopopup
!CompletionServiceImpl.isPhase(CompletionPhase.CommittingDocuments.class)) {
CompletionServiceImpl.setCompletionPhase(hasModifiers ? new CompletionPhase.InsertedSingleItem(indicator, restorePrefix) : CompletionPhase.NoCompletion);
}
}
else if (decision == AutoCompletionDecision.CLOSE_LOOKUP) {
LookupManager.hideActiveLookup(indicator.getProject());
}
}
catch (Throwable e) {
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
LOG.error(e);
}
finally {
checkNotSync(indicator, items);
}
}
private boolean isOutdated() {
return CompletionServiceImpl.getCompletionPhase().indicator != this;
}
@Override
public void stop() {
super.stop();
myQueue.cancelAllUpdates();
myFreezeSemaphore.up();
myFinishSemaphore.up();
GuiUtils.invokeLaterIfNeeded(() -> {
final CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
if (!(phase instanceof CompletionPhase.BgCalculation) || phase.indicator != this) return;
LOG.assertTrue(!getProject().isDisposed(), "project disposed");
if (myEditor.isDisposed()) {
myLookup.hideLookup(false);
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
return;
}
if (myEditor instanceof EditorWindow) {
LOG.assertTrue(((EditorWindow)myEditor).getInjectedFile().isValid(), "injected file !valid");
LOG.assertTrue(((DocumentWindow)myEditor.getDocument()).isValid(), "docWindow !valid");
}
PsiFile file = myLookup.getPsiFile();
LOG.assertTrue(file == null || file.isValid(), "file !valid");
myLookup.setCalculating(false);
if (myCount == 0) {
myLookup.hideLookup(false);
if (!isAutopopupCompletion()) {
final CompletionProgressIndicator current = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
LOG.assertTrue(current == null, current + "!=" + this);
handleEmptyLookup(!((CompletionPhase.BgCalculation)phase).modifiersChanged);
}
}
else {
updateLookup(myIsUpdateSuppressed);
if (CompletionServiceImpl.getCompletionPhase() != CompletionPhase.NoCompletion) {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated(this));
}
}
}, myQueue.getModalityState());
}
@Override
public String toString() {
return "CompletionProgressIndicator[count=" + myCount + ",phase=" + CompletionServiceImpl.getCompletionPhase() + "]@" + System.identityHashCode(this);
}
@Override
protected void executeInLookup(LookupImpl lookup, DataContext context, final Caret caret) {
final Editor editor = lookup.getEditor();
final int offset = editor.getCaretModel().getOffset();
final CharSequence seq = editor.getDocument().getCharsSequence();
if (seq.length() <= offset || !lookup.isCompletion()) {
myOriginalHandler.execute(editor, caret, context);
return;
}
char c = seq.charAt(offset);
CharFilter.Result lookupAction = LookupTypedHandler.getLookupAction(c, lookup);
if (lookupAction != CharFilter.Result.ADD_TO_PREFIX || Character.isWhitespace(c)) {
myOriginalHandler.execute(editor, caret, context);
return;
}
if (!lookup.performGuardedChange(() -> {
CaretAction action = lookupCaret -> {
lookupCaret.removeSelection();
int caretOffset = lookupCaret.getOffset();
if (caretOffset < seq.length()) {
lookupCaret.moveToOffset(caretOffset + 1);
}
};
if (caret == null) {
editor.getCaretModel().runForEachCaret(action);
}
else {
action.perform(caret);
}
})) {
return;
}
lookup.fireBeforeAppendPrefix(c);
lookup.appendPrefix(c);
final CompletionProgressIndicator completion = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
if (completion != null) {
completion.prefixUpdated();
}
}