IntelliJ DocumentListener gives an internally inconsistent event stream
I'm using a DocumentListener to listen to changes to the document. I record each change in a file, and reconstruct the document from those events using a simple StringBuilder. Unfortunately, the reconstructed document is inconsistent because:
- One event that's generated is a modification with the text IntellijIdeaRulezzz. This event is not immediately canceled by IDEA.
- The Rulezzz event is canceled (text removed) at an arbitrary distance away from when the text was inserted. It doesn't have to happen immediately after, it can happen several edits away from when it was inserted.
- IDEA sometimes generates insertion events for very large chunks of already-written code. For example, I have a toString() implementation and all of a sudden I get a DocumentEvent where the NewText is half of the method's body. Now, this would be OK but the event is sent with incorrect offset/length, meaning that instead of using this event as-is I need to discard it.
- IDEA sometimes generates duplicate DocumentEvents resulting in a single typed character being added twice. I see no consistent way of detecting that an event is duplicate. This is typically a re-broadcast that followes a Rulezzz removal event, but not consistently so.
Please note that my implementation is a port of identical code being used in ReSharper, and ReSharper does it perfectly: all its ranges and insertions are internally consistent without duplication.
Here is an example of the kind of input I capture. I appreciate any suggestions/ideas you might have on how one could coalesce the event stream into the original document.
Please sign in to leave a comment.
It looks like you're listening to changes in all documents at once, probably adding listener via EditorFactory. IntellijIdeaRulezzz is inserted/removed into non-physical document used internally for code completion, it probably should be ignored by your listener. To listen to changes in a specific document only, please use document.addDocumentListener.
My exact code is
I really need to manage all documents that the user is editing, so for me it’s much simpler to take a
SelectionEvent.editor.documentto get the filename. Unfortunately, every single instance of the document has a valid non-nullfilename. So how am I meant to detect non-physical documents?Where do selection events come from? Document changes aren't in any way related to selection.
FileDocumentManager#getFile will return some file for the document, possibly non-physical. You can check if the file is #isInLocalFileSystem, for example.