Реализация поиска ссылок в языковой службе Visual Studio 2010

Я реализую языковой сервис Visual Studio для пользовательского языка сценариев. Мне удалось реализовать подсветку синтаксиса, проверку ошибок, завершение кода и "Перейти к определению". У меня возникают проблемы с выяснением того, как подключиться к пункту меню "Найти все ссылки" (или даже заставить его отображаться в данный момент).

Может кто-нибудь указать мне полезный ресурс для реализации функциональности "Найти все ссылки" в Visual Studio для пользовательского языка? Я пробовал поискать в Google любую информацию, но не могу ничего найти.

1 ответ

Решение

Прежде всего, есть несколько мест, где можно найти все ссылки. Основные из них:

  1. Правым щелчком мыши по узлу в представлении классов.
  2. Щелкнув правой кнопкой мыши в текстовом редакторе.

Другие включают в себя:

  1. Иерархия вызовов

Начиная

В идеальной реализации у вас будет реализация IVsSimpleLibrary2 который интегрирует поддержку вашего языка в окнах просмотра классов и объектов. Реализация Find All References сосредоточена вокруг IVsFindSymbol интерфейс, который предоставляется Visual Studio. Ваш код обрабатывает соответствующие поиски в реализации 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 реализации, чьи потомки являются лениво вычисленными результатами команды Find All References.

Поддержка команды текстового редактора

  1. В вашем ViewFilter.QueryCommandStatus реализация, когда guidCmdGroup == VSConstants.GUID_VSStandardCommandSet97 а также nCmdId == VSStd97CmdID.FindReferences вам нужно вернуться OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED,

    • В Visual Studio 2005 обратите внимание, что nCmdId будет VSStd2KCmdID.FindReferences но guidCmdGroup будет таким же, как упоминалось ранее. Это несоответствие было исправлено начиная с Visual Studio 2008, после чего VSStd2KCmdID.FindReferences больше не использовался.
  2. Override ViewFilter.HandlePreExec для случая команды GUID и ID, перечисленных выше, и выполните следующий код для этого случая:

    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 вместо того, чтобы вычислять результаты команды Find All References на узле Class View или Object Browser, вам нужно только вернуть IVsSimpleObjectList2 который оборачивает результаты, предварительно рассчитанные вашим HandleFindReferencesResponse метод.

Другие вопросы по тегам