Share via


How to: Implement a Library That Supports the Call Browser Tool

The Call Browser tool enables you to view the methods contained in Visual Studio projects or external .NET Framework components. There are two hierarchical tree views, Call and Callers graphs, that display the caller/callee relationships between the methods.

The Call graph is the hierarchical view of methods in which each child node is a method that is called by the parent method. The Callers graph is the hierarchical view of methods in which each child node is a method that calls the parent method.

To display the methods in the Call Browser views, you must implement a library that tracks and exposes the lists of symbols to the Visual Studio object manager. The library is described by the IVsSimpleLibrary2 interface. The lists of symbols provided by the library are exposed to the object manager through the IVsSimpleObjectList2 interface.

The object manager organizes the symbols by sorting, grouping and caching some of the data. When the Call Browser is first invoked, or when the user expands the nodes in the Call or Callers graphs, the object manager requests the library to provide new lists of symbols. Some lists are reused by the Visual Studio object manager if they are still valid. A library may not manufacture a new list for every request. Instead, it may provide lists that have been already created. After obtaining the lists, the object manager populates the graphs with the new data.

The object manager refreshes the Call Browser views when it detects changes in the content of the library or the lists of symbols. For more information, see How to: Detect Changes in Lists of Symbols and Cause an Update of the Call Browser Tool. The same approach is used in populating and refreshing the views of other symbol-browsing tools, such as Class View, Object Browser, or Find Symbol. The libraries supporting these tools contain the symbols, such as namespaces, classes, structures, and other language elements, and expose them to the Visual Studio object manager through the same interfaces as the Call Browser. A single library may track both project and global symbols that are appropriate for displaying in one or several symbol-browsing tools.

After the library registers with the Visual Studio object manager, the object manager obtains the information about the library capabilities. It collects the information on the library flags to determine which tools the library supports. It also determines the categories that the library supports. The supported categories are specified in the LIB_CATEGORY enumeration and include member types, member access, visibility, and other categories. Knowing the capabilities of the libraries helps the object manager to select an appropriate library when the data request comes from a specific symbol-browsing tool.

Note

The following managed code examples demonstrate how to implement a library that supports the Call Browser tool by utilizing IVsSimpleLibrary2 and IVsSimpleObjectList2 interfaces. All symbols in the library are methods contained in a single component or multiple components, such as managed assemblies. The object manager collects the information about the capabilities of the library and uses the obtained data to populate the Call Browser tool.

To implement a native code symbol provider, use the IVsLibrary2 and IVsObjectList2 interfaces.

Implementing a Library that Supports the Call Browser

