Eclipse CDT 插件 - 操作仅限于函数名称

Eclipse CDT plugin - action restricted to function name

目前我正在为 Eclipse CDT 开发一个插件。我已经在我的 plugin.xml 文件中成功地做出了行动声明。

<extension
     point="org.eclipse.ui.popupMenus">
  <objectContribution
        id="MyOwnPlugin.contribution1"
        nameFilter="*.c"
        objectClass="org.eclipse.ui.IEditorInput">
     <action
           class="myownplugin.popup.actions.DoTestsAction"
           enablesFor="1"
           id="myownplugin.doTests"
           label="Do Tests"
           menubarPath="additions">
     </action>
  </objectContribution>
</extension>

当我右键单击编辑器时,这成功声明了一个弹出操作,我可以 select 该操作。

然而,我想要实现的是只有当我右键单击函数 name/function 声明时才会出现该操作。有没有办法实现这一目标?我一直在尝试 filter XML 标签在 plugin.xml 中,但没有成功。

谢谢。

我自己没有尝试过,但我相信你想要的是可行的(模数评论中描述的点击位置与插入符号位置问题)。使用 <filter> 元素是在正确的轨道上,但还需要其他一些部分才能使其正常工作。


首先要意识到上下文菜单属于 对象 ,对于编辑器的上下文菜单,该对象是 IEditorInput 代表编辑器选项卡的内容。

任何使上下文菜单操作的存在依赖于某些条件的机制,都只会将该对象用作输入。因此,条件必须基于对象的状态(仅)。这就是为什么我们可以将其基于插入符位置而不是点击本身的位置:"the current caret position in the editor" 是 IEditorInput 状态的一部分,但 "the location of the current click within the editor" 不是(我知道的).


<filter>元素的documentation表示:

This element is used to evaluate the attribute state of each object in the current selection. A match only if each object in the selection has the specified attribute state. Each object in the selection must implement, or adapt to, org.eclipse.ui.IActionFilter.

这里讨论 "selection" 的原因是,在某些视图中,可以调用上下文菜单并选择多个对象(例如,在 Project Explorer 视图中,选择多个文件/文件夹)。在不适用的编辑器上下文中; "selection" 中只有一个对象,类型为 IEditorInput.

不幸的是,IEditorInput 没有实现 IActionFilter。但是,它确实实现了 IAdaptable,因此我们可以使用 adapter mechanism 让我们的插件支持将其适应 IActionFilter

这将涉及向您的 plugin.xml:

添加这样的内容
  <extension point="org.eclipse.core.runtime.adapters">
     <factory 
        class="your.plugin.EditorInputAdapterFactory" 
        adaptableType="org.eclipse.ui.IEditorInput">
        <adapter type="org.eclipse.ui.IActionFilter"/>
     </factory>
  </extension>

其中 your.plugin.EditorInputAdapterFactory 是您将在插件中编写的类型。它的实现看起来像这样:

public class EditorInputAdapterFactory implements IAdapterFactory {
    @Override
    public <T> T getAdapter(Object adaptable, Class<T> adapterType) {
        if (adaptable instanceof IEditorInput && adapterType.equals(IActionFilter.class)) {
            return new EditorInputActionFilter((IEditorInput) adaptable);
        }
        return null;
    }
}

其中 EditorInputActionFilter 是我们将要编写的类型。


好的,现在我们有了一个与 IEditorInput 对象一起使用的动作过滤器,使我们能够使用 <filter> 元素。

<filter> 元素使用 "attribute name" 和 "attribute value",它们将被传递给 IActionFilter。作为动作过滤器的作者,我们可以发明这些。例如,我们可以发明一个名为 selectedElementType 的属性名称(其中 "selected element" 我指的是插入符号当前结束的 C++ 元素的类型),以及一个名为 function.[=59 的值=]

那么我们的过滤器声明将如下所示:

<filter name="selectedElementType" value="function" />

最后,我们需要实现我们的操作过滤器,以便它评估我们为 IEditorInput 对象定义的 属性。我不会在这里写出完整的实现,但概括地说:

  • 使用 CDTUITools.getWorkingCopyManager()IEditorInput 映射到 IWorkingCopy,实现 ITranslationUnit
  • 获取编辑器的当前插入符位置,使用类似 CUIPlugin.getActivePage().findEditor(editorInput).getEditorSite().getSelectionProvider().getSelection() 的方法(中间进行适当的空值检查)。可能有一种更简单的方法可以做到这一点,但这就是我想到的。由于您在编辑器中,返回的选择应具有类型 ITextSelection.
  • 使用 SharedASTJob 访问编辑器的共享 AST (IASTTranslationUnit)。请注意,您需要阻塞作业,并且操作过滤器将(我假设)在 UI 线程上调用,这并不理想。 (更多内容见下文。)
  • 使用 IASTTranslationUnit.getNodeSelector(null).findEnclosingName(offset, length),加上 ITextSelection 的偏移量和长度,得到一个 IASTName 表示插入符号下的名称(如果有的话)。
  • 使用IASTName.resolveBinding()获取名称引用的绑定(C++语义模型对象)。
  • 检查绑定是否实现 IFunction

所有这些都将用于您的 IActionFilter.testAttribute() 实施。该函数的 target 参数将是 IEditorInput。为了更好地衡量,您应该在执行任何此操作(最初,您的动作过滤器只会被你的 <filter> 元素调用,所以它们总是匹配的,但你可以想象在未来扩展这种机制,例如支持其他选定的元素类型。)


最后,关于性能的说明:您在这里所做的是调节 UI 元素(弹出窗口的外观)对 属性 的 C++ 代码的响应能力,它可以解析和分析速度慢。这必然意味着您的弹出窗口可能需要更长的时间才能显示(这反映在您的操作过滤器需要在 SharedASTJob 上阻止)。通过使用 SharedASTJob,您可以通过重新使用已经解析的 AST(如果有的话)来最小化这种影响,但是例如如果您刚刚打开一个编辑器并单击鼠标右键,并且初始 AST 需要几秒钟的时间来构建,那么您的弹出窗口将需要几秒钟的时间才能显示出来。买者自负。