DocumentEvent and PsiTreeChangeEvent fired many times

I need to run a compiler whenever a document changes. A compiler is a relatively slow process, so I only want to run it once per change, at most; and probably with some throttling. My first thought was to do either 

PsiManager.getInstance(project).addPsiTreeChangeListener

or

FileDocumentManager.getInstance().getCachedDocument(virtualFile).addDocumentListener

However, I find that on a single document change, both get fired 10 or more times. Why is that, and how can I invoke the compiler exactly once? I don't want to wait for the file to be saved, because my next step will be to turn compiler warnings and errors into annotations.

Edit: also tried  externalAnnotator, but my external annotator is never called. Is not it supposed to be called on file change? No errors in plugin.xml or console.

4 comments
Comment actions Permalink

Привет Ирина, 

document change events are triggered often. Nothing wrong with that. Calling external process on each event will slow down the program a lot.

 

here is another possibility:

init a repeat process on start. This process will run at regular intervals, trigger compiler and annotator.

 

To avoid compilation in idle:

listen to document change events. 

the listener(s) will save a timestamp of last change. Store this timestamp in a service.

the repeat process will check current time against last changed stamp (stored in service).

 

write if you need hints re: how to do any of these.

0
Comment actions Permalink

Привет Imants,

Thank you for your response. This is not an external process I am running. The compiler is Java code run in-process that I can modify a bit if I have to (but probably not a lot, given time constraints). It's Psi-aware and uses code generated by GrammarPlugin, wrapped into some fixtures to make it run standalone. 

Seems like a perfect candidate for externalAnnotator, does not it? Not sure why my externalAnnotator is never called. 

I can implement your solution, this sounds straightforward enough, but I wonder if there is a better way in light of the above.

So, document change events are triggered dozens of time per each character entered? What is the purpose of this? Just curious.

Спасибо!

Ирина

0
Comment actions Permalink

different event triggers are probably not aware of each other. They trigger event as soon as there is a reason to do so, without connection to other event triggers.

 

is externalAnnotator extension properly registered?

are all ExternalAnnotator methods implemented (overriden)? Note they are not abstract so easy to overlook.

0
Comment actions Permalink

There should be only one document change event (reported to listeners registered via Document.addDocumentListener) per character entered. Make sure you register only one listener or register it only once.

0

Please sign in to leave a comment.