我自己没有尝试过,但我相信你想要的是可行的(以评论中描述的点击位置与插入符号位置问题为模)。您在使用该<filter>
元素方面走在了正确的轨道上,但还需要其他一些部件才能使其正常工作。
首先要意识到上下文菜单与对象有关,在编辑器上下文菜单的情况下,该对象IEditorInput
代表编辑器选项卡的内容。
任何使上下文菜单动作的存在依赖于某些条件的机制,都只会将该对象用作输入。因此,条件必须基于对象的状态(仅)。这就是为什么我们可以基于插入符号位置而不是单击本身的位置:“编辑器中的当前插入符号位置”是状态的一部分IEditorInput
,但“编辑器中当前单击的位置”是从来没听说过)。
该元素的文档说:<filter>
此元素用于评估当前选择中每个对象的属性状态。A match only if each object in the selection has the specified attribute state. 选择中的每个对象都必须实现或适应,org.eclipse.ui.IActionFilter
。
这里谈论“选择”的原因是,在某些视图中,可以在选择多个对象的情况下调用上下文菜单(例如,在项目资源管理器视图中,选择多个文件/文件夹)。在不适用的编辑器上下文中;“选择”中只有一个对象,类型为IEditorInput
。
不幸的是,IEditorInput
没有实现IActionFilter
. 但是,它确实实现IAdaptable
了 ,因此我们可以使用适配器机制让我们的插件支持将其适配到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>
whereyour.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>
元素使用“属性名称”和“属性值”,它们将被传递给IActionFilter
. 作为动作过滤器的作者,我们可以发明这些。例如,我们可以发明一个名为的属性名称selectedElementType
(其中“选定元素”是指插入符号当前所在的 C++ 元素的类型)和一个名为function
.
然后我们的过滤器声明将如下所示:
<filter name="selectedElementType" value="function" />
最后,我们需要实现我们的动作过滤器,以便它评估我们为IEditorInput
对象定义的属性。我不会在这里写出完整的实现,但概括地说:
- 用于
CDTUITools.getWorkingCopyManager()
将 映射IEditorInput
到IWorkingCopy
实现ITranslationUnit
.
- 获取编辑器当前插入符号的位置,使用类似的东西
CUIPlugin.getActivePage().findEditor(editorInput).getEditorSite().getSelectionProvider().getSelection()
(中间有适当的空检查)。可能有一种更简单的方法可以做到这一点,但这就是我想到的。由于您在编辑器中,因此返回的选择应该具有 type ITextSelection
。
- 用于
SharedASTJob
访问编辑器的共享 AST ( IASTTranslationUnit
)。请注意,您需要阻止作业,并且(我假设)将在 UI 线程上调用操作过滤器,这并不理想。(更多内容如下。)
- 使用
IASTTranslationUnit.getNodeSelector(null).findEnclosingName(offset, length)
, 与 , 的偏移量和长度ITextSelection
一起获得IASTName
插入符号下的代表名称(如果有)。
- 用于
IASTName.resolveBinding()
获取名称所指的绑定(C++ 语义模型对象)。
- 检查绑定是否实现
IFunction
。
所有这些都将用于您的IActionFilter.testAttribute()
. 该target
函数的参数将是IEditorInput
. 为了更好地衡量,您应该在执行任何操作之前检查name
andvalue
参数是否与您发明的属性名称 ( selectedElementType
and function
) 相对应(最初,您的操作过滤器只会由您的<filter>
元素调用,因此它们将始终匹配,但您可以想象一下将来扩展这种机制以支持其他选定的元素类型。)
最后,关于性能的说明:您在这里所做的是将 UI 元素的响应能力(弹出窗口的外观)调整为 C++ 代码的属性,这可能会很慢地解析和分析。这必然意味着您的弹出窗口可能需要更长的时间才能显示出来(这反映在您需要阻止的操作过滤器中SharedASTJob
)。通过使用SharedASTJob
,您可以通过重新使用已经解析的 AST(如果有的话)来最小化这种影响,但是例如,如果您刚刚打开一个编辑器并右键单击,并且初始 AST 需要几秒钟来构建,您的弹出窗口将需要几秒钟才能显示。买者自负。