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

时间:2014-02-24 20:35:18

标签: c# visual-studio-2010 visual-studio visual-studio-addins languageservice

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

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

1 个答案:

答案 0 :(得分:5)

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

  1. 右键单击Class View中的节点。
  2. 在文本编辑器中右键单击。
  3. 其他包括:

    1. 呼叫层次结构
    2. 入门

      在理想的实现中,您将拥有IVsSimpleLibrary2的实现,它将对您的语言的支持集成到类视图和对象浏览器窗口中。 Find All References的实现围绕Visual Studio提供的IVsFindSymbol接口。您的代码处理IVsSimpleLibrary2.GetList2

      实现中的相关搜索

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

      1. 确保您的图书馆功能包括_LIB_FLAGS2.LF_SUPPORTSLISTREFERENCES

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

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

      4. 支持文本编辑器命令

        1. ViewFilter.QueryCommandStatus实施中,guidCmdGroup == VSConstants.GUID_VSStandardCommandSet97nCmdId == VSStd97CmdID.FindReferences时需要返回OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED

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

          HandleFindReferences();
          return true;
          
        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));
              }
          }
          
        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);
          }
          
        5. 更新IVsSimpleLibrary2.GetList2的实施。当搜索条件的dwCustom值设置为FindReferencesResults,而不是计算类视图或对象浏览器节点上的查找所有引用命令的结果时,您只需返回{ {3}}包含以前由HandleFindReferencesResponse方法计算的结果。