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 需要几秒钟的时间来构建,那么您的弹出窗口将需要几秒钟的时间才能显示出来。买者自负。
目前我正在为 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 需要几秒钟的时间来构建,那么您的弹出窗口将需要几秒钟的时间才能显示出来。买者自负。