Plugin creating multiple files in bulk/batch/grouped events/ mode
I'm developing a plugin that provides an action that creates multiple files according to certain rules.
To create the files, I am using Velocity templates which the plugin also provides.
Naturally, I am using com.intellij.ide.fileTemplates.JavaCreateFromTemplateHandler#createFromTemplate
to create each file.
The problem I'm having is that the use of the mentioned API leads to the creation of each file being fired off as a separate VFS event.
This creates some difficulties for another plugin of mine which listens to VFS changes.
It would be best if I could somehow group those events corresponding to the created files.
I would express it like so:
withBulkVfsChange(() -> createMyFiles())
Is there a way to achieve this? I suspect that I would need to expand the templates and create the corresponding files manually, instead of using JavaCreateFromTemplateHandler
.
Please sign in to leave a comment.
I can see that
JavaCreateFromTemplateHandler
is callingPsiDirectory#add
for each file, thus triggering a separate event.Let's say I create all my files manually using
java.nio.file
, how would I then notify the VFS about all of them at once?Hi,
Did you try implementing
com.intellij.openapi.vfs.newvfs.BulkFileListener
?Karol Lewandowski Yes, I did implement it in the plugin that listens for VFS events. However, I'm currently interested in ways of controlling the notifications about the VFS, not in the listening itself.
I experimented a bit and noticed that if I create a bunch of files externally during AnAction, then they nicely arrive grouped together in a single VFS event when the action completes. However, if I also try to reformat each file, then I need to refresh the VFS to get the corresponding VirtualFile, which causes them to arrive one-by-one… And I guess there is no way around this, that is, forcing the event to be ignored while still obtaining the VirtualFile, since this would probably break stuff.
I see.
I don't know of any API allowing you to do what you want. It sounds like a very low-level task.
Creating files outside VFS just to call the listener with an expected batch of files, even if it was possible, doesn't seem like a good approach.
What is your exact use case? Why do you need the event list to exactly match the list of files that you created?
The plugin that listens to VFS events does some work whenever a new file is created or an existing one is saved. So when my other plugin creates multiple files, the listening plugin kicks in several times, depending on the number of files created. This is inconvenient as it is much slower than kicking in only once for all files together.
Did you measure the difference in execution time between the two approaches? Maybe I'm wrong, but it sounds like a premature optimization.
I haven't implemented the other approach yet (the one where I try to group the files) so I haven't had the opportunity to compare them. However, while the execution time is certainly the most significant factor, it is not the sole one. This is because the listening plugin is performing compilation of incoming Java files, and this process is displayed to the user in the build window. So what I have right now is multiple builds following each another far too quickly for them to be observed, which is far from good user experience. There you have another factor beside performance.
I think that a better approach would be implementing your own listener that will listen to the creation of multiple files and handle them all at once. Handling it with VFS events, as you noticed, ends up in trying to use “hacks” like creating files on the actual file system. Relying on such behaviors is fragile, as it may change in the future.
I ended up doing something along those lines: implemented a synchronisation mechanism to facilitate communication between my plugins. The one that creates files informs the other one (which is expecting them) to temporarily suspend itself until all files have been created.
Coming back to the question of performance. The overhead of synchronisation is tiny - I haven't noticed it at all. In fact, the overall execution time decreased. And user experience improved, as expected. So far so good.
Karol Lewandowski Thank you for assistance.