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.

 

0
3 comments

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.

0

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.

0

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)

0

Please sign in to leave a comment.