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()
);
}
}

 

 

0

I came up with a partial solution, which covers the following patterns (adds entries to the completion dialog after a method reference name):

  1. Object::new.
  2. (Object::new).
  3. Collections::<Integer>sort.

But the solution also covers the following false-positive pattern:

System.

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()
);
}
}
0

请先登录再写评论。