IDEA-343642 cleanup

GitOrigin-RevId: da90d7c3e004c824694278b5aba85156f59f5856
This commit is contained in:
Vladimir Krivosheev
2024-01-24 11:18:26 +01:00
committed by intellij-monorepo-bot
parent 5ac2c35ccf
commit a00dc47229
11 changed files with 271 additions and 254 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
@@ -41,7 +41,7 @@ import java.util.List;
* A more generic way is to override default {@link #fillCompletionVariants(CompletionParameters, CompletionResultSet)} implementation
* and provide your own. It's easier to debug, but harder to write.<p>
*
* Q: How do I get automatic lookup element filtering by prefix?<br>
* Q: How do I get an automatic lookup element filtering by prefix?<br>
* A: When you return variants from reference ({@link PsiReference#getVariants()}), the filtering will be done
* automatically, with prefix taken as the reference text from its start ({@link PsiReference#getRangeInElement()}) to
* the caret position.
@@ -64,12 +64,12 @@ import java.util.List;
* Q: I'm not satisfied that completion just inserts the item's lookup string on item selection. How to make it write something else?<br>
* A: See {@link LookupElement#handleInsert(InsertionContext)}.<p>
*
* Q: What if I select item with TAB key?<br>
* A: Semantics is, that the identifier that you're standing inside gets removed completely, and then the lookup string is inserted. You can change
* Q: What if I select item with a TAB key?<br>
* A: Semantics is that the identifier that you're standing inside gets removed completely, and then the lookup string is inserted. You can change
* the deleting range end offset, do it in {@link CompletionContributor#beforeCompletion(CompletionInitializationContext)}
* by putting new offset to {@link CompletionInitializationContext#getOffsetMap()} as {@link CompletionInitializationContext#IDENTIFIER_END_OFFSET}.<p>
*
* Q: I know more about my environment than the IDE does, and I can swear that those 239 variants it suggests me in some place aren't all that relevant,
* Q: I know more about my environment than the IDE does, and I can swear that those 239 variants it suggests me in some places aren't all that relevant,
* so I'd be happy to filter out 42 of them. How do I do this?<br>
* A: This is a bit harder than just adding variants. First, you should invoke
* {@link CompletionResultSet#runRemainingContributors(CompletionParameters, Consumer)}.
@@ -82,7 +82,7 @@ import java.util.List;
*
* Q: How are lookup elements sorted?<br>
* A: Basically in lexicographic order, ascending, by lookup string ({@link LookupElement#getLookupString()}).
* Also, there's a number of "weigher" extensions under "completion" key (see {@link CompletionWeigher}) that bubble up the most relevant
* Also, there are a number of "weigher" extensions under "completion" key (see {@link CompletionWeigher}) that bubble up the most relevant
* items. To control lookup elements order you may implement {@link CompletionWeigher} or use {@link PrioritizedLookupElement}.<br>
* To debug the order of the completion items use '<code>Dump lookup element weights to log</code>' action when the completion lookup is
* shown (Ctrl+Alt+Shift+W / Cmd+Alt+Shift+W), the action also copies the debug info to the Clipboard.<p>
@@ -193,7 +193,7 @@ public abstract class CompletionContributor {
}
/**
* Called when the completion is finished quickly, lookup hasn't been shown and gives possibility to auto-insert some item (typically - the only one).
* Called when the completion is finished quickly, lookup hasn't been shown and gives the possibility to auto-insert some item (typically - the only one).
*/
public @Nullable AutoCompletionDecision handleAutoCompletionPossibility(@NotNull AutoCompletionContext context) {
return null;
@@ -212,7 +212,7 @@ public abstract class CompletionContributor {
* Invoked in a read action in parallel to the completion process. Used to calculate the replacement offset
* (see {@link CompletionInitializationContext#setReplacementOffset(int)})
* if it takes too much time to spend it in {@link #beforeCompletion(CompletionInitializationContext)},
* e.g. doing {@link com.intellij.psi.PsiFile#findReferenceAt(int)}
* e.g., doing {@link com.intellij.psi.PsiFile#findReferenceAt(int)}
*
* Guaranteed to be invoked before any lookup element is selected
*
@@ -221,10 +221,11 @@ public abstract class CompletionContributor {
public void duringCompletion(@NotNull CompletionInitializationContext context) {
}
public static @NotNull List<CompletionContributor> forParameters(final @NotNull CompletionParameters parameters) {
public static @NotNull List<CompletionContributor> forParameters(@NotNull CompletionParameters parameters) {
return ReadAction.compute(() -> {
PsiElement position = parameters.getPosition();
return forLanguageHonorDumbness(PsiUtilCore.getLanguageAtOffset(position.getContainingFile(), parameters.getOffset()), position.getProject());
return forLanguageHonorDumbness(PsiUtilCore.getLanguageAtOffset(position.getContainingFile(), parameters.getOffset()),
position.getProject());
});
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
@@ -17,27 +17,27 @@ import java.util.LinkedHashSet;
* match them against specified
* {@link PrefixMatcher} and give them to special {@link Consumer}
* for further processing, which usually means
* they will sooner or later appear in completion list. If they don't, there must be some {@link CompletionContributor}
* up the invocation stack that filters them out.
*
* they will sooner or later appear in a completion list.
* If they don't, there must be some {@link CompletionContributor} up the invocation stack that filters them out.
* <p>
* If you want to change the matching prefix, use {@link #withPrefixMatcher(PrefixMatcher)} or {@link #withPrefixMatcher(String)}
* to obtain another {@link CompletionResultSet} and give your lookup elements to that one.
*/
public abstract class CompletionResultSet implements Consumer<LookupElement> {
private final PrefixMatcher myPrefixMatcher;
private final Consumer<? super CompletionResult> myConsumer;
private final PrefixMatcher prefixMatcher;
private final java.util.function.Consumer<? super CompletionResult> consumer;
protected final CompletionService myCompletionService = CompletionService.getCompletionService();
protected final CompletionContributor myContributor;
protected final CompletionContributor contributor;
private boolean myStopped;
protected CompletionResultSet(final PrefixMatcher prefixMatcher, Consumer<? super CompletionResult> consumer, CompletionContributor contributor) {
myPrefixMatcher = prefixMatcher;
myConsumer = consumer;
myContributor = contributor;
protected CompletionResultSet(final PrefixMatcher prefixMatcher, java.util.function.Consumer<? super CompletionResult> consumer, CompletionContributor contributor) {
this.prefixMatcher = prefixMatcher;
this.consumer = consumer;
this.contributor = contributor;
}
protected Consumer<? super CompletionResult> getConsumer() {
return myConsumer;
protected java.util.function.Consumer<? super CompletionResult> getConsumer() {
return consumer;
}
@Override
@@ -52,18 +52,18 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
public abstract void addElement(final @NotNull LookupElement element);
public void passResult(@NotNull CompletionResult result) {
myConsumer.consume(result);
consumer.accept(result);
}
public void startBatch() {
if (myConsumer instanceof BatchConsumer) {
((BatchConsumer<?>)myConsumer).startBatch();
if (consumer instanceof BatchConsumer) {
((BatchConsumer<?>)consumer).startBatch();
}
}
public void endBatch() {
if (myConsumer instanceof BatchConsumer) {
((BatchConsumer<?>)myConsumer).endBatch();
if (consumer instanceof BatchConsumer) {
((BatchConsumer<?>)consumer).endBatch();
}
}
@@ -74,7 +74,7 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
* Otherwise, when the lookup is shown, most relevant elements processed to that moment are put to the top
* and remain there even if more relevant elements appear later.
* These "first" elements may differ from completion invocation to completion invocation due to performance fluctuations,
* resulting in varying preselected item in completion and worse user experience. Using {@code addAllElements}
* resulting in varying preselected items in completion and worse user experience. Using {@code addAllElements}
* instead of {@link #addElement(LookupElement)} helps to avoid that.
*/
public void addAllElements(final @NotNull Iterable<? extends LookupElement> elements) {
@@ -106,13 +106,13 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
/**
* @return A result set with the same prefix, but the lookup strings will be matched case-insensitively. Their lookup strings will
* remain as they are though, so upon insertion the prefix case will be changed.
* remain as they are though, so upon insertion, the prefix case will be changed.
*/
@Contract(pure = true)
public abstract @NotNull CompletionResultSet caseInsensitive();
public @NotNull PrefixMatcher getPrefixMatcher() {
return myPrefixMatcher;
return prefixMatcher;
}
public boolean isStopped() {
@@ -147,7 +147,7 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
if (stop) {
stopHere();
}
myCompletionService.getVariantsFromContributors(parameters, myContributor, getPrefixMatcher(), new BatchConsumer<>() {
myCompletionService.getVariantsFromContributors(parameters, contributor, getPrefixMatcher(), new BatchConsumer<>() {
@Override
public void startBatch() {
CompletionResultSet.this.startBatch();

View File

@@ -26,7 +26,7 @@ import java.util.ArrayList;
public class BaseCompletionService extends CompletionService {
private static final Logger LOG = Logger.getInstance(BaseCompletionService.class);
protected @Nullable CompletionProcess myApiCompletionProcess;
protected @Nullable CompletionProcess apiCompletionProcess;
@ApiStatus.Internal
public static final Key<CompletionContributor> LOOKUP_ELEMENT_CONTRIBUTOR = Key.create("lookup element contributor");
@@ -43,12 +43,12 @@ public class BaseCompletionService extends CompletionService {
@Override
public void performCompletion(@NotNull CompletionParameters parameters, @NotNull Consumer<? super CompletionResult> consumer) {
myApiCompletionProcess = parameters.getProcess();
apiCompletionProcess = parameters.getProcess();
try {
super.performCompletion(parameters, consumer);
}
finally {
myApiCompletionProcess = null;
apiCompletionProcess = null;
}
}
@@ -56,8 +56,8 @@ public class BaseCompletionService extends CompletionService {
public void setAdvertisementText(@Nullable @NlsContexts.PopupAdvertisement String text) {
if (text == null) return;
if (myApiCompletionProcess instanceof CompletionProcessEx) {
((CompletionProcessEx)myApiCompletionProcess).addAdvertisement(text, null);
if (apiCompletionProcess instanceof CompletionProcessEx) {
((CompletionProcessEx)apiCompletionProcess).addAdvertisement(text, null);
}
}
@@ -88,21 +88,21 @@ public class BaseCompletionService extends CompletionService {
@Override
public @Nullable CompletionProcess getCurrentCompletion() {
return myApiCompletionProcess;
return apiCompletionProcess;
}
protected static class BaseCompletionResultSet extends CompletionResultSet {
protected final CompletionParameters myParameters;
protected CompletionSorter mySorter;
protected final CompletionParameters parameters;
protected CompletionSorter sorter;
protected final @Nullable BaseCompletionService.BaseCompletionResultSet myOriginal;
private int myItemCounter = 0;
private int itemCounter = 0;
protected BaseCompletionResultSet(Consumer<? super CompletionResult> consumer, PrefixMatcher prefixMatcher,
protected BaseCompletionResultSet(java.util.function.Consumer<? super CompletionResult> consumer, PrefixMatcher prefixMatcher,
CompletionContributor contributor, CompletionParameters parameters,
@Nullable CompletionSorter sorter, @Nullable BaseCompletionService.BaseCompletionResultSet original) {
super(prefixMatcher, consumer, contributor);
myParameters = parameters;
mySorter = sorter;
this.parameters = parameters;
this.sorter = sorter;
myOriginal = original;
}
@@ -111,18 +111,18 @@ public class BaseCompletionService extends CompletionService {
ProgressManager.checkCanceled();
if (!element.isValid()) {
LOG.error("Invalid lookup element: " + element + " of " + element.getClass() +
" in " + myParameters.getOriginalFile() + " of " + myParameters.getOriginalFile().getClass());
" in " + parameters.getOriginalFile() + " of " + parameters.getOriginalFile().getClass());
return;
}
mySorter = mySorter == null ? getCompletionService().defaultSorter(myParameters, getPrefixMatcher()) : mySorter;
sorter = sorter == null ? getCompletionService().defaultSorter(parameters, getPrefixMatcher()) : sorter;
CompletionResult matched = CompletionResult.wrap(element, getPrefixMatcher(), mySorter);
CompletionResult matched = CompletionResult.wrap(element, getPrefixMatcher(), sorter);
if (matched != null) {
element.putUserData(LOOKUP_ELEMENT_CONTRIBUTOR, myContributor);
element.putUserData(LOOKUP_ELEMENT_CONTRIBUTOR, contributor);
element.putUserData(LOOKUP_ELEMENT_RESULT_ADD_TIMESTAMP_MILLIS, System.currentTimeMillis());
element.putUserData(LOOKUP_ELEMENT_RESULT_SET_ORDER, myItemCounter);
myItemCounter += 1;
element.putUserData(LOOKUP_ELEMENT_RESULT_SET_ORDER, itemCounter);
itemCounter += 1;
passResult(matched);
}
}
@@ -132,7 +132,7 @@ public class BaseCompletionService extends CompletionService {
if (matcher.equals(getPrefixMatcher())) {
return this;
}
return new BaseCompletionResultSet(getConsumer(), matcher, myContributor, myParameters, mySorter, this);
return new BaseCompletionResultSet(getConsumer(), matcher, contributor, parameters, sorter, this);
}
@Override
@@ -153,7 +153,7 @@ public class BaseCompletionService extends CompletionService {
@Override
public @NotNull CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) {
return new BaseCompletionResultSet(getConsumer(), getPrefixMatcher(), myContributor, myParameters, sorter, this);
return new BaseCompletionResultSet(getConsumer(), getPrefixMatcher(), contributor, parameters, sorter, this);
}
@Override

View File

@@ -19,10 +19,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.OverridingAction;
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.application.*;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
@@ -46,6 +43,7 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.platform.diagnostic.telemetry.TelemetryManager;
import com.intellij.platform.diagnostic.telemetry.helpers.TraceKt;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
@@ -71,7 +69,6 @@ import java.util.Objects;
import static com.intellij.codeInsight.completion.CompletionThreadingKt.checkForExceptions;
import static com.intellij.codeInsight.util.CodeCompletionKt.CodeCompletion;
import static com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.runWithSpan;
import static com.intellij.psi.stubs.StubInconsistencyReporter.SourceOfCheck.DeliberateAdditionalCheckInCompletion;
@SuppressWarnings("deprecation")
@@ -192,12 +189,13 @@ public class CodeCompletionHandlerBase {
long startingTime = System.currentTimeMillis();
Runnable initCmd = () -> {
WriteAction.run(() -> EditorUtil.fillVirtualSpaceUntilCaret(editor));
CompletionInitializationContextImpl context = withTimeout(calcSyncTimeOut(startingTime), () ->
CompletionInitializationUtil.createCompletionInitializationContext(project, editor, caret, invocationCount, completionType));
CompletionInitializationContextImpl context = withTimeout(calcSyncTimeOut(startingTime), () -> {
return CompletionInitializationUtil.createCompletionInitializationContext(project, editor, caret, invocationCount, completionType);
});
boolean hasValidContext = context != null;
if (!hasValidContext) {
final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(caret, project);
PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(caret, project);
context = new CompletionInitializationContextImpl(editor, caret, psiFile, completionType, invocationCount);
}
@@ -225,19 +223,21 @@ public class CodeCompletionHandlerBase {
int time,
boolean hasModifiers,
@NotNull Caret caret) {
runWithSpan(completionTracer, "invokeCompletion", (span) -> {
span.setAttribute("project", project.getName());
span.setAttribute("caretOffset", caret.hasSelection() ? caret.getSelectionStart() : caret.getOffset());
invokeCompletion(project, editor, time, hasModifiers, caret);
});
TraceKt.useWithScopeBlocking(
completionTracer.spanBuilder("invokeCompletion")
.setAttribute("project", project.getName())
.setAttribute("caretOffset", caret.hasSelection() ? caret.getSelectionStart() : caret.getOffset()),
span -> {
invokeCompletion(project, editor, time, hasModifiers, caret);
return null;
}
);
}
private static void checkNoWriteAccess() {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
throw new AssertionError("Completion should not be invoked inside write action");
}
Application app = ApplicationManager.getApplication();
if (!app.isUnitTestMode() && app.isWriteAccessAllowed()) {
throw new AssertionError("Completion should not be invoked inside write action");
}
}
@@ -263,18 +263,19 @@ public class CodeCompletionHandlerBase {
}
private void doComplete(CompletionInitializationContextImpl initContext, boolean hasModifiers, boolean isValidContext, long startingTime) {
final Editor editor = initContext.getEditor();
Editor editor = initContext.getEditor();
CompletionAssertions.checkEditorValid(editor);
LookupImpl lookup = obtainLookup(editor, initContext.getProject());
CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
if (phase instanceof CompletionPhase.CommittingDocuments) {
if (phase instanceof CompletionPhase.CommittingDocuments p) {
if (phase.indicator != null) {
phase.indicator.closeAndFinish(false);
}
((CompletionPhase.CommittingDocuments)phase).replaced = true;
} else {
p.replaced = true;
}
else {
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
}
@@ -305,7 +306,8 @@ public class CodeCompletionHandlerBase {
if (synchronous) {
phase = new CompletionPhase.BgCalculation(indicator);
indicator.showLookup();
} else {
}
else {
phase = new CompletionPhase.CommittingDocuments(indicator, InjectedLanguageEditorUtil.getTopLevelEditor(indicator.getEditor()), null);
}
CompletionServiceImpl.setCompletionPhase(phase);
@@ -339,7 +341,10 @@ public class CodeCompletionHandlerBase {
int timeout = calcSyncTimeOut(startingTime);
if (indicator.blockingWaitForFinish(timeout)) {
checkForExceptions(future);
if (ApplicationManager.getApplication().isUnitTestMode()) {
//noinspection TestOnlyProblems
checkForExceptions(future);
}
try {
indicator.getLookup().refreshUi(true, false);
completionFinished(indicator, hasModifiers);

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
@@ -227,6 +227,7 @@ public abstract class CompletionPhase implements Disposable {
}
}
public static final class Synchronous extends CompletionPhase {
public Synchronous(CompletionProgressIndicator indicator) {
super(indicator);
@@ -239,6 +240,7 @@ public abstract class CompletionPhase implements Disposable {
return time;
}
}
public static final class BgCalculation extends CompletionPhase {
boolean modifiersChanged = false;
private final @NotNull ClientId ownerId = ClientId.getCurrent();

View File

@@ -85,22 +85,22 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
@NotNull
private final Caret myCaret;
@Nullable private CompletionParameters myParameters;
private final CodeCompletionHandlerBase myHandler;
private final CodeCompletionHandlerBase handler;
private final CompletionLookupArrangerImpl myArranger;
private final CompletionType myCompletionType;
private final int myInvocationCount;
private OffsetsInFile myHostOffsets;
private final LookupImpl myLookup;
private final MergingUpdateQueue myQueue;
private final LookupImpl lookup;
private final MergingUpdateQueue queue;
private final Update myUpdate = new Update("update") {
@Override
public void run() {
updateLookup();
myQueue.setMergingTimeSpan(ourShowPopupGroupingTime);
queue.setMergingTimeSpan(ourShowPopupGroupingTime);
}
};
private final Semaphore myFreezeSemaphore = new Semaphore(1);
private final Semaphore myFinishSemaphore = new Semaphore(1);
private final Semaphore freezeSemaphore = new Semaphore(1);
private final Semaphore finishSemaphore = new Semaphore(1);
@NotNull private final OffsetMap myOffsetMap;
private final Set<Pair<Integer, ElementPattern<String>>> myRestartingPrefixConditions = ConcurrentHashMap.newKeySet();
private final LookupListener myLookupListener = new LookupListener() {
@@ -116,7 +116,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
private static int ourShowPopupGroupingTime = 300;
private static int ourShowPopupAfterFirstItemGroupingTime = 100;
private volatile int myCount;
private volatile int count;
private enum LookupAppearancePolicy {
/**
* The default strategy for lookup appearance.
@@ -143,7 +143,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
private boolean myLookupUpdated;
private final PropertyChangeListener myLookupManagerListener;
private final Queue<Runnable> myAdvertiserChanges = new ConcurrentLinkedQueue<>();
private final List<CompletionResult> myDelayedMiddleMatches = new ArrayList<>();
private final List<CompletionResult> delayedMiddleMatches = new ArrayList<>();
private final int myStartCaret;
private final CompletionThreadingBase myThreading;
private final Object myLock = ObjectUtils.sentinel("CompletionProgressIndicator");
@@ -161,24 +161,24 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
boolean hasModifiers, @NotNull LookupImpl lookup) {
myEditor = editor;
myCaret = caret;
myHandler = handler;
this.handler = handler;
myCompletionType = handler.completionType;
myInvocationCount = invocationCount;
myOffsetMap = offsetMap;
myHostOffsets = hostOffsets;
myLookup = lookup;
this.lookup = lookup;
myStartCaret = myEditor.getCaretModel().getOffset();
myThreading = ApplicationManager.getApplication().isWriteAccessAllowed() || myHandler.isTestingCompletionQualityMode()
myThreading = ApplicationManager.getApplication().isWriteAccessAllowed() || this.handler.isTestingCompletionQualityMode()
? new SyncCompletion()
: new AsyncCompletion(editor.getProject());
myAdvertiserChanges.offer(() -> myLookup.getAdvertiser().clearAdvertisements());
myAdvertiserChanges.offer(() -> this.lookup.getAdvertiser().clearAdvertisements());
myArranger = new CompletionLookupArrangerImpl(this);
myLookup.setArranger(myArranger);
this.lookup.setArranger(myArranger);
myLookup.addLookupListener(myLookupListener);
myLookup.setCalculating(true);
this.lookup.addLookupListener(myLookupListener);
this.lookup.setCalculating(true);
myEmptyCompletionNotifier = LightEdit.owns(editor.getProject()) ? LightEditUtil.createEmptyCompletionNotifier() :
new ProjectEmptyCompletionNotifier();
@@ -191,7 +191,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
};
LookupManager.getInstance(getProject()).addPropertyChangeListener(myLookupManagerListener);
myQueue = new MergingUpdateQueue("completion lookup progress", ourShowPopupAfterFirstItemGroupingTime, true, myEditor.getContentComponent());
queue = new MergingUpdateQueue("completion lookup progress", ourShowPopupAfterFirstItemGroupingTime, true, myEditor.getContentComponent());
ThreadingAssertions.assertEventDispatchThread();
@@ -208,7 +208,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
setMergeCommand();
myHandler.lookupItemSelected(this, lookupItem, completionChar, myLookup.getItems());
handler.lookupItemSelected(this, lookupItem, completionChar, lookup.getItems());
}
@Override
@@ -230,7 +230,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
LookupFocusDegree degree = CodeInsightSettings.getInstance().isSelectAutopopupSuggestionsByChars()
? LookupFocusDegree.FOCUSED
: LookupFocusDegree.SEMI_FOCUSED;
myLookup.setLookupFocusDegree(degree);
lookup.setLookupFocusDegree(degree);
}
addDefaultAdvertisements(parameters);
@@ -338,14 +338,17 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
void scheduleAdvertising(CompletionParameters parameters) {
if (myLookup.isAvailableToUser()) {
if (lookup.isAvailableToUser()) {
return;
}
DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(() -> {
for (CompletionContributor contributor : CompletionContributor.forParameters(parameters)) {
if (!myLookup.isCalculating() && !myLookup.isVisible()) return;
if (!lookup.isCalculating() && !lookup.isVisible()) {
return;
}
//noinspection deprecation
@SuppressWarnings("removal")
String s = contributor.advertise(parameters);
if (s != null) {
addAdvertisement(s, null);
@@ -393,7 +396,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
@Override
@NotNull
public LookupImpl getLookup() {
return myLookup;
return lookup;
}
/**
@@ -424,7 +427,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
private void openLookupLater() {
ApplicationManager.getApplication()
.invokeLater(this::showLookup, obj -> myLookup.getShownTimestampMillis() != 0L || myLookup.isLookupDisposed());
.invokeLater(this::showLookup, obj -> lookup.getShownTimestampMillis() != 0L || lookup.isLookupDisposed());
}
void withSingleUpdate(Runnable action) {
@@ -442,28 +445,28 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
}
if (!myLookupUpdated) {
if (myLookup.getAdvertisements().isEmpty() && !isAutopopupCompletion() && !DumbService.isDumb(getProject())) {
DefaultCompletionContributor.addDefaultAdvertisements(myLookup, myHasPsiElements);
if (lookup.getAdvertisements().isEmpty() && !isAutopopupCompletion() && !DumbService.isDumb(getProject())) {
DefaultCompletionContributor.addDefaultAdvertisements(lookup, myHasPsiElements);
}
myLookup.getAdvertiser().showRandomText();
lookup.getAdvertiser().showRandomText();
}
boolean justShown = false;
if (!myLookup.isShown()) {
if (!lookup.isShown()) {
if (hideAutopopupIfMeaningless()) {
return;
}
if (!myLookup.showLookup()) {
if (!lookup.showLookup()) {
return;
}
justShown = true;
}
myLookupUpdated = true;
myLookup.refreshUi(true, justShown);
lookup.refreshUi(true, justShown);
hideAutopopupIfMeaningless();
if (justShown) {
myLookup.ensureSelectionVisible(true);
lookup.ensureSelectionVisible(true);
}
}
@@ -472,10 +475,10 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
return false;
}
if (isAutopopupCompletion()) {
if (myCount == 0) {
if (count == 0) {
return false;
}
if (myLookup.isCalculating() && Registry.is("ide.completion.delay.autopopup.until.completed")) {
if (lookup.isCalculating() && Registry.is("ide.completion.delay.autopopup.until.completed")) {
return false;
}
}
@@ -486,7 +489,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
if (!isRunning()) return;
ProgressManager.checkCanceled();
if (!myHandler.isTestingMode()) {
if (!handler.isTestingMode()) {
ApplicationManager.getApplication().assertIsNonDispatchThread();
}
@@ -502,7 +505,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
return;
}
boolean allowMiddleMatches = myCount > BaseCompletionLookupArranger.MAX_PREFERRED_COUNT * 2;
boolean allowMiddleMatches = count > BaseCompletionLookupArranger.MAX_PREFERRED_COUNT * 2;
if (allowMiddleMatches) {
addDelayedMiddleMatches();
}
@@ -511,8 +514,8 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
if (item.isStartMatch() || allowMiddleMatches) {
addItemToLookup(item);
} else {
synchronized (myDelayedMiddleMatches) {
myDelayedMiddleMatches.add(item);
synchronized (delayedMiddleMatches) {
delayedMiddleMatches.add(item);
}
}
}
@@ -520,41 +523,42 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
private void addItemToLookup(CompletionResult item) {
Ref<Boolean> stopRef = new Ref<>(Boolean.FALSE);
DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(() -> {
stopRef.set(!myLookup.addItem(item.getLookupElement(), item.getPrefixMatcher()));
stopRef.set(!lookup.addItem(item.getLookupElement(), item.getPrefixMatcher()));
});
if (stopRef.get()) {
return;
}
myArranger.setLastLookupPrefix(myLookup.getAdditionalPrefix());
myArranger.setLastLookupPrefix(lookup.getAdditionalPrefix());
//noinspection NonAtomicOperationOnVolatileField
myCount++; // invoked from a single thread
count++; // invoked from a single thread
if (myCount == myUnfreezeAfterNItems) {
if (count == myUnfreezeAfterNItems) {
showLookupAsSoonAsPossible();
}
if (myLookupAppearancePolicy == LookupAppearancePolicy.ON_FIRST_POSSIBILITY && myLookup.getShownTimestampMillis() == 0L) {
AppExecutorUtil.getAppScheduledExecutorService().schedule(myFreezeSemaphore::up, 0, TimeUnit.MILLISECONDS);
if (myLookupAppearancePolicy == LookupAppearancePolicy.ON_FIRST_POSSIBILITY && lookup.getShownTimestampMillis() == 0L) {
AppExecutorUtil.getAppScheduledExecutorService().schedule(freezeSemaphore::up, 0, TimeUnit.MILLISECONDS);
openLookupLater();
} else {
if (myCount == 1) {
AppExecutorUtil.getAppScheduledExecutorService().schedule(myFreezeSemaphore::up, ourInsertSingleItemTimeSpan, TimeUnit.MILLISECONDS);
}
else {
if (count == 1) {
AppExecutorUtil.getAppScheduledExecutorService().schedule(freezeSemaphore::up, ourInsertSingleItemTimeSpan, TimeUnit.MILLISECONDS);
}
myQueue.queue(myUpdate);
queue.queue(myUpdate);
}
}
/**
* In certain cases we add the first batch of items almost at once and want to show lookup directly after they are added.
* In certain cases, we add the first batch of items almost at once and want to show lookup directly after they are added.
* It makes sense to set this number when you get all your items from one contributor, and you have full control over the completion
* process. So you can, for example, set this number in the beginning of `addCompletions()` in your completion provider and reset it
* when the completion is over.
* Example: Completion provider receives first 100 items at once after significant delay (200+ ms) and adds them all together. If you
* don't set this value, and you continue adding results in your completion provider (for example you get your next batch of results in
* 500ms) the popup might be shown with significant delay.
* don't set this value, and you continue adding results in your completion provider (for example, you get your next batch of results in
* 500ms), the popup might be shown with significant delay.
*
* @param number The Number of items in lookup which trigger the popup. -1 means this functionality is disabled. Also specifying 0 makes
* no sense since we can't add 0 items.
@@ -563,13 +567,14 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
myUnfreezeAfterNItems = number;
}
void addDelayedMiddleMatches() {
ArrayList<CompletionResult> delayed;
synchronized (myDelayedMiddleMatches) {
if (myDelayedMiddleMatches.isEmpty()) return;
delayed = new ArrayList<>(myDelayedMiddleMatches);
myDelayedMiddleMatches.clear();
synchronized (delayedMiddleMatches) {
if (delayedMiddleMatches.isEmpty()) {
return;
}
delayed = new ArrayList<>(delayedMiddleMatches);
delayedMiddleMatches.clear();
}
for (CompletionResult item : delayed) {
ProgressManager.checkCanceled();
@@ -578,18 +583,18 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
}
public void closeAndFinish(boolean hideLookup) {
if (!myLookup.isLookupDisposed()) {
if (!lookup.isLookupDisposed()) {
Lookup lookup = LookupManager.getActiveLookup(myEditor);
if (lookup != null && lookup != myLookup && ClientId.isCurrentlyUnderLocalId()) {
if (lookup != null && lookup != this.lookup && ClientId.isCurrentlyUnderLocalId()) {
LOG.error("lookup changed: " + lookup + "; " + this);
}
}
myLookup.removeLookupListener(myLookupListener);
lookup.removeLookupListener(myLookupListener);
finishCompletionProcess(true);
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
if (hideLookup) {
myLookup.hideLookup(true);
lookup.hideLookup(true);
}
}
@@ -597,20 +602,21 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
cancel();
ThreadingAssertions.assertEventDispatchThread();
Disposer.dispose(myQueue);
Disposer.dispose(queue);
LookupManager.getInstance(getProject()).removePropertyChangeListener(myLookupManagerListener);
CompletionServiceImpl
.assertPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class, CompletionPhase.Synchronous.class,
CompletionPhase.CommittingDocuments.class);
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) {
if (oldPhase instanceof CompletionPhase.CommittingDocuments p) {
LOG.assertTrue(oldPhase.indicator != null, oldPhase);
((CompletionPhase.CommittingDocuments)oldPhase).replaced = true;
p.replaced = true;
}
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
if (disposeOffsetMap) {
@@ -652,13 +658,14 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
}
boolean blockingWaitForFinish(int timeoutMs) {
if (myHandler.isTestingMode() && !TestModeFlags.is(CompletionAutoPopupHandler.ourTestingAutopopup)) {
if (!myFinishSemaphore.waitFor(100 * 1000)) {
if (handler.isTestingMode() && !TestModeFlags.is(CompletionAutoPopupHandler.ourTestingAutopopup)) {
if (!finishSemaphore.waitFor(100 * 1000)) {
throw new AssertionError("Too long completion");
}
return true;
}
if (myFreezeSemaphore.waitFor(timeoutMs)) {
if (freezeSemaphore.waitFor(timeoutMs)) {
// the completion is really finished, now we may auto-insert or show lookup
return !isRunning() && !isCanceled();
}
@@ -669,18 +676,20 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
public void stop() {
super.stop();
myQueue.cancelAllUpdates();
myFreezeSemaphore.up();
myFinishSemaphore.up();
queue.cancelAllUpdates();
freezeSemaphore.up();
finishSemaphore.up();
ModalityUiUtil.invokeLaterIfNeeded(myQueue.getModalityState(), () -> {
final CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
if (!(phase instanceof CompletionPhase.BgCalculation) || phase.indicator != this) return;
ModalityUiUtil.invokeLaterIfNeeded(queue.getModalityState(), () -> {
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);
lookup.hideLookup(false);
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
return;
}
@@ -689,20 +698,21 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
LOG.assertTrue(((EditorWindow)myEditor).getInjectedFile().isValid(), "injected file !valid");
LOG.assertTrue(((DocumentWindow)myEditor.getDocument()).isValid(), "docWindow !valid");
}
PsiFile file = myLookup.getPsiFile();
PsiFile file = lookup.getPsiFile();
LOG.assertTrue(file == null || file.isValid(), "file !valid");
myLookup.setCalculating(false);
lookup.setCalculating(false);
if (myCount == 0) {
myLookup.hideLookup(false);
if (!isAutopopupCompletion()) {
final CompletionProgressIndicator current = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
if (count == 0) {
lookup.hideLookup(false);
if (isAutopopupCompletion()) {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.EmptyAutoPopup(myEditor, myRestartingPrefixConditions));
}
else {
CompletionProgressIndicator current = CompletionServiceImpl.getCurrentCompletionProgressIndicator();
LOG.assertTrue(current == null, current + "!=" + this);
handleEmptyLookup(!((CompletionPhase.BgCalculation)phase).modifiersChanged);
} else {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.EmptyAutoPopup(myEditor, myRestartingPrefixConditions));
}
}
else {
@@ -715,31 +725,30 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
}
private boolean hideAutopopupIfMeaningless() {
if (!myLookup.isLookupDisposed() && isAutopopupCompletion() && !myLookup.isSelectionTouched() && !myLookup.isCalculating()) {
myLookup.refreshUi(true, false);
final List<LookupElement> items = myLookup.getItems();
if (lookup.isLookupDisposed() || !isAutopopupCompletion() || lookup.isSelectionTouched() || lookup.isCalculating()) {
return false;
}
for (LookupElement item : items) {
if (!isAlreadyInTheEditor(item)) {
return false;
}
if (item.isValid() && item.isWorthShowingInAutoPopup()) {
return false;
}
lookup.refreshUi(true, false);
for (LookupElement item : lookup.getItems()) {
if (!isAlreadyInTheEditor(item)) {
return false;
}
myLookup.hideLookup(false);
LOG.assertTrue(CompletionServiceImpl.getCompletionService().getCurrentCompletion() == null);
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.EmptyAutoPopup(myEditor, myRestartingPrefixConditions));
return true;
if (item.isValid() && item.isWorthShowingInAutoPopup()) {
return false;
}
}
return false;
lookup.hideLookup(false);
LOG.assertTrue(CompletionServiceImpl.getCompletionService().getCurrentCompletion() == null);
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.EmptyAutoPopup(myEditor, myRestartingPrefixConditions));
return true;
}
private boolean isAlreadyInTheEditor(LookupElement item) {
Editor editor = myLookup.getEditor();
int start = editor.getCaretModel().getOffset() - myLookup.itemPattern(item).length();
Editor editor = lookup.getEditor();
int start = editor.getCaretModel().getOffset() - lookup.itemPattern(item).length();
Document document = editor.getDocument();
return start >= 0 && StringUtil.startsWith(document.getImmutableCharSequence().subSequence(start, document.getTextLength()),
item.getLookupString());
@@ -773,7 +782,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
return false;
}
if (isAutopopupCompletion() && !myLookup.mayBeNoticed()) {
if (isAutopopupCompletion() && !lookup.mayBeNoticed()) {
return false;
}
@@ -839,7 +848,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
@Override
public void scheduleRestart() {
ThreadingAssertions.assertEventDispatchThread();
if (myHandler.isTestingMode() && !TestModeFlags.is(CompletionAutoPopupHandler.ourTestingAutopopup)) {
if (handler.isTestingMode() && !TestModeFlags.is(CompletionAutoPopupHandler.ourTestingAutopopup)) {
closeAndFinish(false);
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
new CodeCompletionHandlerBase(myCompletionType, false, false, true).invokeCompletion(getProject(), myEditor, myInvocationCount);
@@ -868,7 +877,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
@Override
public String toString() {
return "CompletionProgressIndicator[count=" +
myCount +
count +
",phase=" +
CompletionServiceImpl.getCompletionPhase() +
"]@" +
@@ -883,7 +892,7 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
LOG.assertTrue(!isAutopopupCompletion());
CompletionParameters parameters = getParameters();
if (myHandler.invokedExplicitly && parameters != null) {
if (handler.invokedExplicitly && parameters != null) {
LightweightHint hint = showErrorHint(getProject(), getEditor(), getNoSuggestionsMessage(parameters));
if (awaitSecondInvocation) {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.NoSuggestionsHint(hint, this));
@@ -976,9 +985,9 @@ public final class CompletionProgressIndicator extends ProgressIndicatorBase imp
@Override
public void addAdvertisement(@NotNull String text, @Nullable Icon icon) {
myAdvertiserChanges.offer(() -> myLookup.addAdvertisement(text, icon));
myAdvertiserChanges.offer(() -> lookup.addAdvertisement(text, icon));
myQueue.queue(myUpdate);
queue.queue(myUpdate);
}
@TestOnly

View File

@@ -2,7 +2,6 @@
package com.intellij.codeInsight.completion
import com.intellij.codeWithMe.ClientId
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ex.ApplicationManagerEx
import com.intellij.openapi.components.ComponentManagerEx
import com.intellij.openapi.diagnostic.logger
@@ -17,6 +16,7 @@ import com.intellij.util.concurrency.Semaphore
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import org.jetbrains.annotations.TestOnly
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit
@@ -150,10 +150,10 @@ internal class AsyncCompletion(project: Project?) : CompletionThreadingBase() {
batchList.add(result)
}
else {
queue.offer(Computable {
queue.offer {
tryReadOrCancel(indicator) { indicator.addItem(result) }
true
})
}
}
}
}
@@ -180,11 +180,10 @@ internal class AsyncCompletion(project: Project?) : CompletionThreadingBase() {
}
}
@Suppress("SSBasedInspection")
@TestOnly
internal fun checkForExceptions(future: Deferred<Unit>) {
if (ApplicationManager.getApplication().isUnitTestMode) {
@Suppress("SSBasedInspection")
runBlocking {
future.await()
}
runBlocking {
future.await()
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.completion
import com.intellij.codeInsight.lookup.LookupElement
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.ApiStatus
class FilteringResultSet(
private val base: CompletionResultSet,
private val filter: (CompletionContributor) -> Boolean
) : CompletionResultSet(base.prefixMatcher, base.consumer, base.myContributor) {
) : CompletionResultSet(base.prefixMatcher, base.consumer, base.contributor) {
override fun addElement(element: LookupElement) {
base.addElement(element)
}
@@ -64,7 +64,7 @@ class FilteringResultSet(
consumer.consume(result)
}
}
myCompletionService.getVariantsFromContributors(parameters, myContributor, prefixMatcher, batchConsumer, customSorter, filter)
myCompletionService.getVariantsFromContributors(parameters, contributor, prefixMatcher, batchConsumer, customSorter, filter)
}
companion object {

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.completion
import com.intellij.codeInsight.completion.addingPolicy.ElementsAddingPolicy
@@ -10,7 +10,7 @@ import org.jetbrains.annotations.ApiStatus
class PolicyObeyingResultSet(
private val originalResult: CompletionResultSet,
private val policyHolder: () -> ElementsAddingPolicy
) : CompletionResultSet(originalResult.prefixMatcher, originalResult.consumer, originalResult.myContributor) {
) : CompletionResultSet(originalResult.prefixMatcher, originalResult.consumer, originalResult.contributor) {
override fun addElement(element: LookupElement) {
policyHolder().addElement(originalResult, element)

View File

@@ -26,12 +26,11 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.NlsContexts
import com.intellij.patterns.ElementPattern
import com.intellij.platform.diagnostic.telemetry.TelemetryManager
import com.intellij.platform.diagnostic.telemetry.helpers.runWithSpan
import com.intellij.platform.diagnostic.telemetry.helpers.useWithScopeBlocking
import com.intellij.psi.Weigher
import com.intellij.util.Consumer
import com.intellij.util.ExceptionUtil
import com.intellij.util.concurrency.ThreadingAssertions
import io.opentelemetry.api.trace.Span
import kotlin.concurrent.Volatile
private val LOG = logger<CompletionServiceImpl>()
@@ -53,13 +52,8 @@ open class CompletionServiceImpl : BaseCompletionService() {
@JvmStatic
fun assertPhase(vararg possibilities: Class<out CompletionPhase>) {
val holder = tryGetClientCompletionService(getAppSession())?.completionPhaseHolder ?: DEFAULT_PHASE_HOLDER
assertPhase(holder, *possibilities)
}
@SafeVarargs
private fun assertPhase(phaseHolder: CompletionPhaseHolder, vararg possibilities: Class<out CompletionPhase>) {
if (!isPhase(phaseHolder.phase, *possibilities)) {
reportPhase(phaseHolder)
if (!isPhase(holder.phase, *possibilities)) {
reportPhase(holder)
}
}
@@ -72,13 +66,11 @@ open class CompletionServiceImpl : BaseCompletionService() {
@JvmStatic
var completionPhase: CompletionPhase
get() {
val clientCompletionService = tryGetClientCompletionService(getAppSession())
if (clientCompletionService == null) return DEFAULT_PHASE_HOLDER.phase
val clientCompletionService = tryGetClientCompletionService(getAppSession()) ?: return DEFAULT_PHASE_HOLDER.phase
return clientCompletionService.completionPhase
}
set(phase) {
val clientCompletionService = tryGetClientCompletionService(getAppSession())
if (clientCompletionService == null) return
val clientCompletionService = tryGetClientCompletionService(getAppSession()) ?: return
clientCompletionService.completionPhase = phase
}
}
@@ -89,9 +81,7 @@ open class CompletionServiceImpl : BaseCompletionService() {
override fun projectClosing(project: Project) {
val sessions = getAppSessions(ClientKind.ALL)
for (session in sessions) {
val clientCompletionService = tryGetClientCompletionService(session)
if (clientCompletionService == null) continue
val clientCompletionService = tryGetClientCompletionService(session) ?: continue
val indicator = clientCompletionService.currentCompletionProgressIndicator
if (indicator != null && indicator.project === project) {
indicator.closeAndFinish(true)
@@ -107,8 +97,7 @@ open class CompletionServiceImpl : BaseCompletionService() {
override fun beforePluginUnload(pluginDescriptor: IdeaPluginDescriptor, isUpdate: Boolean) {
val sessions = getAppSessions(ClientKind.ALL)
for (session in sessions) {
val clientCompletionService = tryGetClientCompletionService(session)
if (clientCompletionService == null) continue
val clientCompletionService = tryGetClientCompletionService(session) ?: continue
clientCompletionService.completionPhase = NoCompletion
}
}
@@ -117,44 +106,48 @@ open class CompletionServiceImpl : BaseCompletionService() {
@Suppress("OVERRIDE_DEPRECATION")
override fun setAdvertisementText(text: @NlsContexts.PopupAdvertisement String?) {
if (text == null) return
val completion = currentCompletionProgressIndicator
completion?.addAdvertisement(text, null)
if (text == null) {
return
}
currentCompletionProgressIndicator?.addAdvertisement(text, null)
}
override fun createResultSet(parameters: CompletionParameters,
consumer: Consumer<in CompletionResult>,
contributor: CompletionContributor,
matcher: PrefixMatcher): CompletionResultSet {
return CompletionResultSetImpl(consumer, matcher, contributor, parameters, null, null)
return CompletionResultSetImpl(consumer = consumer,
prefixMatcher = matcher,
contributor = contributor,
parameters = parameters,
sorter = null,
original = null)
}
override fun getCurrentCompletion(): CompletionProcess? {
val indicator = currentCompletionProgressIndicator
if (indicator != null) {
return indicator
currentCompletionProgressIndicator?.let {
return it
}
// TODO we have to move myApiCompletionProcess inside per client service somehow
// also shouldn't we delegate here to base method instead of accessing the field of the base class?
return if (isCurrentlyUnderLocalId) myApiCompletionProcess else null
return if (isCurrentlyUnderLocalId) apiCompletionProcess else null
}
private class CompletionResultSetImpl(consumer: Consumer<in CompletionResult>?, prefixMatcher: PrefixMatcher?,
contributor: CompletionContributor?, parameters: CompletionParameters?,
sorter: CompletionSorter?, original: CompletionResultSetImpl?) : BaseCompletionResultSet(consumer,
prefixMatcher,
contributor,
parameters,
sorter,
original) {
private class CompletionResultSetImpl(consumer: java.util.function.Consumer<in CompletionResult>?,
prefixMatcher: PrefixMatcher?,
contributor: CompletionContributor?,
parameters: CompletionParameters?,
sorter: CompletionSorter?,
original: CompletionResultSetImpl?) :
BaseCompletionResultSet(consumer, prefixMatcher, contributor, parameters, sorter, original) {
override fun addAllElements(elements: Iterable<LookupElement>) {
CompletionThreadingBase.withBatchUpdate({ super.addAllElements(elements) }, myParameters.process)
CompletionThreadingBase.withBatchUpdate({ super.addAllElements(elements) }, parameters.process)
}
override fun passResult(result: CompletionResult) {
val element = result.lookupElement
if (element != null && element.getUserData(LOOKUP_ELEMENT_CONTRIBUTOR) == null) {
element.putUserData(LOOKUP_ELEMENT_CONTRIBUTOR, myContributor)
element.putUserData(LOOKUP_ELEMENT_CONTRIBUTOR, contributor)
}
super.passResult(result)
}
@@ -164,11 +157,21 @@ open class CompletionServiceImpl : BaseCompletionService() {
return this
}
return CompletionResultSetImpl(consumer, matcher, myContributor, myParameters, mySorter, this)
return CompletionResultSetImpl(consumer = consumer,
prefixMatcher = matcher,
contributor = contributor,
parameters = parameters,
sorter = sorter,
original = this)
}
override fun withRelevanceSorter(sorter: CompletionSorter): CompletionResultSet {
return CompletionResultSetImpl(consumer, prefixMatcher, myContributor, myParameters, sorter, this)
return CompletionResultSetImpl(consumer = consumer,
prefixMatcher = prefixMatcher,
contributor = contributor,
parameters = parameters,
sorter = sorter,
original = this)
}
override fun addLookupAdvertisement(text: String) {
@@ -176,15 +179,14 @@ open class CompletionServiceImpl : BaseCompletionService() {
}
override fun restartCompletionOnPrefixChange(prefixCondition: ElementPattern<String>) {
val process = myParameters.process
val process = parameters.process
if (process is CompletionProcessBase) {
process
.addWatchedPrefix(myParameters.offset - prefixMatcher.prefix.length, prefixCondition)
process.addWatchedPrefix(parameters.offset - prefixMatcher.prefix.length, prefixCondition)
}
}
override fun restartCompletionWhenNothingMatches() {
val process = myParameters.process
val process = parameters.process
if (process is CompletionProgressIndicator) {
process.lookup.isStartCompletionWhenNothingMatches = true
}
@@ -208,14 +210,15 @@ open class CompletionServiceImpl : BaseCompletionService() {
}
override fun getVariantsFromContributor(params: CompletionParameters, contributor: CompletionContributor, result: CompletionResultSet) {
runWithSpan(completionTracer, contributor.javaClass.simpleName) { span: Span ->
super.getVariantsFromContributor(params, contributor, result)
span.setAttribute("avoid_null_value", true)
}
completionTracer.spanBuilder(contributor.javaClass.simpleName)
.setAttribute("avoid_null_value", true)
.useWithScopeBlocking {
super.getVariantsFromContributor(params, contributor, result)
}
}
override fun performCompletion(parameters: CompletionParameters, consumer: Consumer<in CompletionResult>) {
runWithSpan(completionTracer, "performCompletion") { span: Span ->
completionTracer.spanBuilder("performCompletion").useWithScopeBlocking { span ->
val countingConsumer = object : Consumer<CompletionResult> {
@JvmField
var count: Int = 0
@@ -248,10 +251,7 @@ private class ClientCompletionService(private val appSession: ClientAppSession)
ThreadingAssertions.assertEventDispatchThread()
val oldPhase = this.completionPhase
val oldIndicator = oldPhase.indicator
if (oldIndicator != null &&
phase !is BgCalculation &&
oldIndicator.isRunning &&
!oldIndicator.isCanceled) {
if (oldIndicator != null && phase !is BgCalculation && oldIndicator.isRunning && !oldIndicator.isCanceled) {
LOG.error("don't change phase during running completion: oldPhase=$oldPhase")
}
val wasCompletionRunning = isRunningPhase(oldPhase)
@@ -262,8 +262,7 @@ private class ClientCompletionService(private val appSession: ClientAppSession)
}
Disposer.dispose(oldPhase)
val phaseTrace = Throwable()
completionPhaseHolder = CompletionPhaseHolder(phase = phase, phaseTrace = phaseTrace)
completionPhaseHolder = CompletionPhaseHolder(phase = phase, phaseTrace = Throwable())
}
}

View File

@@ -1,3 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.testFramework.fixtures;
import com.intellij.codeInsight.completion.CompletionPhase;
@@ -21,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
public class CompletionAutoPopupTester {
public final class CompletionAutoPopupTester {
private final CodeInsightTestFixture myFixture;
public CompletionAutoPopupTester(CodeInsightTestFixture fixture) {
@@ -44,9 +45,11 @@ public class CompletionAutoPopupTester {
}
public void joinCompletion() {
waitPhase(phase -> !(phase instanceof CompletionPhase.CommittingDocuments ||
phase instanceof CompletionPhase.Synchronous ||
phase instanceof CompletionPhase.BgCalculation));
waitPhase(phase -> {
return !(phase instanceof CompletionPhase.CommittingDocuments ||
phase instanceof CompletionPhase.Synchronous ||
phase instanceof CompletionPhase.BgCalculation);
});
}
@SuppressWarnings("UseOfSystemOutOrSystemErr")
@@ -112,5 +115,4 @@ public class CompletionAutoPopupTester {
joinCompletion();
}
}
}