Intercept action for project
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.
Please sign in to leave a comment.
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
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
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
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.
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.
method.I got no errors when I`m using the
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
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
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.
No good advice then. Will ask our UI guys if they have any suggestion.
Denis
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.
Thanks.
Its working this way.
@...
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 .
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
@...
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
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.