while collecting completion variants, don't depend on global state containing CompletionProgressIndicator

This commit is contained in:
peter
2018-01-25 09:48:02 +01:00
parent 2d1bbf5916
commit 7f83ede73b
5 changed files with 59 additions and 67 deletions
@@ -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;
}
}
@@ -75,7 +75,7 @@ public class CodeCompletionHandlerBase {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CodeCompletionHandlerBase");
private static final Key<Boolean> 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<CompletionContributor> 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<LookupElement> items) {
if (!invokedExplicitly) {
return AutoCompletionDecision.SHOW_LOOKUP;
@@ -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);
@@ -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<Boolean> 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);
@@ -110,13 +110,9 @@ public final class CompletionServiceImpl extends CompletionService {
@Nullable
private final CompletionResultSetImpl myOriginal;
public CompletionResultSetImpl(final Consumer<CompletionResult> consumer, final int lengthOfTextBeforePosition,
final PrefixMatcher prefixMatcher,
CompletionContributor contributor,
CompletionParameters parameters,
@NotNull CompletionSorterImpl sorter,
@Nullable CompletionResultSetImpl original) {
CompletionResultSetImpl(Consumer<CompletionResult> 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<? extends LookupElement> 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<String> 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);
}
}
}