How do I add a completion contributor for a composite element?
I need to add additional entries to the completion dialog for method references (e.g. Objects::toString). The article says that I need to use withParent or withSuperParent for composite elements, but none of them works.
PSIViewer says that PsiMethodReferenceExpression is direct parent of the toString identifier, so when I define the following element pattern
PlatformPatterns.psiElement(JavaTokenType.IDENTIFIER).withParent(PsiMethodReferenceExpression.class)
or
PlatformPatterns.psiElement(PsiIdentifier.class).withParent(PsiMethodReferenceExpression.class)
it does not work. If I remove the .withParent(...) part the additional entries in the completion dialog are present everywhere.
Notice: For the specified element pattern the entries appears in the completion dialog for Objects:: (after the double colon)
The completion contribution class looks like this:
public class MethodReferenceCompletion extends CompletionContributor {
public MethodReferenceCompletion() {
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement(PsiIdentifier.class).withParent(PsiMethodReferenceExpression.class),
new MethodReferenceCompletionProvider()
);
}
}
Please sign in to leave a comment.
I came up with a partial solution, which covers the following patterns (adds entries to the completion dialog after a method reference name):
But the solution also covers the following false-positive pattern:
because PsiMethodReferenceExpression happens to inherit PsiReferenceExpression
How can I simplify it and eliminate the false-positive case?
The current version of the class:
public class MethodReferenceCompletion extends CompletionContributor {
public MethodReferenceCompletion() {
final PsiElementPattern.Capture<PsiElement> methodLocation = psiElement()
.afterLeafSkipping(
psiElement()
.withParent(PsiMethodReferenceExpression.class)
.withText("::")
.afterSibling(psiElement(PsiReferenceParameterList.class)),
psiElement()
);
final PsiElementPattern.Capture<PsiElement> doubleColumnLocationAfter = psiElement().afterLeaf("::");
final PsiElementPattern.Capture<PsiElement> parameterListLocationAfter = psiElement().afterLeaf("<", ">");
final PsiElementPattern.Capture<PsiElement> parameterListLocationBefore = psiElement().beforeLeaf("<", ">");
final PsiElementPattern.Capture<PsiElement> classLocation = psiElement().beforeLeaf(psiElement().withText("::"));
final PsiElementPattern.Capture<PsiElement> firstParenthesisLocation = psiElement().beforeLeafSkipping(psiElement().withText("::"), psiElement().beforeLeaf("("));
final PsiElementPattern.Capture<PsiElement> place = methodLocation
.andNot(firstParenthesisLocation)
.andNot(classLocation)
.andNot(doubleColumnLocationAfter)
.andNot(parameterListLocationAfter)
.andNot(parameterListLocationBefore)
;
extend(
CompletionType.BASIC,
place
,new MethodReferenceCompletionProvider()
);
}
}