Intercept action for project

Answered

Hi,

I wrode a little plugin, that needs to intercept some of actions (run, debug, stop, restart). I implemented this with AnActionListener and in there I checked the actionId. This all worked well. But my logic throws errors if I have more than one project open. So I thought good. I will compare the action events project with my saved instance. This works for one project but not for the other one. I get an error saying "cannot share data context between Swing events".
This makes complete sense because I execute an action in one window, and in the other window my listener tries to excess the data context.

What is the correct way to do something like this?

I could sorround my project check with try...catch but that looks and feels dirty.

14 comments
Comment actions Permalink

Hi Manne,

You said 'I compare the action events project with my saved instance' - how you do that? Please also provide a stack trace of the exception you get.

Denis

0
Comment actions Permalink

I have a project component. I get the current project as a constructor property. I save this property in a final field in my component. The component also implement AnActionListener.
When I test my plugin with one project opened. Everything is fine. But when I open two projects and then execute an action I get the following error in one of the two plugin components. (there two at that time because of the two opened projects :))

cannot share data context between Swing events; initial event count = 4716; current event count = 4777
java.lang.Throwable
    at com.intellij.openapi.diagnostic.Logger.error(Logger.java:54)
    at com.intellij.ide.impl.DataManagerImpl$MyDataContext.getData(DataManagerImpl.java:342)
    at com.intellij.openapi.actionSystem.DataKey.getData(DataKey.java:75)
    at com.intellij.openapi.actionSystem.AnActionEvent.getData(AnActionEvent.java:139)
    at com.intellij.openapi.actionSystem.AnActionEvent.getProject(AnActionEvent.java:95)
    at de.tslarusso.MyComponent.afterActionPerformed(MyComponent.java:168)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.fireAfterActionPerformed(ActionManagerImpl.java:1065)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.processAction(IdeKeyEventDispatcher.java:610)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.d(IdeKeyEventDispatcher.java:464)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.dispatchKeyEvent(IdeKeyEventDispatcher.java:208)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:479)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:333)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

I need to compore the projects, because I want to execute some action only in the corrosponding project. This error only happens for actions that are triggered by key strokes. It works for clicks on action buttons.

Hope those information makes my problem a little bit clearer

0
Comment actions Permalink

That's not a good design because ActionManager is an application-level component. That means that when you register an action listener which is a project component itself, that project will be not eligible for gc while the application is alive, i.e. there is a memory leak.

You should declare your AnActionListener as an application-level component/service and encapsulate project-specific logic inside it instead.

Denis

0
Comment actions Permalink

I tried that also.
I created a application component, registered this component as an action listener.
But when i tried to access the project I got the same error.

I will tried this solution. Maybe I did something wrong.

0
Comment actions Permalink

I`m using an application component as action listener now. The problem still exist though. The error happens only for action triggered by keyboard shortcuts. I think that this is a general problem.
I got no errors when I`m using the

public void beforeActionPerformed( AnAction anAction, DataContext dataContext, AnActionEvent anActionEvent )
method.

What is the alternative to an actionlistener? I read that someone meantioned to subclass a given action and put the new action in that place. How should that work? Is this even possible?
As I wrode in my question, I need to intercept the debug/run configuration actions and stop/rerun actions from the console toolbar.

Thanks so far
0
Comment actions Permalink

You can try to listen not for actions but commands instead (see com.intellij.openapi.command.CommandProcessor.addCommandListener()). CommandEvent object given to a CommandListener holds a project reference explicitly.

Denis

0
Comment actions Permalink

That was a good idea. But the command name property is null for all the actions/commands
I want to intercept. This way I`m not able to distinguish between the different commands.

0
Comment actions Permalink

No good advice then. Will ask our UI guys if they have any suggestion.

Denis

0
Comment actions Permalink

Use ApplicationComponent and AnActionListener. Do all your logic in beforeActionPerformed() method, so you won't have troubles with data context sharing. Get proper project from DataContext: PlatformDataKeys.PROJECT.getData(dataContext) or event.getData(PlatformDataKeys.PROJECT)
That's it.

0
Comment actions Permalink

Thanks.
Its working this way.

0
Comment actions Permalink

Manne Endres
Please I will be very gratefull if you  give me the class's code that intercept the " run " action to get text of run window .

0
Comment actions Permalink

Eltayef Mohamed

Oh man. This was seven years ago! But you are in luck. I found my sources on github. I can't say if it still compiles though.

https://github.com/Larusso/idea_custom_logger

 

Hope this helps.

 

Cheers

1
Comment actions Permalink

Manne Endres
It doesn't work with recent versions of Intellij IDEA such version 2019.1.2

Konstantin Bulenkov

Please can you  give me the class's code that intercept the " run " action to get text of run window currently for intellij 2019

0
Comment actions Permalink

As I wrote. My initial question and solution is from 7 years ago. My repo is also not updated since. I have no more resources to give.

0

Please sign in to leave a comment.