public abstract class CompletionContributor
extends java.lang.Object
Q: How do I implement code completion?
A: Define a com.intellij.completion.contributor
extension of type CompletionContributor
.
Or, if the place you want to complete in contains a PsiReference
, just return the variants
you want to suggest from its PsiReference.getVariants()
method as String
s,
PsiElement
s, or better LookupElement
s.
Q: OK, but what to do with CompletionContributor?
A: There are two ways. The easier and preferred one is to provide constructor in your contributor and register completion providers there:
extend(CompletionType, ElementPattern, CompletionProvider)
.
A more generic way is to override default fillCompletionVariants(CompletionParameters, CompletionResultSet)
implementation
and provide your own. It's easier to debug, but harder to write.
Q: How do I get automatic lookup element filtering by prefix?
A: When you return variants from reference (PsiReference.getVariants()
), the filtering will be done
automatically, with prefix taken as the reference text from its start (PsiReference.getRangeInElement()
) to
the caret position.
In CompletionContributor
you will be given a CompletionResultSet
which will match LookupElement
s against its prefix matcher CompletionResultSet.getPrefixMatcher()
.
If the default prefix calculated by the IDE doesn't satisfy you, you can obtain another result set via
CompletionResultSet.withPrefixMatcher(PrefixMatcher)
and feed your lookup elements to the latter.
It's one of the item's lookup strings (LookupElement.getAllLookupStrings()
that is matched against prefix matcher.
Q: How do I plug into those funny texts below the items in shown lookup?
A: Use CompletionResultSet.addLookupAdvertisement(String)
.
Q: How do I change the text that gets shown when there are no suitable variants at all?
A: Use handleEmptyLookup(CompletionParameters, Editor)
.
Don't forget to check whether you are in correct place (see CompletionParameters
).
Q: How do I affect lookup element's appearance (icon, text attributes, etc.)?
A: See LookupElement.renderElement(LookupElementPresentation)
.
Q: I'm not satisfied that completion just inserts the item's lookup string on item selection. How to make it write something else?
A: See LookupElement.handleInsert(InsertionContext)
.
Q: What if I select item with TAB key?
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 beforeCompletion(CompletionInitializationContext)
by putting new offset to CompletionInitializationContext.getOffsetMap()
as CompletionInitializationContext.IDENTIFIER_END_OFFSET
.
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,
so I'd be happy to filter out 42 of them. How do I do this?
A: This is a bit harder than just adding variants. First, you should invoke
CompletionResultSet.runRemainingContributors(CompletionParameters, Consumer)
.
The consumer you provide should pass all the lookup elements to the CompletionResultSet
given to you, except for the ones you wish to filter out. Be careful: it's too easy to break completion this way. Since you've
ordered to invoke remaining contributors yourself, they won't be invoked automatically after yours finishes (see
CompletionResultSet.stopHere()
and CompletionResultSet.isStopped()
).
Calling CompletionResultSet.stopHere()
explicitly will stop other contributors (which happened to be loaded after yours)
from execution, and the user will never see their so useful and precious completion variants, so please be careful with this method.
Q: How are lookup elements sorted?
A: Basically in lexicographic order, ascending, by lookup string (LookupElement.getLookupString()
).
Also there's a number of "weigher" extensions under "completion" key (see CompletionWeigher
) that bubble up the most relevant
items. To control lookup elements order you may implement CompletionWeigher
or use PrioritizedLookupElement
.
To debug the order of the completion items use 'Dump lookup element weights to log
' 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.
Q: Elements in the lookup are sorted in an unexpected way, the weights I provide are not honored, why?
A: To be more responsive, when first lookup elements are produced, completion infrastructure waits for some small time
and then displays the lookup with whatever items are ready. After that, few the most relevant of the displayed items
are considered "frozen" and not re-sorted anymore, to avoid changes around the selected item that the user already sees
and can interact with. Even if new, more relevant items are added, they won't make it to the top of the list anymore.
Therefore you should try to create the most relevant items as early as possible. If you can't reliably produce
most relevant items first, you could also return all your items in batch via CompletionResultSet.addAllElements(java.lang.Iterable<? extends com.intellij.codeInsight.lookup.LookupElement>)
to ensure
that this batch is all sorted and displayed together.
Q: My completion is not working! How do I debug it?
A: One source of common errors is that the pattern you gave to extend(CompletionType, ElementPattern, CompletionProvider)
method
may be incorrect. To debug this problem you can still override fillCompletionVariants(CompletionParameters, CompletionResultSet)
in
your contributor, make it only call its super and put a breakpoint there.
If you want to know which contributor added a particular lookup element, the best place for a breakpoint will be
CompletionService.performCompletion(CompletionParameters, Consumer)
. The consumer passed there
is the 'final' consumer, it will pass your lookup elements directly to the lookup.
If your contributor isn't even invoked, probably there was another contributor that said 'stop' to the system, and yours happened to be ordered after
that contributor. To test this hypothesis, put a breakpoint to
CompletionService.getVariantsFromContributors(CompletionParameters, CompletionContributor, PrefixMatcher, Consumer)
,
to the 'return' line.
Q: My completion contributor has to get its results from far away (e.g., blocking I/O or internet). How do I do that?
A: To avoid UI freezes, your completion thread should be cancellable at all times.
So it's a bad idea to do blocking requests from it directly since it runs in a read action,
and if it can't do ProgressManager.checkCanceled()
and therefore any attempt to type in a document will freeze the UI.
A common solution is to start another thread, without read action, for such blocking requests,
and wait for their results in completion thread. You can use ApplicationUtil.runWithCheckCanceled(java.util.concurrent.Callable<T>, com.intellij.openapi.progress.ProgressIndicator)
for that.
Q: How can I trigger showing completion popup programmatically?
A: See AutoPopupController
.
Q: The suggestion popup hides when I type some exotic character but I want completion keep going matching against typed character.
A: See CharFilter.acceptChar(char, int, com.intellij.codeInsight.lookup.Lookup)
.
Modifier and Type | Field and Description |
---|---|
static ExtensionPointName<CompletionContributorEP> |
EP |
Constructor and Description |
---|
CompletionContributor() |
Modifier and Type | Method and Description |
---|---|
java.lang.String |
advertise(CompletionParameters parameters)
Deprecated.
|
void |
beforeCompletion(CompletionInitializationContext context)
Invoked before completion is started.
|
void |
duringCompletion(CompletionInitializationContext context)
Invoked in a read action in parallel to the completion process.
|
void |
extend(CompletionType type,
ElementPattern<? extends PsiElement> place,
CompletionProvider<CompletionParameters> provider) |
void |
fillCompletionVariants(CompletionParameters parameters,
CompletionResultSet result)
The main contributor method that is supposed to provide completion variants to result, based on completion parameters.
|
static java.util.List<CompletionContributor> |
forLanguage(Language language) |
static java.util.List<CompletionContributor> |
forLanguageHonorDumbness(Language language,
Project project) |
static java.util.List<CompletionContributor> |
forParameters(CompletionParameters parameters) |
AutoCompletionDecision |
handleAutoCompletionPossibility(AutoCompletionContext context)
Called when the completion is finished quickly, lookup hasn't been shown and gives possibility to auto-insert some item (typically - the only one).
|
java.lang.String |
handleEmptyLookup(CompletionParameters parameters,
Editor editor) |
boolean |
invokeAutoPopup(PsiElement position,
char typeChar)
Deprecated.
Don't use this method, because
position can come from uncommitted PSI and be totally unrelated to the code being currently in the document/editor.
Please consider using TypedHandlerDelegate.checkAutoPopup(char, com.intellij.openapi.project.Project, com.intellij.openapi.editor.Editor, com.intellij.psi.PsiFile) instead. |
public static final ExtensionPointName<CompletionContributorEP> EP
public final void extend(CompletionType type, ElementPattern<? extends PsiElement> place, CompletionProvider<CompletionParameters> provider)
public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result)
CompletionProvider
s you could register by
invoking extend(CompletionType, ElementPattern, CompletionProvider)
from your contributor constructor,
matches the desired completion type and ElementPattern
with actual ones, and, depending on it, invokes those
completion providers.
If you want to implement this functionality directly by overriding this method, the following is for you.
Always check that parameters match your situation, and that completion type (CompletionParameters.getCompletionType()
is of your favourite kind. This method is run inside a read action. If you do any long activity non-related to PSI in it, please
ensure you call ProgressManager.checkCanceled()
often enough so that the completion process
can be cancelled smoothly when the user begins to type in the editor.
public void beforeCompletion(CompletionInitializationContext context)
@Deprecated public java.lang.String advertise(CompletionParameters parameters)
CompletionResultSet.addLookupAdvertisement(String)
public java.lang.String handleEmptyLookup(CompletionParameters parameters, Editor editor)
public AutoCompletionDecision handleAutoCompletionPossibility(AutoCompletionContext context)
@Deprecated public boolean invokeAutoPopup(PsiElement position, char typeChar)
position
can come from uncommitted PSI and be totally unrelated to the code being currently in the document/editor.
Please consider using TypedHandlerDelegate.checkAutoPopup(char, com.intellij.openapi.project.Project, com.intellij.openapi.editor.Editor, com.intellij.psi.PsiFile)
instead.public void duringCompletion(CompletionInitializationContext context)
CompletionInitializationContext.setReplacementOffset(int)
)
if it takes too much time to spend it in beforeCompletion(CompletionInitializationContext)
,
e.g. doing PsiElement.findReferenceAt(int)
Guaranteed to be invoked before any lookup element is selectedcontext
- contextpublic static java.util.List<CompletionContributor> forParameters(CompletionParameters parameters)
public static java.util.List<CompletionContributor> forLanguage(Language language)
public static java.util.List<CompletionContributor> forLanguageHonorDumbness(Language language, Project project)