Search code examples
intellij-plugin

Text Field with Standard PsiElement Auto Completion in IntelliJ Plugin


I'm trying to create a simple text field with auto completion for my IntelliJ plugin. I think this should be pretty simple but so far I've run into dead ends...

E.g. this should work as far as I understand:

EditorTextField format = new TextFieldWithCompletion(currentEditor.getProject(),
                provider,
                "",
                true,
                true,
                true);

The problem is the provider. I'd expect to see a provider that isn't a list provider. I just want to show the completion matching the current line in the editor cursor so I'd like the full completion dialog and not just a short list of options.

I also looked at TextFieldWithAutoCompletion but it seems to be designed for hardcoded string values instead of free form completion.

I just want the standard Java/Kotlin completion. Not a custom list or anything like that. I saw some discussion with replacing the document of the text field but I couldn't get that to work either. I have a PsiExpressionCodeFragment and would expect there to be a completion provider that accepts that but I can't find it.

For reference what I want to do is something very similar to the conditional statement in the breakpoint dialog.

Another approach illustrated here is:

JavaCodeFragmentFactory jcff = JavaCodeFragmentFactory.getInstance(currentEditor.getProject());
PsiFile pf = PsiDocumentManager.getInstance(currentEditor.getProject()).getPsiFile(currentEditor.getDocument());
PsiElement psiElement = pf.findElementAt(currentEditor.getCaretModel().getOffset());
PsiExpressionCodeFragment fragment = jcff.createExpressionCodeFragment("", psiElement,null, false);
EditorTextField f = new EditorTextField(PsiDocumentManager.getInstance(currentEditor.getProject()).getDocument(fragment),
        currentEditor.getProject(),
        FileTypes.PLAIN_TEXT, false, true);

This loads the UI but doesn't popup code completion no matter what I type.


Solution

  • The trick is to create an editor that contains an instance of the Document. And this document refers to a language and a psi element context:

    JPanel panel = new JPanel();
    
    // Just detect an element under caret for context
    PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument());
    PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset());
    
    PsiExpressionCodeFragment code = JavaCodeFragmentFactory.getInstance(editor.getProject()).createExpressionCodeFragment("", element, null, true);
    Document document = PsiDocumentManager.getInstance(editor.getProject()).getDocument(code);
    
    EditorTextField myInput = new EditorTextField(document, editor.getProject(), JavaFileType.INSTANCE);
    myInput.setPreferredWidth(300);
    
    panel.add(myInput);
    
    return panel;
    
    

    Here the caret used to be located on dsa5, so the dsa5 variable is not yet visible for the completion.

    enter image description here