6

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.

Shai Almog
  • 51,749
  • 5
  • 35
  • 65

1 Answers1

2

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

Feedforward
  • 4,521
  • 4
  • 22
  • 34
  • Thank you and merry Christmas/Happy Holidays! It won't let me award the 500 for the next 9 hours, I will once it allows it. It's stupid how I missed the Java argument there ;-) A couple of followup questions if you have an idea (fyi I'll award the 500 anyway so no pressure)... I have 2 fields not one. If I do this twice then both of them show the same content as I type (since they have the same doc). Also features such as setText() to initialize the text field with a value no longer work. Do you have an idea? – Shai Almog Dec 25 '19 at 02:54
  • 1
    Happy Holidays! 1) Yes, you have to create another instance of `Document` using another instance of `PsiExpressionCodeFragment`. This `code fragment` can be created using the same `PsiElement` as a context to get the same autosuggestion. 2) I'm not sure why `setText()` doesn't work, but speaking of this method you can initialize text with the first parameter of `createExpressionCodeFragment`. As for other features that don't work, I'm afraid they should be investigated separately. – Feedforward Dec 25 '19 at 08:22
  • Thanks! This is 100% solved now, in two hours I'll be able to grant the 500 bonus. BTW if you have an idea I have a followup question that's possibly harder posted here: https://stackoverflow.com/questions/59443789/text-field-with-standard-psielement-auto-completion-in-intellij-plugin – Shai Almog Dec 25 '19 at 09:24
  • 1
    You mean [this](https://stackoverflow.com/questions/59476930/limit-text-field-completion-to-a-specific-set-of-segments-within-intellij-plugin) question, right? Yes, it's possible using language injection. I'll try to provide an answer a bit later when I'll get a bit time for that (if no one answers faster), but for now you can, for instance, try to check the implementation in [Grammar-kit](https://github.com/JetBrains/Grammar-Kit) plugin. There are java code injections in `flex` files. – Feedforward Dec 25 '19 at 09:36
  • Yes, thanks... There's a lot of code in that project, I'm not exactly sure what I'm looking for – Shai Almog Dec 29 '19 at 12:21
  • I've banged my head against this quite a bit. Should I create a new language implementation for this? Do I need to use grammar-kit to do that or just look at it for reference. – Shai Almog Jan 01 '20 at 11:48
  • FYI the bounty in that question is really close to expiring if you have any answer now would be the time... – Shai Almog Jan 06 '20 at 02:20