How to save memory changes to disk, avoiding "File Cache Conflict"

Answered

I'm developing a custom language plugin, and I use a separate command line program to "format a single file". To do so, I add a "format code" action in editor pop menu, and then in the action's actionPerformed method,  I did following steps:

1. save the file content in memory to disk, to make sure everything saved.

2. execute the format command, which consumes a file path, analyse the file based on the file system, and produces the formatted code to std out stream.

3. replace the old document text by formatted code, via WriteCommandAction.runWriteCommandAction

Here is the problem, every time after I click the "format code" button, I can see the formatted code flushed in editor, but if I then save the code by type Ctrl+S shortcut, I get the "File Cache Conflict" warning dialog:

 

I click the "show different" button, then it says there's no difference between memory & disk:

 

So, how can I avoid that useless dialog?

 

My code:

public void actionPerformed(@NotNull AnActionEvent event) {
// make sure to save memory content to disk
SaveAllAction saveAllAction = new SaveAllAction();
saveAllAction.actionPerformed(event);

VirtualFile vFile = event.getData(PlatformDataKeys.VIRTUAL_FILE);
if (vFile == null) {
return;
}

// execute kcl --fmt -w command to get formatted content
String[] options = {"--fmt", vFile.getPath(), "-w"};
ExecuteResult result = KCLBinaryUtil.execKCLCmd(options);

if (!result.isSuccess() || result.getStdout() == null) {
return;
}
String formatted = result.getStdout();
// Replace the text content in editor with formatted string. Must do this document change in a write action context.
// See: https://jetbrains.org/intellij/sdk/docs/tutorials/editor_basics/working_with_text.html#safely-replacing-selected-text-in-the-document
final Project project = event.getRequiredData(CommonDataKeys.PROJECT);
final Document document = getDocument(event);
if (document != null) {
WriteCommandAction.runWriteCommandAction(project, () ->
{
document.replaceString(0, document.getTextLength(), formatted);
PsiDocumentManager.getInstance(project).commitDocument(document);
}
);
}
}
0
1 comment

Please see com.intellij.sh.formatter.ShExternalFormatter in IJ Community sources as a reference implementation on how to interact with external formatter. Please note that com.intellij.psi.codeStyle.ExternalFormatProcessor is experimental API, so it's safer for you to keep Action-based approach.

0

Please sign in to leave a comment.