Autocompletion inserting at a wrong position Follow
I'm writing a custom language plugin where you can invoke autocompletion. But when I choose an item from the pop up, it doesn't insert where my caret is but goes to start of the line and inserts it from there. To give you guys a better idea, I have attached two screen shots.
I invoke the popup after the token * but when I choose the item it removes it and places it on the start of the line. Should I do something to handle proper insertion of the auto completed item. Since it is inserted without a * , it changes the token type also.
Attachment(s):
2.png
1.png
Please sign in to leave a comment.
The default matching prefix starts for some reason from the beginning of the line. By debugging in com.intellij.codeInsight.completion.impl.CompletionServiceImpl#createResultSet, you can check why. com.intellij.codeInsight.completion.CompletionResultSet#withPrefixMatcher gives you a possibility to change that prefix.
I debugged and saw that the prefix matcher is working fine. It sets the prefix to "* ". I even changed the prefix matcher from CamelHumpMatcher which is by default to PlainPrefixMatcher. But still it inserts before *
resultSet.withPrefixMatcher(new PlainPrefixMatcher(resultSet.getPrefixMatcher().getPrefix()));
It is not because of the prefix being the start of the line. If I try to give some spaces before * and auto complete in the middle of the file, then it gets added just before the *, it doesn't go to the start of the line. I have attached the screenshots
Furthermore, I have attached the psi structure also. If they are not parsed fine (i.e) some error is present in the above lines. The identifier(*) and the Step text won't get created as children to a Step. Then when I auto complete, it gets inserted correcltly. Is it something to do with the psi structure ?
Attachment(s):
prefix working fine.png
insert in the middle.png
autocomplete in the middle.png
psistructure.jpg
Thanks! So the asterisk is the part of prefix, and it's replaced. Is this the desired behavior? If not, you should probably change the prefix so that it doesn't include the asterisk.
I tried removing the * from the prefix matcher,
resultSet.withPrefixMatcher(new PlainPrefixMatcher(""));
still doesn't seem to work. I have edited the above post to give further info.
Do you have a custom insert handler in your items? It could be removing the spaces, or invoking reformat which does this.
I'd suggest to put a breakpoint to DocumentImpl.changedUpdate, then you'll see all document changes made during completion and you'll surely understand what's happening and why.
I haven't added the custom insert handler yet. I debugged the DocumentImpl.changedUpdate after the autocompletion and saw that the event has
myOldString='*', myNewString='task1' if there is no parse error above
myOldString='', myNewString='task1' if there is a parse error above
I'm just so confused why this is happening. It should just insert the text that I want at the cursor position by default. I don't do any sort of manipulation after the insertion.
When debugging, you can also see the stack trace of the event. Please provide it. "Get Thread Dump" debugger action might be useful for that purpose.
This is the thread dump I got just before the insertion. If you guys want, i can zip the plugin project and send it to you guys.
"AWT-EventQueue-0 13.1.3#IU-135.909, eap:false [WriteAccessToken]@2391" prio=6 tid=0x1a nid=NA runnable
java.lang.Thread.State: RUNNABLE
at com.intellij.openapi.editor.impl.DocumentImpl.a(DocumentImpl.java:764)
at com.intellij.openapi.editor.impl.DocumentImpl.a(DocumentImpl.java:716)
at com.intellij.openapi.editor.impl.DocumentImpl.a(DocumentImpl.java:596)
at com.intellij.openapi.editor.impl.DocumentImpl.replaceString(DocumentImpl.java:551)
at com.intellij.codeInsight.lookup.impl.LookupImpl$8.perform(LookupImpl.java:725)
at com.intellij.openapi.editor.impl.CaretModelImpl$3.run(CaretModelImpl.java:355)
at com.intellij.openapi.editor.impl.CaretModelImpl.doWithCaretMerging(CaretModelImpl.java:426)
at com.intellij.openapi.editor.impl.CaretModelImpl.runForEachCaret(CaretModelImpl.java:349)
at com.intellij.codeInsight.lookup.impl.LookupImpl.a(LookupImpl.java:713)
at com.intellij.codeInsight.lookup.impl.LookupImpl.access$800(LookupImpl.java:93)
at com.intellij.codeInsight.lookup.impl.LookupImpl$7.run(LookupImpl.java:659)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:984)
at com.intellij.codeInsight.lookup.impl.LookupImpl.finishLookup(LookupImpl.java:655)
at com.intellij.codeInsight.lookup.impl.LookupImpl.finishLookup(LookupImpl.java:612)
at com.intellij.codeInsight.lookup.impl.actions.ChooseItemAction$Handler.execute(ChooseItemAction.java:73)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.doExecute(EditorActionHandler.java:93)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.execute(EditorActionHandler.java:125)
at com.intellij.openapi.editor.actionSystem.EditorAction$1.run(EditorAction.java:83)
at com.intellij.openapi.command.impl.CommandProcessorImpl.executeCommand(CommandProcessorImpl.java:124)
at com.intellij.openapi.editor.actionSystem.EditorAction.actionPerformed(EditorAction.java:94)
at com.intellij.openapi.editor.actionSystem.EditorAction.actionPerformed(EditorAction.java:68)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher$3.performAction(IdeKeyEventDispatcher.java:564)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.processAction(IdeKeyEventDispatcher.java:611)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.d(IdeKeyEventDispatcher.java:463)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.dispatchKeyEvent(IdeKeyEventDispatcher.java:206)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:493)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:335)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
It still looks like "* " is included into the prefix that a particular lookup item was matched against.
Yes, if you share your plugin project, it'll definitely make the investigation easier.
I have included both plugin as well as a sample project.
In that sample project I have two .spec files in which one with parse error handles the autocompletion properly and the other doesn't.
This might be helpful for http://devnet.jetbrains.com/thread/455962 also. I have explicilty mentioned empty prefix matcher for all the completion providers.
Just run the plugin and open the sample project.
Attachment(s):
project.tar.gz
plugin.tar.gz
withPrefixMatcher creates a new CompletionResultSet and doesn't change the old one. You should use it like this:
Ah!! I thought resultSet was a mutable object. Many thanks Peter.
I'll make IDEA highlight unused return values of withPrefixMatcher to avoid such confusion.
How can I remove the templates surround/B and surround/P? It seems like they are getting added to the resultSet before it reaches my completionProvider, so doing a resultSet.stopHere() is of no help.
It's an IDE-wide feature that live templates are suggested so please think again whether to interfere with it. But your contributor can register itself before the live template one add call resultSet.stopHere. To do that, you should add order="first,before liveTemplates" to the completion contributor extension tag in plugin.xml