Partager via


How to: Get a List of Installed Code Snippets

A VSPackage-based language service provides the support for inserting code snippets into a source buffer. A code snippet is a piece of code that can be inserted into the source buffer either with a menu command (which allows choosing among a list of installed code snippets) or by selecting a snippet shortcut from an IntelliSense completion list.

This topic discusses the problem of retrieving a list of code snippets for a particular language so the shortcuts for those snippets can be inserted into an IntelliSense completion list. The approach discussed here is basically a single method, written in Visual C#, that retrieves all code snippets for a specific language GUID. However, the approach is general enough that it can be adapted to any language.

See Supporting Code Snippets (Managed Package Framework) for details on how code snippets are implemented in a managed package framework (MPF) language service.

Retrieving a List of Code Snippets

  • The following method shows how to retrieve a list of code snippets given a language GUID. The results are stored in an array of VsExpansion structures. This method uses the MPF GetGlobalService method to obtain the IVsTextManager interface from the SVsTextManager service. However, you can also use the service provider given to your VSPackage and call the QueryService method.

    using System;
    using System.Collections;
    using Microsoft.VisualStudio.Package;
    using Microsoft.VisualStudio.TextManager.Interop;
    
    namespace MyLanguagePackage
    {
        class MyLanguageService : LanguageService
        {
            private void GetSnippets(Guid languageGuid,
                                     ref ArrayList expansionsList)
            {
                IVsTextManager textManager = (IVsTextManager)GetGlobalService(typeof(SVsTextManager));
                if (textManager != null)
                {
                    IVsTextManager2 textManager2 = (IVsTextManager2)textManager;
                    if (textManager2 != null)
                    {
                        IVsExpansionManager expansionManager = null;
                        textManager2.GetExpansionManager(out expansionManager);
                        if (expansionManager != null)
                        {
                            // Tell the environment to fetch all of our snippets.
                            IVsExpansionEnumeration expansionEnumerator = null;
                            expansionManager.EnumerateExpansions(languageGuid,
                                                                 0,     // return all info
                                                                 null,    // return all types
                                                                 0,     // return all types
                                                                 1,     // include snippets without types
                                                                 0,     // do not include duplicates
                                                                 out expansionEnumerator);
                            if (expansionEnumerator != null)
                            {
                                // Cache our expansions in an array of
                                // VSExpansion structures.
                                uint count   = 0;
                                uint fetched = 0;
                                VsExpansion expansionInfo = new VsExpansion();
                                IntPtr[] pExpansionInfo   = new IntPtr[1];
    
                                // Allocate enough memory for one VSExpansion structure.
                                // This memory is filled in by the Next method.
                                pExpansionInfo[0] = Marshal.AllocCoTaskMem(
                                                               Marshal.SizeOf(expansionInfo));
    
                                expansionEnumerator.GetCount(out count);
                                for (uint i = 0; i < count; i++)
                                {
                                    expansionEnumerator.Next(1, pExpansionInfo, out fetched);
                                    if (fetched > 0)
                                    {
                                        // Convert the returned blob of data into a
                                        // structure that can be read in managed code.
                                        expansionInfo = (VsExpansion)
                                                        Marshal.PtrToStructure(pExpansionInfo[0],
                                                                               typeof(VsExpansion));
    
                                        if (!String.IsNullOrEmpty(expansionInfo.shortcut))
                                        {
                                            expansionsList.Add(expansionInfo);
                                        }
                                    }
                                }
                                Marshal.FreeCoTaskMem(pExpansionInfo[0]);
                            }
                        }
                    }
                }
            }
        }
    }
    

Calling the GetSnippets method

  • The following method shows one way to call the GetSnippets method described in the "Retrieving a List of Code Snippets" procedure. This call is shown in the context of an MPF language service. The OnParseComplete method is called when a parsing operation is completed that was started with the reason Check.

    Notes

    The expansionsList array is cached for performance reasons. This does mean, however, that any changes to the snippets on the machine are not reflected in the list until this language service is stopped and reloaded (which is most easily done by stopping and restarting Visual Studio).

    namespace MyLanguagePackage
    {
        class MyLanguageService : LanguageService
        {
            private ArrayList expansionList;
    
            public override void OnParseComplete(ParseRequest req)
            {
                if (this.expansionsList == null)
                {
                    this.expansionsList = new ArrayList();
                    GetSnippets(this.GetLanguageServiceGuid(),
                                ref this.expansionsList);
                }
            }
        }
    }
    

Using the Array of Snippet Information

  • The following method shows one way in which the array of snippet information retrieved by the GetSnippets method (described in the "Retrieving a List of Code Snippets" procedure) is used. The AddSnippets method (shown here) should be called from within the parser in response to any parse reason that is used to fill a completion list and in which code snippets can apply (for example, a member completion list should not show code snippets). Such reasons occur after the Check parse reason is run for the first time.

    The MyAuthoringScope object implements the AuthoringScope class (an MPF class). The AddDeclaration method is custom to the MyAuthoringScope class and builds a list of declarations that is later displayed in a completion list.

    The MyDeclaration class is the basis of the declarations list in the MyAuthoringScope class. The MyDeclaration class contains all the information that can be displayed in a completion list as well as the type of declaration (used to determine an icon to display, for example). In this case, the type of declaration for a code snippet is a string: "snippet".

    namespace MyLanguagePackage
    {
        class MyLanguageService : LanguageService
        {
            private ArrayList expansionList;
    
            internal void AddSnippets(ref MyAuthoringScope scope)
            {
                if (this.expansionsList != null && this.expansionsList.Count > 0)
                {
                    int count = this.expansionsList.Count;
                    for (int i = 0; i < count; i++)
                    {
                        VsExpansion expansionInfo = (VsExpansion)this.expansionsList[i];
                        scope.AddDeclaration(
                            new MyDeclaration("",
                                  expansionInfo.shortcut,
                                  expansionInfo.title,
                                  "snippet",
                                  expansionInfo.description
                                )
                        );
                    }
                }
            }
        }
    }
    

See Also

Concepts

Supporting Code Snippets (Managed Package Framework)