In CompletionContributer my elements are LeafPsiElement???


I'm trying to implement autocompletion for my custom language. I've implemented a completion contributor, and trying to make a decision based on the type of the PSI element at the current position. The problem is that `parameters.getPosition().getOriginalElement()` returns instance of class `LeafPsiElement` instead of my language PSI elements. Wondering if anyone else had this issue and what would be steps to troubleshoot.



Traverse up on element.getParent() until you reach your desired element or PsiFile. The latter means your element is not available at position.


Indeed, I try to go up and the parent of the element is FileElement. 



Actually it seems like none of the elements in the tree are of my custom language types, they are all LeafPsiElements or whitespaces. In debugger they all have correct values and myType shows correct token type (even though I don't see how can I access the token type in the code). 



Completion inserts Intellij dummy identifier at caret position. Does your grammar properly parse the resulting text? 

Default dummy identifier is "IntellijIdeaRulezzz " and can be changed in CompletionContributor.beforeCompletion by setting context.setDummyIdentifier()

In my plugin I use  "\u001f" for the dummy identifier because it was easier to add to my markdown parser an extra character than a whole string.

Test your grammar by inserting the dummy identifier string in various elements you plan to use in completions.


Yes, I saw that "IntellijIdeaRulezzz" thing, lol, but this is not the issue I'm facing. I think there's something wrong with the way PSI tree is created. I tried to call PsiTreeUtil.findChildOfType(file, myPsiCustomElement.class) and got null. So it looks like PSI tree is not built properly. What should I look into?



You can use PsiViewer plugin to see the PSI tree for the file at caret position. It is very useful for getting a detailed look at what PSI is created without having to write code to inspect details. It also has a highlight option to highlight the span of text for the selected PSI element.

How are you creating the PSI tree?

I cannot comment on doing it with grammar kit since markdown is not a good candidate for grammar based parsing. I construct the PSI tree using a builder from my custom parse data.



What does your psi look like in PsiViewer?


Oddly enough, in PsiViewer I see my correct types. So why can't I see them in my completion provider?



OK, I think I understand what's going on. If the file is syntactically correct, I see the proper PSI tree. But while typing, obviously it is not syntactically correct, so I only see LeafPsiElements and white spaces. Is this how it should be? If yes, I guess I need to find a better way to generate autocompletion suggestions.



The trick is to make sure that your parser generates the right tree even if it is not quite syntactically correct. That is the hardest part.

You also have to make sure that insertion of the dummy identifier into a parseable file does not prevent the parser from generating expected PSI tree. 

That is why I recommended testing the parser by inserting the dummy identifier at various points in your file to make sure it does not break the results.

In my case I simply add the '\u001f' character to the valid set of characters for all elements that normally do not handle it. That way completion works without breaking the grammar. In your case using the default dummy identifier (with a space in it) breaks your grammar and results in unexpected psi tree.

Try setting the dummy identifier to CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED that way at least it will not insert unexpected spaces into identifier elements.



Please sign in to leave a comment.