Why is PsiTreeChangeAdapter#beforeChildrenChange fired after BulkFileListener#after ?

Hello,

I have two listeners in my plugin:

public class FileSaveListener implements ApplicationComponent, BulkFileListener {

    @Override
     /**
     * Executes after file(s) are saved to the disc. Note it does not happen immediately if you type new code
     */
     public void after(@NotNull List<? extends VFileEvent> events) {
        // start my logic
     }

}


and

PsiManager.getInstance(project).addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
     @Override
      /**
       * // executes on every small change in the editor
       */
      public void beforeChildrenChange(@NotNull PsiTreeChangeEvent event) {
         // stop my logic if currently executing
      }
}



What I want to achieve:

- after file is saved: execute my logic
- if file is changed in editor (but not yet saved to disc) then stop any executing logic

My Problem:

After I have edited a file and press "Save All Files (Ctrl+S)" then first BulkFileListener#after (file saved) is fired and then the PsiTreeChangeAdapter#beforeChildrenChange (file changed in editor), why ?
What is the proper way to achieve what I need?

3 comments

The reasons for that ordering are motivated by internal architectural needs and complicated. It depends on the reason that PSI event was fired, which is unclear to me. A stacktrace could shed some light on that.

But anyway I feel you need another way to process things. If you want to react to editor typing, it's better to listen for document changes, not PSI. EditorFactory.getEventMulticaster().addDocumentListener() will help.

And it's most probably not the best idea to have any logic in the listener. There might be thousands of events and the logic will just slow down everything. It'd be better to delay the logic, running it in a background thread or at least "later". Classes like Alarm or MergingUpdateQueue, together with Application.executeOnPooledThread might be of interest.

0

there is no stacktrace because there is no error ;-)

> If you want to react to editor typing, it's better to listen for document changes, not PSI. EditorFactory.getEventMulticaster().addDocumentListener() will help.

That's what I need, Thank you very much, will try it!

>And it's most probably not the best idea to have any logic in the listener. There might be thousands of events and the logic will just slow down everything. It'd be better to delay the logic, running it in a background thread or at >least "later". Classes like Alarm or MergingUpdateQueue, together with Application.executeOnPooledThread might be of interest.

nice tip, thanks again, will keep it in mind.

0

To get a stacktrace, you can always do new Throwable().printStackTrace(), or pause on a breakpoint and invoke "Get thread dump" action.
That said, I'm not that interested in the stacktrace :) If you really want to know what's happening, you can provide it. But those events happen and it's quite expected that at least some of them would happen on save.

0

Please sign in to leave a comment.