To implement a library that supports the Call Browser

  1. Get information on the library flags by implementing the GetLibFlags2 method.

    The method returns a combination of the _LIB_FLAGS2 flags. This information is saved and used by the object manager to identify an appropriate library in response to the symbol-browsing tool request for new data. In the following example the returned LF_SUPPORTSCALLBROWSER flag identifies the library as a library that provides the Call Browser information.

    ' The library supports Call Browser.
    Public Function GetLibFlags2(ByRef pfFlags As UInteger) As Integer
        pfFlags = CInt(Fix(_LIB_FLAGS2.LF_SUPPORTSCALLBROWSER))
        Return Microsoft.VisualStudio.VSConstants.S_OK
    End Function
    
    // The library supports Call Browser.
    public int GetLibFlags2(out uint pfFlags)
    {
        pfFlags = (int)_LIB_FLAGS2.LF_SUPPORTSCALLBROWSER;
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
  2. Get information on the categories that the library supports by implementing the GetSupportedCategoryFields2 method. The following example demonstrates how the library tracks the symbols by type, access, and visibility categories.

    Public Function GetSupportedCategoryFields2(ByVal category As Integer, ByRef pCatField As UInteger) As Integer
        pCatField = 0
    
        Select Case category
            Case CInt(Fix(LIB_CATEGORY.LC_MEMBERTYPE))
                pCatField = CUInt(_LIBCAT_MEMBERTYPE.LCMT_METHOD)
    
            Case CInt(Fix(LIB_CATEGORY.LC_MEMBERACCESS))
                pCatField = CUInt(_LIBCAT_MEMBERACCESS.LCMA_PUBLIC) Or CUInt(_LIBCAT_MEMBERACCESS.LCMA_PRIVATE) Or CUInt(_LIBCAT_MEMBERACCESS.LCMA_PROTECTED) Or CUInt(_LIBCAT_MEMBERACCESS.LCMA_PACKAGE) Or CUInt(_LIBCAT_MEMBERACCESS.LCMA_FRIEND) Or CUInt(_LIBCAT_MEMBERACCESS.LCMA_SEALED)
    
            Case CInt(Fix(LIB_CATEGORY.LC_LISTTYPE))
                pCatField = CUInt(_LIB_LISTTYPE.LLT_MEMBERS)
    
            Case CInt(Fix(LIB_CATEGORY.LC_VISIBILITY))
                pCatField = CUInt(_LIBCAT_VISIBILITY.LCV_VISIBLE Or _LIBCAT_VISIBILITY.LCV_HIDDEN)
    
            Case Else
                pCatField = CUInt(0)
                Return Microsoft.VisualStudio.VSConstants.E_FAIL
        End Select
    
    public int GetSupportedCategoryFields2(int category, out uint pCatField)
    {
        pCatField = 0;
    
        switch (category)
        {
            case (int)LIB_CATEGORY.LC_MEMBERTYPE:
                pCatField = (uint)_LIBCAT_MEMBERTYPE.LCMT_METHOD;
                break;
    
            case (int)LIB_CATEGORY.LC_MEMBERACCESS:
                pCatField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PUBLIC |
                            (uint)_LIBCAT_MEMBERACCESS.LCMA_PRIVATE |
                            (uint)_LIBCAT_MEMBERACCESS.LCMA_PROTECTED |
                            (uint)_LIBCAT_MEMBERACCESS.LCMA_PACKAGE |
                            (uint)_LIBCAT_MEMBERACCESS.LCMA_FRIEND |
                            (uint)_LIBCAT_MEMBERACCESS.LCMA_SEALED;
                break;
    
            case (int)LIB_CATEGORY.LC_LISTTYPE:
                pCatField = (uint)_LIB_LISTTYPE.LLT_MEMBERS;
                break;
    
            case (int)LIB_CATEGORY.LC_VISIBILITY:
                pCatField = (uint)(_LIBCAT_VISIBILITY.LCV_VISIBLE |
                                    _LIBCAT_VISIBILITY.LCV_HIDDEN);
                break;
    
            default:
                pCatField = (uint)0;
                return Microsoft.VisualStudio.VSConstants.E_FAIL;
    }
    
  3. Get the top-level list of symbols by implementing the GetList2 method. This method performs the following important functions:

    • Determines the type of the list to manufacture based on the search criteria.

      If the search criterion is CALLSFROM, the library provides a list of symbols to be viewed in the Call graph. If the search criterion is CALLSTO, the library provides a list of symbols for the Callers graph. The initial view shows a complete list of all methods contained in the library. This list is generated with the search criteria set to both, CALLSTO and CALLSFROM flags.

    • Exposes the manufactured lists to the object manager through the IVsSimpleObjectList2 interface.

    The following example demonstrates how to manufacture Call and Callers lists and provide these lists to the object manager.

    Public Function GetList2(ByVal listType As UInteger, ByVal flags As UInteger, ByVal pobSrch As VSOBSEARCHCRITERIA2(), ByRef ppList As IVsSimpleObjectList2) As Integer
        ppList = Nothing
    
        Dim strSearchCriteria As String = pobSrch(0).szName
        Dim grfOptions As UInteger = pobSrch(0).grfOptions
        Dim NavInfo As Microsoft.VisualStudio.Shell.Interop.IVsNavInfo = pobSrch(0).pIVsNavInfo
    
        ' Return generated list of symbols to the object manager.
        Dim resultsList As ResultsList = New RootMethodsList(Me, grfOptions)
        ppList = CType(resultsList, Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2)
        Dim strFullNameFromNavInfo As String
    
        If (CUInt(grfOptions And CUInt(Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSFROM)) > 0) AndAlso (CUInt(grfOptions And CUInt(Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSTO)) > 0) Then
            ' Initial view with VSOBSO_CALLSFROM and VSOBSO_CALLSTO flags set simultaneously.
            ' Generate list of all methods in the container.
    
            For Each [call] As CallInstance In m_CallGraph
                resultsList.AddMethod([call].m_Source)
                resultsList.AddMethod([call].m_Target)
            Next [call]
    
            ' Generate CALLFROM list for Call graph.
        ElseIf CUInt(grfOptions And CUInt(Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSFROM)) > 0 Then
            Dim Calls As System.Collections.Generic.List(Of CallInstance) = Nothing
    
            If Not NavInfo Is Nothing Then
                strFullNameFromNavInfo = CallBrowserNavInfo.GetFullNameFromNavInfo(NavInfo)
                Calls = m_CallGraph.GetCallGraph(strFullNameFromNavInfo)
            ElseIf strSearchCriteria.Length > 0 Then
                Calls = m_CallGraph.GetCallGraph(strSearchCriteria)
            End If
    
            For i As Integer = 0 To Calls.Count - 1
                Dim method As Method = Calls(i).m_Source
                resultsList.AddMethod(method)
            Next i
            ' Generate CALLTO list for Callers graph.
    
        ElseIf CUInt(grfOptions And CUInt(Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSTO)) > 0 Then
            Dim Callers As System.Collections.Generic.List(Of CallInstance) = Nothing ' = new System.Collections.Generic.List(Of CallInstance)
    
            If Not NavInfo Is Nothing Then
                strFullNameFromNavInfo = CallBrowserNavInfo.GetFullNameFromNavInfo(NavInfo)
                Callers = m_CallGraph.GetCallersGraph(strFullNameFromNavInfo)
            ElseIf strSearchCriteria.Length > 0 Then
                Callers = m_CallGraph.GetCallersGraph(strSearchCriteria)
            End If
    
            For i As Integer = 0 To Callers.Count - 1
                Dim method As Method = Callers(i).m_Target
                resultsList.AddMethod(method)
            Next i
        End If
    
        Return Microsoft.VisualStudio.VSConstants.S_OK
    End Function
    
    public int GetList2(uint listType, uint flags, VSOBSEARCHCRITERIA2[] pobSrch, out IVsSimpleObjectList2 ppList)
    {
        ppList = null;
    
        string strSearchCriteria = pobSrch[0].szName;
        uint grfOptions = pobSrch[0].grfOptions;
        Microsoft.VisualStudio.Shell.Interop.IVsNavInfo NavInfo = pobSrch[0].pIVsNavInfo;
    
        // Return generated list of symbols to the object manager.
        ResultsList resultsList = new RootMethodsList(this, grfOptions);
        ppList = (Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2)(resultsList);
        string strFullNameFromNavInfo;
    
        if (((uint)(grfOptions & (uint)Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSFROM) > 0) &&
            ((uint)(grfOptions & (uint)Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSTO) > 0))
        {
            // Initial view with VSOBSO_CALLSFROM and VSOBSO_CALLSTO flags set simultaneously.
            // Generate list of all methods in the container.
    
            foreach (CallInstance call in m_CallGraph)
            {
                resultsList.AddMethod(call.m_Source);
                resultsList.AddMethod(call.m_Target);
            }
    
        }
        // Generate CALLFROM list for Call graph.
        else if ((uint)(grfOptions & (uint)Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSFROM) > 0)
        {
            System.Collections.Generic.List<CallInstance> Calls = null;
    
            if (NavInfo != null)
            {
                strFullNameFromNavInfo = CallBrowserNavInfo.GetFullNameFromNavInfo(NavInfo);
                Calls = m_CallGraph.GetCallGraph(strFullNameFromNavInfo);
            }
            else if (strSearchCriteria.Length > 0)
            {
                Calls = m_CallGraph.GetCallGraph(strSearchCriteria);
            }
    
            for (int i=0; i < Calls.Count; i+)
            {
                Method method = Calls[i].m_Source;
                resultsList.AddMethod(method);
            }
        }
        // Generate CALLTO list for Callers graph.
    
        else if ((uint)(grfOptions & (uint)Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSTO) > 0)
        {
            System.Collections.Generic.List<CallInstance> Callers = null; // = new System.Collections.Generic.List<CallInstance>();
    
            if (NavInfo != null)
            {
                strFullNameFromNavInfo = CallBrowserNavInfo.GetFullNameFromNavInfo(NavInfo);
                Callers = m_CallGraph.GetCallersGraph(strFullNameFromNavInfo);
            }
            else if (strSearchCriteria.Length > 0)
            {
                Callers = m_CallGraph.GetCallersGraph(strSearchCriteria);
            }
    
            for (int i=0; i < Callers.Count; i+)
            {
                Method method = Callers[i].m_Target;
                resultsList.AddMethod(method);
            }
        }
    
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    

See Also

Tasks

How to: Register a Library with the Object Manager

How to: Expose Lists of Symbols Provided by the Library to the Object Manager

How to: Detect Changes in Lists of Symbols and Cause an Update of the Call Browser Tool

How to: Identify Symbols in a Library

Concepts

Supporting Symbol-Browsing Tools

Other Resources

Language Services