Partager via


Prise en charge des extraits de code (managed de package)

Un extrait est un peu de code inséré dans le fichier source. L'extrait de code lui-même est un modèle XML à un ensemble de champs. Ces champs sont mis en surbrillance après que l'extrait de code est inséré et puisse avoir des valeurs différentes selon le contexte dans lequel l'extrait de code est inséré. Juste après que l'extrait de code est inséré, le service de langage peut mettre en forme l'extrait de code.

L'extrait de code est inséré dans un mode Édition spécial qui permet aux champs de l'extrait de code à naviguer à l'aide de la touche TAB. Les champs peuvent prendre en charge les menus déroulants de style Intellisense. L'utilisateur valide l'extrait de code au fichier source en tapant la touche ENTRÉE ou Échap. Pour en savoir plus sur les extraits de code consultez Extraits de code.

Prise en charge managé du package des extraits de code

Managed package (MPF) prend en charge la plupart des fonctionnalités d'extrait de code, de lire le modèle à insérer l'extrait de code et à activer le mode Édition spécial. La prise en charge s'effectue via la classe d' ExpansionProvider .

Lorsque la classe d' Source est instanciée, la méthode d' CreateExpansionProvider dans la classe d' LanguageService est appelée pour obtenir un objet d' ExpansionProvider (notez que la classe de base d' LanguageService retourne toujours un nouvel objet d' ExpansionProvider pour chaque objet d' Source ).

Le MPF ne prend pas en charge les fonctions d'expansion. Une fonction d'expansion est une fonction nommée qui est incorporée dans un modèle d'extrait de code et retourne une ou plusieurs valeurs à placer dans un domaine. Les valeurs sont retournées par le service de langage via un objet d' ExpansionFunction . L'objet d' ExpansionFunction doit être implémenté par le service de langage pour prendre en charge des fonctions d'expansion.

Fourniture de la prise en charge pour les extraits de code

Pour activer la prise en charge des extraits de code, vous devez fournir ou installer les extraits de code et vous devez fournir les moyen à l'utilisateur insère ces extraits de code. Il existe trois étapes à activer la prise en charge des extraits de code :

  1. installer les fichiers d'extrait de code.

  2. Activer des extraits de code pour votre service de langage.

  3. appeler l'objet d' ExpansionProvider .

installer les fichiers d'extrait de code

Tous les extraits de code pour un langage sont stockés en tant que modèles dans des fichiers XML, généralement un modèle d'extrait de code par fichier. Pour plus d'informations sur le schéma XML utilisé pour les modèles d'extrait de code, consultez Référence de schéma des extraits de code. Chaque modèle d'extrait de code est marqué avec un ID de langue Cet ID de langue est spécifié dans le Registre et passe à l'attribut d' <Code> Language de la balise dans le modèle.

Il y a généralement deux emplacements dans lesquels les fichiers modèles d'extrait de code sont stockés : 1) où votre langue a été installé et 2) dans le dossier de l'utilisateur. Ces derniers sont ajoutés au Registre afin que Visual Studio Gestionnaire des extraits de code peut rechercher les extraits de code. Le dossier de l'utilisateur est où les extraits de code créés par l'utilisateur sont stockés.

La disposition classique de dossier pour les fichiers modèles installés d'extrait de code présente l'aspect suivant : [InstallRoot]\[TestLanguage]\Snippets \[LCID]\Snippets.

[InstallRoot] est le dossier que votre langage est installé dans.

[TestLanguage] est le nom de votre langage comme nom de dossier.

[LCID] est l'ID de paramètres régionaux Voici comment les versions localisées des extraits de code sont enregistrées. Par exemple, l'ID de paramètres régionaux pour l'anglais est 1033, ce [LCID] est remplacé d'ici 1033.

Un fichier supplémentaire doit être fourni et il s'agit d'un fichier d'index, un SnippetsIndex.xml généralement appelé ou un ExpansionsIndex.xml (vous pouvez utiliser toute queue valide de nom de fichier dans .xml). Ce fichier est généralement stocké dans le dossier de [InstallRoot]\[TestLanguage] et spécifie l'emplacement exact du dossier des extraits de code ainsi que de l'ID de langue et le GUID du service de langage qui utilise les extraits de code. Le chemin d'accès exact du fichier d'index est placé dans le Registre comme décrit ultérieurement « en installant les entrées du Registre ». Voici un exemple de fichier de SnippetsIndex.xml :

<?xml version="1.0" encoding="utf-8" ?>
<SnippetCollection>
    <Language Lang="Testlanguage" Guid="{b614a40a-80d9-4fac-a6ad-fc2868fff7cd}">
        <SnippetDir>
            <OnOff>On</OnOff>
            <Installed>true</Installed>
            <Locale>1033</Locale>
            <DirPath>%InstallRoot%\TestLanguage\Snippets\%LCID%\Snippets\</DirPath>
            <LocalizedName>Snippets</LocalizedName>
        </SnippetDir>
    </Language>
</SnippetCollection>

<Language> La balise spécifie l'ID de langue (l'attribut d' Lang ) et le service de langage GUID.

Cet exemple suppose que vous avez installé votre service de langage dans le dossier d'installation de Visual Studio. Le %LCID% est remplacé par l'ID actuelle des paramètres régionaux de l'utilisateur Plusieurs <SnippetDir> indicateurs peuvent être ajoutées, une pour chaque répertoire différent et des paramètres régionaux. De plus, un dossier d'extrait de code peut contenir des sous-dossiers, qui est identifié dans le fichier d'index avec <SnippetSubDir> l'indicateur qui est intégrée dans <SnippetDir> une balise.

les utilisateurs peuvent également créer leurs propres extraits de code pour votre langage. Celles-ci sont stockées en général dans le dossier des paramètres de l'utilisateur, par exemple [TestDocs]\Code Snippets \[TestLanguage]\Test Code Snippets, où [TestDocs] est l'emplacement du dossier les paramètres de l'utilisateur pour Visual Studio.

Les éléments suivants de substitution peuvent être placés dans le chemin d'accès stocké dans <DirPath> la balise dans le fichier d'index.

Élément

Description

%LCID%

ID de paramètres régionaux.

%InstallRoot%

La racine du dossier d'installation pour Visual Studio, par exemple, C : \Program Files\Microsoft Visual Studio 8.

%ProjDir%

Dossier contenant le projet actuel.

%ProjItem%

Dossier qui contient l'élément de projet en cours.

%TestDocs%

dossier dans le dossier des paramètres de l'utilisateur, par exemple, C : \Documents and Settings \[nom d'utilisateur]\My Documents\Visual Studio \ 8.

