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.

0
14 comments
Avatar
Permanently deleted user

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
Avatar
Permanently deleted user

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
Avatar
Permanently deleted user

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
Avatar
Permanently deleted user

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
Avatar
Permanently deleted user

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
Avatar
Permanently deleted user

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
Avatar
Permanently deleted user

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
Avatar
Permanently deleted user

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

Denis

0
Avatar
Konstantin Bulenkov

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
Avatar
Permanently deleted user

Thanks.
Its working this way.

0

@...
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
Avatar
Permanently deleted user

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

@...
It doesn't work with recent versions of Intellij IDEA such version 2019.1.2

@...

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
Avatar
Permanently deleted user

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.