我正在为自定义脚本语言实现Visual Studio语言服务。我已设法实现语法突出显示,错误检查,代码完成和“转到定义”。我无法弄清楚如何挂钩“查找所有引用”菜单选项(或者甚至让它在此时显示)。
有人能指出我在Visual Studio中为自定义语言实现“查找所有引用”功能的有用资源吗?我已经尝试使用Google搜索有关它的任何信息,但我不能似乎找不到任何东西。
答案 0 :(得分:5)
首先,有多个位置可以调用查找所有引用。主要的是:
其他包括:
在理想的实现中,您将拥有IVsSimpleLibrary2
的实现,它将对您的语言的支持集成到类视图和对象浏览器窗口中。 Find All References的实现围绕Visual Studio提供的IVsFindSymbol
接口。您的代码处理IVsSimpleLibrary2.GetList2
。
确保您的图书馆功能包括_LIB_FLAGS2.LF_SUPPORTSLISTREFERENCES
。
在IVsSimpleLibrary2.GetList2
的处理程序中,您感兴趣的是满足以下所有条件的情况。
pobSrch
是长度为1的非空数组。我假设第一个元素在其余条件下分配给局部变量criteria
。criteria.eSrchType == VSOBSEARCHTYPE.SO_ENTIREWORD
criteria.grfOptions
的旗帜为_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS
criteria.grfOptions
的旗帜为_VSOBSEARCHOPTIONS.VSOBSO_CASESENSITIVE
满足上述条件时,返回IVsSimpleObjectList2
实现,其子项是“查找所有引用”命令的延迟计算结果。
在ViewFilter.QueryCommandStatus
实施中,guidCmdGroup == VSConstants.GUID_VSStandardCommandSet97
和nCmdId == VSStd97CmdID.FindReferences
时需要返回OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED
。
nCmdId
将为VSStd2KCmdID.FindReferences
,但guidCmdGroup
将与之前提到的相同。从Visual Studio 2008开始纠正了这种不匹配,之后不再使用VSStd2KCmdID.FindReferences
。对于上面列出的命令GUID和ID的情况覆盖ViewFilter.HandlePreExec
,并针对该情况执行以下代码:
HandleFindReferences();
return true;
添加以下扩展方法类:
public static class IVsFindSymbolExtensions
{
public static void DoSearch(this IVsFindSymbol findSymbol, Guid symbolScope, VSOBSEARCHCRITERIA2 criteria)
{
if (findSymbol == null)
throw new ArgumentNullException("findSymbol");
VSOBSEARCHCRITERIA2[] criteriaArray = { criteria };
ErrorHandler.ThrowOnFailure(findSymbol.DoSearch(ref symbolScope, criteriaArray));
}
}
将以下方法添加到ViewFilter
班级:
public virtual void HandleFindReferences()
{
int line;
int col;
// Get the caret position
ErrorHandler.ThrowOnFailure( TextView.GetCaretPos( out line, out col ) );
// Get the tip text at that location.
Source.BeginParse(line, col, new TokenInfo(), ParseReason.Autos, TextView, HandleFindReferencesResponse);
}
// this can be any constant value, it's just used in the next step.
public const int FindReferencesResults = 100;
void HandleFindReferencesResponse( ParseRequest req )
{
if ( req == null )
return;
// make sure the caret hasn't moved
int line;
int col;
ErrorHandler.ThrowOnFailure( TextView.GetCaretPos( out line, out col ) );
if ( req.Line != line || req.Col != col )
return;
IVsFindSymbol findSymbol = CodeWindowManager.LanguageService.GetService(typeof(SVsObjectSearch)) as IVsFindSymbol;
if ( findSymbol == null )
return;
// TODO: calculate references as an IEnumerable<IVsSimpleObjectList2>
// TODO: set the results on the IVsSimpleLibrary2 (used as described below)
VSOBSEARCHCRITERIA2 criteria =
new VSOBSEARCHCRITERIA2()
{
dwCustom = FindReferencesResults,
eSrchType = VSOBSEARCHTYPE.SO_ENTIREWORD,
grfOptions = (uint)_VSOBSEARCHOPTIONS2.VSOBSO_LISTREFERENCES,
pIVsNavInfo = null,
szName = "Find All References"
};
findSymbol.DoSearch(new Guid(SymbolScopeGuids80.All), criteria);
}
更新IVsSimpleLibrary2.GetList2
的实施。当搜索条件的dwCustom
值设置为FindReferencesResults
,而不是计算类视图或对象浏览器节点上的查找所有引用命令的结果时,您只需返回{ {3}}包含以前由HandleFindReferencesResponse
方法计算的结果。