Activer des extraits de code pour votre service de langage

Vous pouvez activer des extraits de code pour votre service de langage en ajoutant l'attribut d' ProvideLanguageCodeExpansionAttribute à votre VSPackage (consultez Enregistrement d'un service de langage (managed de package) pour plus d'informations). Les paramètres d' ShowRoots et d' SearchPaths sont facultatifs, mais vous devez inclure SearchPaths nommé paramètre pour informer Gestionnaire des extraits de code de l'emplacement de vos propres extraits de code.

Voici un exemple de l'utilisation de cet attribut :

[ProvideLanguageCodeExpansion(
         typeof(TestSnippetLanguageService),
         "Test Snippet Language",          // Name of language used as registry key
         0,                               // Resource ID of localized name of language service
         "Test Snippet Language",        // Name of Language attribute in snippet template
         @"%InstallRoot%\Test Snippet Language\Snippets\%LCID%\SnippetsIndex.xml",  // Path to snippets index
         SearchPaths = @"%InstallRoot%\Test Snippet Language\Snippets\%LCID%\")]    // Path to snippets

appeler le fournisseur d'expansion

Le service de langage contrôle la mise en place de tout extrait de code, ainsi que la mise en place de méthode est appelée.

Appeler le fournisseur d'expansion pour les extraits de code

Il existe deux façons d'appeler le fournisseur de développement : à l'aide d'une commande de menu ou à l'aide d'un raccourci d'une liste de saisie semi-automatique.

Pour insérer un extrait en utilisant une commande de menu

Pour utiliser une commande de menu pour afficher le navigateur d'extrait de code, vous ajoutez une commande de menu puis appelez la méthode de DisplayExpansionBrowser dans l'interface d' ExpansionProvider en réponse à cette commande de menu.

  1. ajoutez une commande et un bouton à votre fichier de .vsct. Vous pouvez rechercher des instructions pour le faire dans Procédure pas - à - pas : Créer une commande de menu à l'aide de le modèle de package Visual Studio.

  2. Dérivez une classe de la classe d' ViewFilter et substituez la méthode d' QueryCommandStatus pour indiquer la prise en charge de la nouvelle commande de menu. Cet exemple vérifie toujours la commande de menu.

    using Microsoft.VisualStudio.Package;
    
    namespace TestLanguagePackage
    {
        class TestViewFilter : ViewFilter
        {
            public TestViewFilter(CodeWindowManager mgr, IVsTextView view)
                : base(mgr, view)
            {
            }
    
            protected override int QueryCommandStatus(ref Guid guidCmdGroup,
                                                      uint nCmdId)
            {
                int hr = base.QueryCommandStatus(ref guidCmdGroup, nCmdId);
                // If the base class did not recognize the command then
                // see if we can handle the command.
                if (hr == (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_UNKNOWNGROUP)
                {
                    if (guidCmdGroup == GuidList.guidTestLanguagePackageCmdSet)
                    {
                        if (nCmdId == PkgCmdIDList.InvokeCodeSnippetsBrowser)
                        {
                            hr = (int)(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED);
                        }
                    }
                }
                return hr;
            }
        }
    }
    
  3. Substituez la méthode d' HandlePreExec dans la classe d' ViewFilter pour obtenir l'objet d' ExpansionProvider et appeler la méthode d' DisplayExpansionBrowser sur cet objet.

    using Microsoft.VisualStudio.Package;
    
    namespace TestLanguagePackage
    {
        class TestViewFilter : ViewFilter
        {
            public override bool HandlePreExec(ref Guid guidCmdGroup,
                                               uint nCmdId,
                                               uint nCmdexecopt,
                                               IntPtr pvaIn,
                                               IntPtr pvaOut)
            {
                if (base.HandlePreExec(ref guidCmdGroup,
                                       nCmdId,
                                       nCmdexecopt,
                                       pvaIn,
                                       pvaOut))
                {
                    // Base class handled the command.  Do nothing more here.
                    return true;
                }
    
                if (guidCmdGroup == GuidList.guidTestLanguagePackageCmdSet)
                {
                    if (nCmdId == PkgCmdIDList.InvokeCodeSnippetsBrowser)
                    {
                        ExpansionProvider ep = this.GetExpansionProvider();
                        if (this.TextView != null && ep != null)
                        {
                            bool bDisplayed = ep.DisplayExpansionBrowser(
                                this.TextView,
                                "TestLanguagePackage Snippet:",
                                null,
                                false,
                                null,
                                false);
                        }
                        return true;   // Handled the command.
                    }
                }
                return false;   // Did not handle the command.
            }
        }
    }
    

    Les méthodes suivantes dans la classe d' ExpansionProvider sont appelées par Visual Studio dans l'ordre donné pendant le processus d'insérer l'extrait de code :

  4. OnItemChosen

  5. IsValidKind

  6. OnBeforeInsertion

  7. FormatSpan

  8. OnAfterInsertion

    Une fois que la méthode d' OnAfterInsertion appelée, l'extrait de code a été inséré et l'objet d' ExpansionProvider est en mode Édition spécial utilisé pour modifier un extrait de code qui vient d'être inséré.

Insérer un extrait de code à l'aide d'un raccourci

L'implémentation d'un raccourci d'une liste de saisie semi-automatique est beaucoup plus complexe qu'implémenter une commande de menu. Vous devez d'abord ajouter des raccourcis d'extrait de code à la liste de saisie semi-automatique de mot Intellisense. Vous devez détecter qu'un nom de raccourci de l'extrait de code a été inséré à la suite de la saisie semi-automatique. Enfin, vous devez obtenir le titre et le chemin d'accès d'extraits de code à l'aide de le nom de raccourci et passer ces informations à la méthode d' InsertNamedExpansion sur la méthode d' ExpansionProvider .

Pour ajouter des raccourcis d'extrait de code à la liste de saisie semi-automatique de mot, ajouter à l'objet d' Declarations dans votre classe d' AuthoringScope . Vous devez vous assurer que vous pouvez identifier le raccourci comme nom d'extrait de code. Pour obtenir un exemple, consultez Procédure pas - à - pas : Obtenir une liste des extraits de code installés (managed de package).

Vous pouvez détecter la mise en place du raccourci de l'extrait de code dans la méthode d' OnAutoComplete de classe d' Declarations . Étant donné que le nom de l'extrait de code a déjà été insérée dans le fichier source, il doit être supprimé lorsque l'expansion est insérée. La méthode d' InsertNamedExpansion prend une étendue qui décrit le point d'insertion pour l'extrait de code ; si l'étendue contient le nom entier d'extrait de code dans le fichier source, ce nom est remplacé par l'extrait de code.

Voici une version d'une classe d' Declarations qui gère l'insertion d'extraits de code donnée un nom de raccourci. D'autres méthodes dans la classe d' Declarations ont été omises pour plus de clarté. notez que le constructeur de cette classe prend un objet d' LanguageService . Cela peut être passé dans votre version de l'objet d' AuthoringScope (par exemple, votre implémentation de la classe d' AuthoringScope peut prendre l'objet d' LanguageService dans son constructeur et transmettre cet objet à votre constructeur de classe d' TestDeclarations ).

[C#]
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;

namespace TestLanguagePackage
{
    internal class TestDeclarations : Declarations
    {
        private ArrayList       declarations;
        private LanguageService languageService;
        private TextSpan        commitSpan;

        public TestDeclarations(LanguageService langService)
            : base()
        {
            languageService = langService;
            declarations = new ArrayList();
        }

        // This method is used to add declarations to the internal list.
        public void AddDeclaration(TestDeclaration declaration)
        {
            declarations.Add(declaration);
        }

        

        // This method is called to get the string to commit to the source buffer.
        // Note that the initial extent is only what the user has typed so far.
        public override string OnCommit(IVsTextView textView,
                                        string textSoFar,
                                        char commitCharacter,
                                        int index,
                                        ref TextSpan initialExtent)
        {
            // We intercept this call only to get the initial extent
            // of what was committed to the source buffer.
            commitSpan = initialExtent;

            return base.OnCommit(textView,
                                 textSoFar,
                                 commitCharacter,
                                 index,
                                 ref initialExtent);
        }

        // This method is called after the string has been committed to the source buffer.
        public override char OnAutoComplete(IVsTextView textView,
                                            string committedText,
                                            char commitCharacter,
                                            int index)
        {
            TestDeclaration item = declarations[index] as TestDeclaration;
            if (item != null)
            {
                // In this example, TestDeclaration identifies types with a string.
                // You can choose a different approach.
                if (item.Type == "snippet")
                {
                    Source src = languageService.GetSource(textView);
                    if (src != null)
                    {
                        ExpansionProvider ep = src.GetExpansionProvider();
                        if (ep != null)
                        {
                            string title;
                            string path;
                            int commitLength = commitSpan.iEndIndex - commitSpan.iStartIndex;
                            if (commitLength < committedText.Length)
                            {
                                // Replace everything that was inserted
                                // so calculate the span of the full
                                // insertion, taking into account what
                                // was inserted when the commitSpan
                                // was obtained in the first place.
                                commitSpan.iEndIndex += (committedText.Length - commitLength);
                            }

                            if (ep.FindExpansionByShortcut(textView,
                                                           committedText,
                                                           commitSpan,
                                                           true,
                                                           out title,
                                                           out path))
                            {
                                ep.InsertNamedExpansion(textView,
                                                        title,
                                                        path,
                                                        commitSpan,
                                                        false);
                            }
                        }
                    }
                }
            }
            return '\0';
        }
    }
}

Lorsque le service de langage obtient le nom de raccourci, il appelle la méthode d' FindExpansionByShortcut pour obtenir le nom de fichier et le titre d'extrait de code. Le service de langage appelle ensuite la méthode d' InsertNamedExpansion dans la classe d' ExpansionProvider pour insérer l'extrait de code. Les méthodes suivantes sont appelées par Visual Studio dans l'ordre indiqué dans la classe d' ExpansionProvider pendant le processus d'insérer l'extrait de code :

  1. IsValidKind

  2. OnBeforeInsertion

  3. FormatSpan

  4. OnAfterInsertion

Pour plus d'informations sur la façon d'obtenir une liste des extraits de code sont installés pour votre service de langage, consultez Procédure pas - à - pas : Obtenir une liste des extraits de code installés (managed de package).

implémenter la classe d'ExpansionFunction

Une fonction d'expansion est une fonction nommée qui est incorporée dans un modèle d'extrait de code et retourne une ou plusieurs valeurs à placer dans un domaine. Pour prendre en charge les fonctions d'expansion de votre service de langage, vous devez dériver une classe de la classe d' ExpansionFunction et implémenter la méthode d' GetCurrentValue . Vous devez substituer la méthode d' CreateExpansionFunction dans la classe d' LanguageService pour retourner une nouvelle instanciation de votre version de la classe d' ExpansionFunction pour chaque fonction d'expansion que vous prenez en charge. Si vous prenez en charge une liste de valeurs possibles d'une fonction de développement, vous devez également substituer la méthode d' GetIntellisenseList dans la classe d' ExpansionFunction pour retourner une liste de ces valeurs.

Une fonction de développement qui accepte les arguments ou les besoins d'accéder aux autres champs ne doivent pas être associés à un champ modifiable, comme le fournisseur d'expansion ne peut pas être entièrement initialisé avant que la fonction d'expansion soit appelée. Par conséquent, la fonction d'expansion ne peut pas obtenir la valeur de ses arguments ou un autre champ.

Exemple

Voici un exemple de la façon dont une fonction simple d'expansion appelée GetName peut être implémentée. Cette fonction d'expansion ajoute un nombre à un nom de classe de base chaque fois que la fonction d'expansion est instanciée (qui correspond à chaque fois à l'extrait de code associé est insérée).

using Microsoft.VisualStudio.Package;

namespace TestLanguagePackage
{
    public class TestLanguageService : LanguageService
    {
        private int classNameCounter = 0;

        public override ExpansionFunction CreateExpansionFunction(
            ExpansionProvider provider,
            string functionName)
        {
            ExpansionFunction function = null;
            if (functionName == "GetName")
            {
                ++classNameCounter;
                function = new TestGetNameExpansionFunction(provider, classNameCounter);
            }
            return function;
        }
    }

    internal class TestGetNameExpansionFunction : ExpansionFunction
    {
        private int nameCount;

        TestGetNameExpansionFunction(ExpansionProvider provider, int counter)
            : base(provider)
        {
            nameCount = counter;
        }

        public override string GetCurrentValue()
        {
            string name = "TestClass";
            name += nameCount.ToString();
            return name;
        }
    }
}

Voir aussi

Tâches

Procédure pas - à - pas : Obtenir une liste des extraits de code installés (managed de package)

Concepts

Enregistrement d'un service de langage (managed de package)

Autres ressources

Fonctionnalités du service de langage (managed de package)

Extraits de code