What's wrong with this code??

Hi all,

I've created an action to convert Markdown to AsciiDoc. However, whenever I run it, IntelliJ will convert the file correctly, but then, in an infinite loop, keep updating the project view.

Am I doing something crazy here, or am I missing something?

Thanks,

Erik



@Override
public void
actionPerformed(@NotNull final AnActionEvent event) {

  final PsiFile file = event.getData(DataKeys.PSI_FILE);
  final Project project = event.getProject();

  final VirtualFile virtualFile = file.getVirtualFile();

  if(project != null) {

    final Document document = PsiDocumentManager.getInstance(project).getDocument(file);

    ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(virtualFile);

    ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(document, project) {
      @Override
      public void
run() {
        CommandProcessor.getInstance().executeCommand(project, new Runnable() {
          @Override
          public void
run() {

            if (document != null) {
              try {
                String newFileName = FilenameUtils.getBaseName(file.getName()) + ".adoc";
                virtualFile.rename(this, newFileName);

                document.setText(convertMarkdownToAsciiDoc(file.getText()));
              }
              catch (IOException e) {
                e.printStackTrace();
              }
            }
          }
        }, getName(), getGroupId(), UndoConfirmationPolicy.REQUEST_CONFIRMATION);
      }
    });
  }


Attachment(s):
bug.gif
0
9 comments

I don't see right away why it would cause such consequences; this looks like a bug in the platform. As a workaround, please try changing the code to:
PsiFile newFile = (PsiFile) file.setName(newFileName)
newFile.setText(...)

0

Hi Dmitry,

Thanks for the quick reply. You mean replacing:

String newFileName = FilenameUtils.getBaseName(file.getName()) + ".adoc";
virtualFile.rename(this, newFileName);

document.setText(convertMarkdownToAsciiDoc(file.getText()));


with this:

String newFileName = FilenameUtils.getBaseName(file.getName()) + ".adoc";

PsiFile newFile = (PsiFile) file.setName(newFileName);
newFile.setText(...)


??

Because that's not possible, there is no setText method on PsiFile.

0

Yep, sorry, got confused. Here's a better solution: use PsiFileFactory.createFileFromText() to create the asciidoc file, save it to disk using PsiDirectory.add() and delete the old Markdown file.

0

I'm trying that now, but how do I get access to the PsiDirectory?

0

file.getContainingDirectory()

0

Ah, yes, that works! Thanks for your speedy help!!!

The functionality did change a bit now, because if the file is open, IntelliJ will close the file (which makes sense of course, since I just deleted it). Before this, it was just a nice inplace rename. But I think I can live with this, since it also fixes the previous issue with the Preview rendering.

Thanks again, this is really helpful!

0

So, the whole action now looks like this:

 
@Override
public void actionPerformed(@NotNull final AnActionEvent event) {

  final PsiFile file = event.getData(DataKeys.PSI_FILE);
  final Project project = event.getProject();

  if (file == null || project == null) {
    return;
  }

  final VirtualFile virtualFile = file.getVirtualFile();
  ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(virtualFile);

  ApplicationManager.getApplication().runWriteAction(new Runnable() {
    @Override
    public void
run() {
      CommandProcessor.getInstance().executeCommand(project, new Runnable() {
        @Override
        public void
run() {
          String newFileName = FilenameUtils.getBaseName(file.getName()) + "." + AsciiDocFileType.INSTANCE.getDefaultExtension();
          PsiFile asciiDocFile = PsiFileFactory.getInstance(project).createFileFromText(newFileName, AsciiDocFileType.INSTANCE, convertMarkdownToAsciiDoc(file.getText()));

          file.getContainingDirectory().add(asciiDocFile);

          try {
            virtualFile.delete(this);
          }
          catch (IOException e) {
            e.printStackTrace();
          }
        }
      }, getName(), getGroupId(), UndoConfirmationPolicy.REQUEST_CONFIRMATION);
    }
  });
}


Is that pretty much how it should be?

0

You can use PsiFile.navigate(true) to open the new file in the editor as well. Note that the PsiDirectory.add() method will return you a new PsiFile instance, and you need to call navigate() on that instance, not the one you passed in.

0

Super, I've added that too! Thanks!

0

Please sign in to leave a comment.