From 7f83ede73ba34047d580e50524dbd7e1130492ec Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 25 Jan 2018 09:47:09 +0100 Subject: [PATCH] while collecting completion variants, don't depend on global state containing CompletionProgressIndicator --- .../completion/CompletionParameters.java | 18 +++++++--- .../completion/CodeCompletionHandlerBase.java | 34 +++++------------- .../CompletionProgressIndicator.java | 36 +++++++++++-------- .../completion/CompletionThreadingBase.java | 14 ++++---- .../impl/CompletionServiceImpl.java | 24 ++++++------- 5 files changed, 59 insertions(+), 67 deletions(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java index 3a10434ca19b..75156b18b572 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,17 +32,20 @@ public final class CompletionParameters { @Nullable private final Editor myEditor; private final int myOffset; private final int myInvocationCount; + private final CompletionProcess myProcess; CompletionParameters(@NotNull final PsiElement position, @NotNull final PsiFile originalFile, - @NotNull CompletionType completionType, int offset, final int invocationCount, @Nullable Editor editor) { + @NotNull CompletionType completionType, int offset, int invocationCount, @Nullable Editor editor, + @NotNull CompletionProcess process) { + PsiUtilCore.ensureValid(position); assert position.getTextRange().containsOffset(offset) : position; myPosition = position; - assert position.isValid(); myOriginalFile = originalFile; myCompletionType = completionType; myOffset = offset; myInvocationCount = invocationCount; myEditor = editor; + myProcess = process; } @NotNull @@ -51,12 +55,12 @@ public final class CompletionParameters { @NotNull public CompletionParameters withType(@NotNull CompletionType type) { - return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myEditor); + return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myEditor, myProcess); } @NotNull public CompletionParameters withInvocationCount(int newCount) { - return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount, myEditor); + return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount, myEditor, myProcess); } @NotNull @@ -99,7 +103,7 @@ public final class CompletionParameters { @NotNull public CompletionParameters withPosition(@NotNull PsiElement element, int offset) { - return new CompletionParameters(element, myOriginalFile, myCompletionType, offset, myInvocationCount, myEditor); + return new CompletionParameters(element, myOriginalFile, myCompletionType, offset, myInvocationCount, myEditor, myProcess); } public boolean isExtendedCompletion() { @@ -124,4 +128,8 @@ public final class CompletionParameters { return myEditor != null; } + @NotNull + public CompletionProcess getProcess() { + return myProcess; + } } 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 c58da25e296d..58efe8555b27 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -75,7 +75,7 @@ public class CodeCompletionHandlerBase { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CodeCompletionHandlerBase"); private static final Key CARET_PROCESSED = Key.create("CodeCompletionHandlerBase.caretProcessed"); - @NotNull private final CompletionType myCompletionType; + @NotNull final CompletionType completionType; final boolean invokedExplicitly; final boolean synchronous; final boolean autopopup; @@ -97,7 +97,7 @@ public class CodeCompletionHandlerBase { } public CodeCompletionHandlerBase(@NotNull CompletionType completionType, boolean invokedExplicitly, boolean autopopup, boolean synchronous) { - myCompletionType = completionType; + this.completionType = completionType; this.invokedExplicitly = invokedExplicitly; this.autopopup = autopopup; this.synchronous = synchronous; @@ -151,7 +151,7 @@ public class CodeCompletionHandlerBase { } CompletionPhase phase = CompletionServiceImpl.getCompletionPhase(); - boolean repeated = phase.indicator != null && phase.indicator.isRepeatedInvocation(myCompletionType, editor); + boolean repeated = phase.indicator != null && phase.indicator.isRepeatedInvocation(completionType, editor); /* if (repeated && isAutocompleteCommonPrefixOnInvocation() && phase.fillInCommonPrefix()) { return; @@ -168,7 +168,7 @@ public class CodeCompletionHandlerBase { } CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass(), CompletionPhase.CommittingDocuments.class); - if (invocationCount > 1 && myCompletionType == CompletionType.BASIC) { + if (invocationCount > 1 && completionType == CompletionType.BASIC) { FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.SECOND_BASIC_COMPLETION); } @@ -206,7 +206,7 @@ public class CodeCompletionHandlerBase { private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount, @NotNull Caret caret) { final Ref current = Ref.create(null); - CompletionInitializationContext context = new CompletionInitializationContext(editor, caret, psiFile, myCompletionType, invocationCount) { + CompletionInitializationContext context = new CompletionInitializationContext(editor, caret, psiFile, completionType, invocationCount) { CompletionContributor dummyIdentifierChanger; @Override @@ -290,7 +290,6 @@ public class CodeCompletionHandlerBase { CompletionContext context = createCompletionContext(initContext.getFile(), hostCopyOffsets); LookupImpl lookup = obtainLookup(editor, initContext.getProject()); - CompletionParameters parameters = createCompletionParameters(invocationCount, context, editor); CompletionPhase phase = CompletionServiceImpl.getCompletionPhase(); if (phase instanceof CompletionPhase.CommittingDocuments) { @@ -302,9 +301,9 @@ public class CodeCompletionHandlerBase { CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass()); } - final CompletionProgressIndicator indicator = new CompletionProgressIndicator(editor, initContext.getCaret(), - parameters, this, - initContext.getOffsetMap(), hostOffsets, hasModifiers, lookup); + CompletionProgressIndicator indicator = new CompletionProgressIndicator(editor, initContext.getCaret(), + invocationCount, context, this, + initContext.getOffsetMap(), hostOffsets, hasModifiers, lookup); Disposer.register(indicator, hostCopyOffsets.getOffsets()); Disposer.register(indicator, context.getOffsetMap()); Disposer.register(indicator, translator); @@ -343,23 +342,6 @@ public class CodeCompletionHandlerBase { } } - private CompletionParameters createCompletionParameters(int invocationCount, - final CompletionContext newContext, Editor editor) { - final int offset = newContext.getStartOffset(); - final PsiFile fileCopy = newContext.file; - PsiFile originalFile = fileCopy.getOriginalFile(); - final PsiElement insertedElement = findCompletionPositionLeaf(newContext, offset, fileCopy, originalFile); - insertedElement.putUserData(CompletionContext.COMPLETION_CONTEXT_KEY, newContext); - return new CompletionParameters(insertedElement, originalFile, myCompletionType, offset, invocationCount, editor); - } - - @NotNull - private static PsiElement findCompletionPositionLeaf(CompletionContext newContext, int offset, PsiFile fileCopy, PsiFile originalFile) { - final PsiElement insertedElement = newContext.file.findElementAt(offset); - CompletionAssertions.assertCompletionPositionPsiConsistent(newContext, offset, fileCopy, originalFile, insertedElement); - return insertedElement; - } - private AutoCompletionDecision shouldAutoComplete(final CompletionProgressIndicator indicator, List items) { if (!invokedExplicitly) { return AutoCompletionDecision.SHOW_LOOKUP; 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 e00d6dc0ea54..ee80e2f7a8f9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -56,10 +56,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.ElementPattern; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiReference; -import com.intellij.psi.ReferenceRange; +import com.intellij.psi.*; import com.intellij.ui.GuiUtils; import com.intellij.ui.LightweightHint; import com.intellij.util.Alarm; @@ -136,26 +133,21 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement private final int myStartCaret; private CompletionThreadingBase myStrategy; - public CompletionProgressIndicator(final Editor editor, - @NotNull Caret caret, - CompletionParameters parameters, - CodeCompletionHandlerBase handler, - final OffsetMap offsetMap, - OffsetsInFile hostOffsets, - boolean hasModifiers, - LookupImpl lookup) { + CompletionProgressIndicator(Editor editor, @NotNull Caret caret, int invocationCount, CompletionContext context, + CodeCompletionHandlerBase handler, OffsetMap offsetMap, OffsetsInFile hostOffsets, + boolean hasModifiers, LookupImpl lookup) { myEditor = editor; myCaret = caret; - myParameters = parameters; myHandler = handler; myOffsetMap = offsetMap; myHostOffsets = hostOffsets; myLookup = lookup; myStartCaret = myEditor.getCaretModel().getOffset(); + myParameters = createCompletionParameters(invocationCount, context, editor); myAdvertiserChanges.offer(() -> myLookup.getAdvertiser().clearAdvertisements()); - myArranger = new CompletionLookupArranger(parameters, this); + myArranger = new CompletionLookupArranger(myParameters, this); myLookup.setArranger(myArranger); myLookup.addLookupListener(myLookupListener); @@ -178,6 +170,22 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } + private CompletionParameters createCompletionParameters(int invocationCount, CompletionContext context, Editor editor) { + int offset = context.getStartOffset(); + PsiFile fileCopy = context.file; + PsiFile originalFile = fileCopy.getOriginalFile(); + PsiElement insertedElement = findCompletionPositionLeaf(context, offset, fileCopy, originalFile); + insertedElement.putUserData(CompletionContext.COMPLETION_CONTEXT_KEY, context); + return new CompletionParameters(insertedElement, originalFile, myHandler.completionType, offset, invocationCount, editor, this); + } + + @NotNull + private static PsiElement findCompletionPositionLeaf(CompletionContext context, int offset, PsiFile fileCopy, PsiFile originalFile) { + PsiElement insertedElement = context.file.findElementAt(offset); + CompletionAssertions.assertCompletionPositionPsiConsistent(context, offset, fileCopy, originalFile, insertedElement); + return insertedElement; + } + public void itemSelected(@Nullable LookupElement lookupItem, char completionChar) { boolean dispose = lookupItem == null; finishCompletionProcess(dispose); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionThreadingBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionThreadingBase.java index 5fa3d569d7a2..4b7c6c5a284d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionThreadingBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionThreadingBase.java @@ -15,15 +15,15 @@ */ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; -import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; +import java.util.Objects; + public abstract class CompletionThreadingBase implements CompletionThreading { protected final static ThreadLocal ourIsInBatchUpdate = ThreadLocal.withInitial(() -> Boolean.FALSE); - public static void withBatchUpdate(Runnable runnable) { - if (ourIsInBatchUpdate.get().booleanValue()) { + public static void withBatchUpdate(Runnable runnable, CompletionProcess process) { + if (ourIsInBatchUpdate.get().booleanValue() || !(process instanceof CompletionProgressIndicator)) { runnable.run(); return; } @@ -32,10 +32,8 @@ public abstract class CompletionThreadingBase implements CompletionThreading { ourIsInBatchUpdate.set(Boolean.TRUE); runnable.run(); ProgressManager.checkCanceled(); - final CompletionProgressIndicator currentIndicator = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); - if(currentIndicator == null) throw new ProcessCanceledException(); - CompletionThreadingBase threading = currentIndicator.getCompletionThreading(); - assert threading != null; + CompletionProgressIndicator currentIndicator = (CompletionProgressIndicator)process; + CompletionThreadingBase threading = Objects.requireNonNull(currentIndicator.getCompletionThreading()); threading.flushBatchResult(currentIndicator); } finally { ourIsInBatchUpdate.set(Boolean.FALSE); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index 1f598bb40a92..bf393fd69674 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -110,13 +110,9 @@ public final class CompletionServiceImpl extends CompletionService { @Nullable private final CompletionResultSetImpl myOriginal; - - public CompletionResultSetImpl(final Consumer consumer, final int lengthOfTextBeforePosition, - final PrefixMatcher prefixMatcher, - CompletionContributor contributor, - CompletionParameters parameters, - @NotNull CompletionSorterImpl sorter, - @Nullable CompletionResultSetImpl original) { + CompletionResultSetImpl(Consumer consumer, int lengthOfTextBeforePosition, PrefixMatcher prefixMatcher, + CompletionContributor contributor, CompletionParameters parameters, + @NotNull CompletionSorterImpl sorter, @Nullable CompletionResultSetImpl original) { super(prefixMatcher, consumer, contributor); myLengthOfTextBeforePosition = lengthOfTextBeforePosition; myParameters = parameters; @@ -126,7 +122,7 @@ public final class CompletionServiceImpl extends CompletionService { @Override public void addAllElements(@NotNull Iterable elements) { - CompletionThreadingBase.withBatchUpdate(() -> super.addAllElements(elements)); + CompletionThreadingBase.withBatchUpdate(() -> super.addAllElements(elements), myParameters.getProcess()); } @Override @@ -191,17 +187,17 @@ public final class CompletionServiceImpl extends CompletionService { @Override public void restartCompletionOnPrefixChange(ElementPattern prefixCondition) { - final CompletionProgressIndicator indicator = getCompletionService().getCurrentCompletion(); - if (indicator != null) { - indicator.addWatchedPrefix(myLengthOfTextBeforePosition - getPrefixMatcher().getPrefix().length(), prefixCondition); + CompletionProcess process = myParameters.getProcess(); + if (process instanceof CompletionProgressIndicator) { + ((CompletionProgressIndicator)process).addWatchedPrefix(myLengthOfTextBeforePosition - getPrefixMatcher().getPrefix().length(), prefixCondition); } } @Override public void restartCompletionWhenNothingMatches() { - final CompletionProgressIndicator indicator = getCompletionService().getCurrentCompletion(); - if (indicator != null) { - indicator.getLookup().setStartCompletionWhenNothingMatches(true); + CompletionProcess process = myParameters.getProcess(); + if (process instanceof CompletionProgressIndicator) { + ((CompletionProgressIndicator)process).getLookup().setStartCompletionWhenNothingMatches(true); } } }