throwing exceptions with runProcessWithProgressSynchronously

My plugin is working, but after I export it and then run it, I get a lot of exceptions in the console.

I think this is because I have put my plugins logic into ProgressManager.getInstance().runProcessWithProgressSynchronously
https://github.com/jedierikb/p5Minimizer/blob/master/org/mediamods/p5minimizer/P5Mini.java#L56

Any suggestions how to remedy this situation?

10:55:27 PM Throwable
            Access is allowed from event dispatch thread only.
            Details: Current thread: Thread[ApplicationImpl pooled thread 8 [WriteAccessToken],4,Idea Thread Group] 1671797594
            Our dispatch thread:Thread[AWT-EventQueue-1 12.0.2#IC-123.123, eap:false,6,Idea Thread Group] 239887136
            SystemEventQueueThread: Thread[AWT-EventQueue-1 12.0.2#IC-123.123, eap:false,6,Idea Thread Group] 239887136
10:55:27 PM Throwable
            Access is allowed from event dispatch thread only.
            Details: Current thread: Thread[ApplicationImpl pooled thread 8 [WriteAccessToken],4,Idea Thread Group] 1671797594
            Our dispatch thread:Thread[AWT-EventQueue-1 12.0.2#IC-123.123, eap:false,6,Idea Thread Group] 239887136
            SystemEventQueueThread: Thread[AWT-EventQueue-1 12.0.2#IC-123.123, eap:false,6,Idea Thread Group] 239887136
10:55:27 PM Throwable
            Write access is allowed from event dispatch thread only
            Details: Current thread: Thread[ApplicationImpl pooled thread 8 [WriteAccessToken],4,Idea Thread Group] 1671797594
            Our dispatch thread:Thread[AWT-EventQueue-1 12.0.2#IC-123.123, eap:false,6,Idea Thread Group] 239887136
0
13 comments

Your code now runs in pooled thread and thus has no write access. Please see http://confluence.jetbrains.net/display/IDEADEV/IntelliJ+IDEA+Architectural+Overview#IntelliJIDEAArchitecturalOverview-Threading for explanation and sample code.

0
Avatar
Permanently deleted user

Okay, I read the page, and googled for some examples and came up with this:

 ProgressManager.getInstance().runProcessWithProgressSynchronously( new Runnable()
 { public void run()
  { ApplicationManager.getApplication().runWriteAction(new Runnable()
    { public void run( )
      { doMinify(psiFile);
      }
    });
  }
 }, "Doing some P5 Minifying", true, psiFile.getProject() );



which sadly does not work...

I appreciate your help.
0
Avatar
Permanently deleted user

You still trying to execute write action from a pooled thread. It must be called from the EDT instead:

ProgressManager.getInstance().runProcessWithProgressSynchronously( new Runnable()
{ public void run()
  { UIUtil.invokeLaterIfNecessary(new Runnable()
    { public void run() {
        ApplicationManager.getApplication().runWriteAction(new Runnable()
        { public void run( )
          { doMinify(psiFile); }
        });
    }}});
}, "Doing some P5 Minifying", true, psiFile.getProject() );


Denis

0
Avatar
Permanently deleted user

Thanks Denis

Unfortunately, this change results in the whole UI becoming unresponsive and no progress dialog. :-/

I used
UIUtil.invokeLaterIfNeeded

As
UIUtil.invokeLaterIfNecessary was not available.

Any other suggestions?  Much appreciated as I continue to get my bearings with the conventions and idioms of plugin in development.

0
Avatar
Permanently deleted user

Sorry, I was incorrect about UIUtil.invokeLaterIfNecessary() - right way is to use UIUtil.invokeLaterIfNeeded().

Generally, you should avoid executing heavy operations from EDT, so, you should design your processing in a way that it performs heavy operations which doesn't require write access at background thread and then perform fast modification from EDT. It's hard to provide more details as we don't know what happens inside your doMinify() method.

Denis

0
Avatar
Permanently deleted user

Is this helpful?

https://github.com/jedierikb/p5Minimizer/blob/master/org/mediamods/p5minimizer/P5Mini.java

i am changing many class names, method names, and variable names in a java file.

0
Avatar
Permanently deleted user

Will try to arrange time to check the code at the weekends. Not 100% sure that I'll succeed though

Denis

0
Avatar
Permanently deleted user

Hello,

Checked the plugin and here is what I see so far:

  1. You execute Refactoring.findUsages() from EDT though it's contract explicitly defines the following: 'This method should be best invoked in the process with progress and it does all the lengthy code analysis operations'. Conslusion: that logic should be moved to background thread which is executed under progress;
  2. Every Refactoring.doRefactoring() operation starts new command and write action internally. That is expensive and also birngs an inconvenience that it's not possible to cancel all changes by a single 'undo' operation, i.e. 'undo' step is registered for every 'doRefactoring()';
  3. You set 'e.getPresentation().setEnabled(false)' inside actionPerformed(). That is totally wrong. AnAction.update() should be used instead;
  4. Tried to execute the plugin against swing JTable class and got a number of exceptions like below
    [ 366706]  ERROR - name.RenameJavaMethodProcessor - Cannot modify compiled element  com.intellij.util.IncorrectOperationException: Cannot modify compiled element
     at com.intellij.psi.impl.compiled.ClsElementImpl.replace(ClsElementImpl.java:141)
     at com.intellij.psi.impl.PsiImplUtil.setName(PsiImplUtil.java:430)
     at com.intellij.psi.impl.compiled.ClsMemberImpl.setName(ClsMemberImpl.java:71)
     at com.intellij.refactoring.rename.RenameJavaMethodProcessor.findCollisions(RenameJavaMethodProcessor.java:177)
     at com.intellij.refactoring.rename.RenameUtil.findUsages(RenameUtil.java:83)
     at com.intellij.refactoring.rename.RenameProcessor.findUsages(RenameProcessor.java:271)
     at com.intellij.refactoring.RefactoringImpl.findUsages(RefactoringImpl.java:48)
     at org.mediamods.p5minimizer.P5Mini.minimizeClass(P5Mini.java:167)
     at org.mediamods.p5minimizer.P5Mini.doMinify(P5Mini.java:100)
     at org.mediamods.p5minimizer.P5Mini.actionPerformed(P5Mini.java:43)

    Not sure about it's origins, will ask our refactoring guys to have a look here


So, the general idea is to do all preparatory work at background thread under progress and then execute all actual refactoring inside a sinle command and write action. Will ask our refactoring guys an advise about the latest as well.

Denis

0

4. You must had added the cls element to be renamed which cannot be performed as library code should not be modified. Seems that the action should be disabled out of project content FileIndex.inContent or on element instantsof ClsElement

0
Avatar
Permanently deleted user

Denis -- Your help and advice is much appreciated.  Still having some trouble getting this plugin running in the background however.

> So, the general idea is to do all preparatory work at background thread under progress and then execute all actual refactoring inside a sinle command and write action.

I understand the plan here, but am not sure how to implement it.  Still working my way through your links, so hopefully something will click for me soon.

I am wondering if there is a small sample project which takes your approach?  It would be very helpful to me and maybe others?

Hereafter are some comments on your points:

1.
In an earlier version of the code, I wrapped all of doMinify inside of a Progress:

ProgressManager.getInstance().runProcessWithProgressSynchronously( new Runnable() {

  public void run() {

    doMinify( psiFile );

  }   

}, "Doing some P5 Minifying", true, psiFile.getProject() );



But this code led to whole application  becoming completely unresponsive.

2.
Okay, so I collect all of the findUsages() into a list and then batch them all at once.
I am unsure, however, how to do this because I use the same instance of RenameRefactoring to both findUsages and to doRefactoring.  

RenameRefactoring renameClass = rf.createRename( psiClass, classNama.getNextName(), true, true );

 UsageInfo[] ui = renameClass.findUsages();

 try

 { renameClass.doRefactoring( ui );

 }

 catch (IncorrectOperationException ex)

 { ex.printStackTrace();

 }



Can an instance of RenameRefactoring's doRefactoring be passed an aggregate UsageInfo[] from different RenameRefactoring instances?

3.
This bit of code was taken, boilerplate, from here:
http://www.youtube.com/watch?feature=player_embedded&v=-ZmQD6Fr6KE#t=746s

But I see it gets removed later in the webinar, so I will re-review and modify.
0
Avatar
Permanently deleted user
  1. You shouldn't run a separate background task for each 'doMinify()'. Single task which performs all 'findUsages()' should be used instead;
  2. Not sure about that at the moment, asked Anna for an advice (she is our refactoring guru);

And no, I'm afraid there is no sample project which illustrates that approach yet. However, yours can be the one when finish here :)

Denis

0

If you simply call renameRefactoring.run() it will wrap find usages with progress and doRefactoring with command and write action. It would also resolve/search for conflicts etc. Though invoked from write action it would be invoked later. Actually it is the best way to use refactoring processors if you are not sure that you need smth else. Hopefully this does help

0
Avatar
Permanently deleted user

So, our advice for running all refactoring tasks as a single operation is to create a custom method which follows the same principle as com.intellij.refactoring.BaseRefactoringProcessor#run() but performs multiple refactorings instead of a single one.

Denis

0

Please sign in to leave a comment.