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
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; }
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; }
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