FileEditorProvider Plugin: Using old code until closing editor


Hi, my plugin is a FileEditorProvider. I got this feedback from a customer:

After activating the licence, The plugin was still asking to get a license (even across restarts). I closed/opened the file by chance before I could use the plugin.

Now I had the same experience while developing. I used the “runIde” task from the Gradle plugin but over multiple runs (with the file editor in question already open) I kept getting the old code until I closed and opened the file editor my plugin was operating in.

Is there some kind of code cache in place?

Is there anything I can do from the plugin side to prevent this behaviour?

Or maybe I am doing something that prevents the code from being reloaded when the IDE restarts.


Hi Sven,

The case is unclear to me. Do you mean that you had an old plugin version loaded in the IDE and when you closed and opened a file, it switched to the new code?

What was old in the file and what was new after closing/opening? It is possible that highlighted problems in the file were cached (to improve perceived startup speed). To know if it is possible to disable this behavior, I must confirm this is it.

It would be great if you visualize what is happening (even in text).


I fixed a bug in my plugin. But it kept appearing in the editor window no matter how often I changed the code and restarted IntelliJ (with runIde). But the bug was immediately gone when I closed and opened the file editor again because it loaded the fixed code. It had nothing to do with the text editor. Just my plugin view.


Sorry, but I'm confused.

You say the bug was appearing in the editor window. Then you closed and opened the file editor, and the bug disappeared. And in the end, you say it had nothing to do with the text editor (but your plugin view, what view?). It seems to me that it has a lot with the editor. If I'm wrong, could you please clarify it? Please provide exact information on what happened, with screenshots, ideally.

BTW, how do you know it loaded the fixed code after closing/opening the editor? Is it somehow confirmed or you base on visual observations? If so, it is crucial to know what exactly you observe.


Okay. I try again.

runIde → old behavior → Close IntelliJ (without closing the file editor)

Change Code → runIde → still old behavior → close/open file editor → new behavior 

My Plugin is a FileEditorProvider so it adds a second view next to the usual text editor.

With IntelliJ I am referring to the second IDE I use to test the plugin.


So, I tried to reproduce it with a simpler example and at least the simple change behaved as it should. But I experienced the same effect as before. So it might be something different.

Anyway… the observation of the user stays the same. I will try if I can reproduce that.


Hi Sven,

One more question – when you open the IDE and see the old version - can you interact with the editor? By interacting with the editor, I mean writing or performing other actions. If you can, is the bug still visible even after interactions (without closing it)?


No, the UI didn’t look frozen. Right now I suspect a problem with my plugin code to cause this behavior. I have to look more into it. I will also try to reproduce what the user experienced. I will post once I have more information.


I investigated further… It seems the behaviour I witnessed happens because the file system is not in sync.

I download and save some files (so I don't have do download them again) in this folder: Paths.get(PathManager.getPluginsPath(), "XSDvisualizer", "cache")

I use Files.copy to save them. But when I try to open them with VirtualFileManager.getInstance().findFileByNioPath the Files are not there.

I need to put the download in a background task anyway. So, I have to figure out how to do that in sync with the file system at the same time. Any hints for that?


In my opinion, using plugins directory as a cache doesn't look good. I suggest saving the file somewhere else.

Why do you access this file via Virtual File System? Is it a binary file that helps perform some operations? If yes, I suggest accessing it via standard Java IO API. VFS may be not in sync with the underlying storage. If you must use VFS for some reason, you can try refreshing the file before access, e.g., with LocalFileSystem.refreshAndFindFileByIoFile.


So where else should I store it? It's the only path I could find that belongs to my plugin so I know it exists.

I use the VirtualFileSystem because I use the PsiManager to read it.

When I used VirtualFileManager.refreshAndFindFileByNioPath I got an exection saying something like I need read/write access. Because of the structure of my plugin it would be difficult to test LocalFileSystem.refreshAndFindFileByIoFile. Would it give me the same error?

Isn't there a best practice for plugins how to download and cache files?


I suggest using Paths.get(PathManager.getSystemPath(), "XSDvisualizer", "cache").

VFS makes sense in this case. VirtualFileManager.refreshAndFindFileByNioPath() is fine too, and the error should be the same in both cases. I see no other option than refreshing VFS before getting the file if VFS doesn't see it, so you will likely have to wrap it in a proper read or write action.


Thanks for your help. I should be able to make progress now. 


Now I had time to check the behaviour the user observed. In the latest version I started using TextEditorWithPreview. I found out that this class doesn't call the getComponent() methode of its parts once they are created. But my component uses the repeated call of this method to check the license. That's why it didn't notice when the user activated the license.

Maybe it would make sense to change this behaviour… Or there is a better way to regularly check for the license. For now I solved this by overriding the getComponent()method and pass the call to my editor.


Hi Sven,

I don't understand what changes you mean, but I assume the behavior was changed for a reason and it is probably an improvement. I wouldn't expect to revert it without an important reason.

Regarding the check, it is not required to put it in code executed frequently. You can create a service holding a flag and schedule refreshing a “licensed” flag (e.g., once per hour) and enable your plugin functionalities based on this flag.


I don't think TextEditorWithPreview was changed. I changed my code to put my editor inside of it instead of using my editor directly. And that's when the behaviour started that the license change wasn't detected.

Checking the license once per hour wouldn't work. My editor shows a message when there is no license together with a buttons that open the window to activate or buy a license. This user complained that the message didn't disappear once he activated the license. Which I agree with. He had to close and reopen the editor.

By checking the license in getComponent() I can make sure that the editor starts working immediately  after users purchased the license.


Please sign in to leave a comment.