Write access is allowed inside write-action in command in test
I have some plugin code I'm developing that does a simple modification to a Java class, to add an annotation. I've previously written another small plugin to do similar modifications, which worked fine. For the first plugin I didn't write any tests, for the second one I have written a test by extending the LightCodeInsightFixtureTestCase class.
My plugin code looks like this:
javaPsiFacade = JavaPsiFacade.getInstance(event.getProject());
elementFactory = javaPsiFacade.getElementFactory();
...
log("Looking for Java class of name: " + className);
PsiClass psiClass = javaPsiFacade.findClass(className, GlobalSearchScope.projectScope(project));
log("Found class: " + psiClass);
PsiIdentifier psiIdentifier = psiClass.getNameIdentifier();
log("identifier: " + psiIdentifier);
CommandProcessor.getInstance().executeCommand(project, () -> {
// find the class declaration and add the @Entity annotation
psiClass.addBefore(elementFactory.createAnnotationFromText("@javax.persistence.Entity", null), psiIdentifier);
}, "Plugin name", "PluginGroup");
However when running the test I get the dreaded:
ERROR: Assertion failed: Write access is allowed inside write-action only (see com.intellij.openapi.application.Application.runWriteAction())
I'm confused because I used the CommandProcessor in my previous plugin and it seemed to work fine. Have I got an issue with it here? Or is this something to do with the test setup that I need to do?
Thanks for any advice.
Please sign in to leave a comment.
I think this isn't test-specific, and you probably get the same issue in production.
As the exception says, write access (and you're modifying, AKA writing to, PSI) is only allowed in a write action. So you need not only CommandProcessor, but also WriteAction.run. You can combine them both in one wrapper, namely WriteCommandAction.runWriteCommandAction.
Many thanks for the fast response, I've confirmed the code runs correctly in the test if I use WriteCommandAction.runWriteCommandAction.
I'm a bit confused how my previous small plugin worked given that I used the CommandProcessor.getInstance().executeCommand!?
Any ideas how that code managed to work? On some occasions does the platform automatically start a write action?
Anyway I'll update my old code to use WriteCommandAction as well.
Thanks.
It depends very much on the code. Maybe it didn't change any physical PSI, or someone else took write action for you (this can happen with intentions/quick fixes, and you can look for "WriteAction" in the stack trace)