# Detecting source of AnAction declare in plugin.xml

**URL:** <https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557>\
**Category:** IntelliJ Platform\
**Created:** [February 17, 2025, 7:53pm UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557 "2025-02-17T19:53:04Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jeremibg](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@jeremibg](https://platform.jetbrains.com/u/jeremibg)\
**Post date:** [February 17, 2025, 7:53pm UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/1 "2025-02-17T19:53:04Z")

</div>

I have this in my `plugin.xml`:

```xml
    <action id="foo.invoke"
            class="foo.bar.MyInvokeAction"
            icon="/icons/pluginIcon.svg">
      <keyboard-shortcut first-keystroke="ctrl I" keymap="$default" replace-all="true"/>
      <add-to-group group-id="Floating.CodeToolbar" anchor="first"/>
    </action>

```

And this as my action:

```kotlin
object MyInvokeAction : EditorAction(InvokeHandler()) {
  const val ACTION_ID: String = "foo.invoke"

  class InvokeHandler : EditorWriteActionHandler() {
    override fun executeWriteAction(editor: Editor, caret: Caret?, dataContext: DataContext?) {
      val project = editor.project ?: return
      MyManager.invoke("source") // TODO: how to adapt the 'source' ?
    }
  }
}

```

I would like to be able to know what caused the `executeWriteAction` to be called.  
How do I programmatically figure out if it was the button clicked from the `Floating.CodeToolbar`, or the `Ctrl+I` shortcut?

---

<div class="post-metadata">

**Author:** ![yann.cebron](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/yann.cebron/32/15_2.png) [@yann.cebron](https://platform.jetbrains.com/u/yann.cebron)\
**Post date:** [February 18, 2025, 10:48am UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/3 "2025-02-18T10:48:00Z")

</div>

Never use `object` for anything registered in the platform, but always `class`. See [Configuring Kotlin Support | IntelliJ Platform Plugin SDK](https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#object-vs-class)

---

<div class="post-metadata">

**Author:** ![yann.cebron](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/yann.cebron/32/15_2.png) [@yann.cebron](https://platform.jetbrains.com/u/yann.cebron)\
**Post date:** [February 18, 2025, 10:52am UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/4 "2025-02-18T10:52:27Z")

</div>

You can query context specific data from `dataContext`, see `com.intellij.openapi.actionSystem.CommonDataKeys` and others.

Not sure it’s possible to capture these two specific contexts, why do you need to distinguish them?

---

<div class="post-metadata">

**Author:** ![jeremibg](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@jeremibg](https://platform.jetbrains.com/u/jeremibg)\
**Post date:** [February 18, 2025, 3:25pm UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/6 "2025-02-18T15:25:40Z")

</div>

I’ll fix my `object` usage, thanks for pointing that out.  
But just being curious here: what is the repercussion of using `object` there? The documentation mentions there are exceptions where this is ok, so I’m slightly confused. My action has been working fine, so it’s unclear why this is a necessary change.

And regarding the `DataContext`, I see nothing in `CommonDataKeys` that would be relevant to derive the value I’m looking for.

> why do you need to distinguish them?

It’s for the purpose of telemetry. I want to be determine how often people use the CodeToolbar as an entry-point, versus how often people use the shortcut. Eventually, we will have even more entry-points, and it’s important for us to know which ones are actually being used.

---

<div class="post-metadata">

**Author:** ![yann.cebron](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/yann.cebron/32/15_2.png) [@yann.cebron](https://platform.jetbrains.com/u/yann.cebron)\
**Post date:** [February 18, 2025, 3:30pm UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/7 "2025-02-18T15:30:45Z")

</div>

About `object`: all entities registered in `plugin.xml` are fully managed by the platform. Using `object` effectively prevents that, also Actions must be state-less.

For telemetry, you might want to try `com.intellij.openapi.actionSystem.AnActionEvent#getPlace` and the various `AnActionEvent#isFrom....()` methods.

---

<div class="post-metadata">

**Author:** ![jeremibg](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@jeremibg](https://platform.jetbrains.com/u/jeremibg)\
**Post date:** [February 18, 2025, 3:36pm UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/8 "2025-02-18T15:36:11Z")

</div>

By the way, regarding the `object`, it was setup this way because of this button we create which allows users to open the KeyMap for the Action so that they can quickly edit it.

```kotlin
  private fun createShortcutBtn(): JButton {
    val invokeActionId = MyInvokeAction.ACTION_ID
    val btnTxt = getShortcutBtnTxt(invokeActionId)
    val btn = JButton(btnTxt, PluginIcons.SETTINGS)

    // opening the Keymap preferences with the shortcut for the invoke action selected
    btn.addActionListener {
      val editKeymapsDialog = EditKeymapsDialog(project, invokeActionId)
      if (editKeymapsDialog.configurable == null) {
        return@addActionListener
      }
      AppUIUtil.invokeOnEdt {
        val modified = editKeymapsDialog.showAndGet()
        if (modified) {
          btn.text = getShortcutBtnTxt(invokeActionId)
        }
      }
    }

    return btn
  }

```

It seems like having the `ACTION_ID` available as a “`static`” variable makes the most sense semantically speaking since it is indeed a property associated with the action, rather than something specific to each separate instance.

---

<div class="post-metadata">

**Author:** ![yann.cebron](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/yann.cebron/32/15_2.png) [@yann.cebron](https://platform.jetbrains.com/u/yann.cebron)\
**Post date:** [February 19, 2025, 8:48am UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/9 "2025-02-19T08:48:31Z")

</div>

Yes, the `ACTION_ID` field can be exposed as static constant.

---

<div class="post-metadata">

**Author:** ![jeremibg](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@jeremibg](https://platform.jetbrains.com/u/jeremibg)\
**Post date:** [February 19, 2025, 3:44pm UTC](https://platform.jetbrains.com/t/detecting-source-of-anaction-declare-in-plugin-xml/557/10 "2025-02-19T15:44:16Z")

</div>

The best I could figure out is this, which seems to be working fine:

```auto
class MyInvokeAction : EditorAction(InvokeHandler()) {

  override fun update(e: AnActionEvent) {
    lastPlace = e.place
    super.update(e)
  }

  class InvokeHandler : EditorWriteActionHandler() {
    override fun executeWriteAction(editor: Editor, caret: Caret?, dataContext: DataContext?) {
      val project = editor.project ?: return
      MyManager.invoke(lastPlace)
    }
  }

  companion object {
    const val ACTION_ID: String = "foo.invoke"
    /** Used in logging to know where the action was invoked from */
    private var lastPlace: String = "unknown"
  }
}

```

Thanks!
