在Visual Studio 2010语言服务中实现查找引用

Jon*_*yna 2 c# visual-studio-addins visual-studio-2010 visual-studio languageservice

我正在为自定义脚本语言实现Visual Studio语言服务.我已设法实现语法突出显示,错误检查,代码完成和"转到定义".我无法弄清楚如何挂钩"查找所有引用"菜单选项(或者甚至让它在此时显示).

有人能指出我在Visual Studio中为自定义语言实现"查找所有引用"功能的有用资源吗? 我已经尝试使用Google搜索有关它的任何信息,但我似乎找不到任何东西.

Sam*_*ell 5

首先,有多个位置可以调用查找所有引用.主要的是:

  1. 右键单击"类视图"中的节点.
  2. 在文本编辑器中右键单击.

其他包括:

  1. 调用层次结构

入门

在理想的实现中,您将有一个实现,IVsSimpleLibrary2它将对您的语言的支持集成到类视图和对象浏览器窗口中.Find All References的实现IVsFindSymbol以Visual Studio提供的界面为中心.您的代码处理执行中的相关搜索IVsSimpleLibrary2.GetList2.

支持在"类视图"中右键单击节点

  1. 确保您的库功能包括_LIB_FLAGS2.LF_SUPPORTSLISTREFERENCES.

  2. 在您的处理程序中IVsSimpleLibrary2.GetList2,您感兴趣的是满足以下所有条件的情况.

    1. pobSrch是一个长度为1的非null数组.我假设第一个元素是criteria为这些条件的其余部分分配给局部变量的.
    2. criteria.eSrchType == VSOBSEARCHTYPE.SO_ENTIREWORD
    3. criteria.grfOptions 有旗帜 _VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS
    4. criteria.grfOptions 有旗帜 _VSOBSEARCHOPTIONS.VSOBSO_CASESENSITIVE
  3. 满足上述条件时,返回IVsSimpleObjectList2其子项是"查找所有引用"命令的延迟计算结果的实现.

支持文本编辑器命令

  1. 在您的ViewFilter.QueryCommandStatus实现中,当guidCmdGroup == VSConstants.GUID_VSStandardCommandSet97nCmdId == VSStd97CmdID.FindReferences你需要返回OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED.

    • 在Visual Studio 2005中,注意nCmdIdVSStd2KCmdID.FindReferences,但guidCmdGroup如前面提到的将是相同的.从Visual Studio 2008开始纠正此不匹配,之后VSStd2KCmdID.FindReferences不再使用该点.
  2. 覆盖ViewFilter.HandlePreExec上面列出的命令GUID和ID的情况,并为该情况执行以下代码:

    HandleFindReferences();
    return true;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加以下扩展方法类:

    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));
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 将以下方法添加到您的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);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 更新您的实施IVsSimpleLibrary2.GetList2.当搜索条件的dwCustom值设置为FindReferencesResults,而不是计算"类视图"或"对象浏览器"节点上的"查找所有引用"命令的结果时,您只需返回一个IVsSimpleObjectList2包装先前由您的HandleFindReferencesResponse方法计算的结果.