Achèvement de membre dans un Service de langage héritéMember Completion in a Legacy Language Service

La saisie semi-automatique IntelliSense membre est une info-bulle qui affiche une liste de membres possibles d’une étendue particulière comme une classe, une structure, une énumération ou une espace de noms.The IntelliSense Member Completion is a tool tip that displays a list of possible members of a particular scope such as a class, structure, enumeration, or namespace. Par exemple, en c#, si l’utilisateur tape « this » suivi d’un point, une liste de tous les membres de la classe ou structure dans l’étendue actuelle est présentée dans une liste à partir de laquelle l’utilisateur peut sélectionner.For example, in C#, if the user types "this" followed by a period, a list of all members of the class or structure at the current scope is presented in a list from which the user can select.

Managed package framework (MPF) fournit la prise en charge pour l’info-bulle et la gestion de la liste dans l’info-bulle ; tout ce qui est nécessaire est coopération à partir de l’analyseur pour fournir les données qui apparaissent dans la liste.The managed package framework (MPF) provides support for the tool tip and managing the list in the tool tip; all that is needed is cooperation from the parser to supply the data that appears in the list.

Les services de langage hérité sont implémentés en tant que partie d’un VSPackage, mais la plus récente pour implémenter des fonctionnalités de service de langage consiste à utiliser des extensions MEF.Legacy language services are implemented as part of a VSPackage, but the newer way to implement language service features is to use MEF extensions. Pour plus d’informations, consultez étendre l’éditeur et les Services de langage.To find out more, see Extending the Editor and Language Services.

Note

Nous vous recommandons de commencer à utiliser l’API de l’éditeur de nouveau dès que possible.We recommend that you begin to use the new editor API as soon as possible. Cela améliorer les performances de votre service de langage et vous permettent de tirer parti des nouvelles fonctionnalités de l’éditeur.This will improve the performance of your language service and let you take advantage of new editor features.

Son fonctionnementHow It Works

Voici deux façons dans lequel une liste de membres est affichée à l’aide des classes MPF :The following are the two ways in which a member list is shown using the MPF classes:

  • Le point d’insertion de positionnement sur un identificateur ou après un caractère de terminaison membre et en sélectionnant liste des membres à partir de la IntelliSense menu.Positioning the caret on an identifier or after a member completion character and selecting List Members from the IntelliSense menu.

  • Le IScanner analyseur détecte un caractère de terminaison membre et définit un déclencheur d’émission de jeton de TokenTriggers pour ce caractère.The IScanner scanner detects a member completion character and sets a token trigger of TokenTriggers for that character.

    Un caractère de terminaison membre indique qu’un membre d’une classe, une structure ou une énumération consiste à suivre.A member completion character indicates that a member of a class, structure, or enumeration is to follow. Par exemple, en c# ou Visual Basic, le caractère de fin de membre est une ., tandis que dans C++ le caractère est un . ou ->.For example, in C# or Visual Basic the member completion character is a ., while in C++ the character is either a . or a ->. La valeur de déclencheur est définie lorsque le caractère de sélection de membre est analysé.The trigger value is set when the member select character is scanned.

La commande de la liste des membres IntelliSenseThe IntelliSense Member List Command

Le VSConstants.VSStd2KCmdID commande lance un appel à la Completion méthode sur le Source classe et le Completion (méthode), à son tour, appelle le ParseSource Analyseur de méthode avec le motif de l’analyse de ParseReason.The VSConstants.VSStd2KCmdID command initiates a call to the Completion method on the Source class and the Completion method, in turn, calls the ParseSource method parser with the parse reason of ParseReason.

L’analyseur détermine le contexte de la position actuelle, ainsi que le jeton sous ou immédiatement avant la position actuelle.The parser determines the context of the current position as well as the token under or immediately before the current position. En fonction de ce jeton, une liste de déclarations est présentée.Based on this token, a list of declarations is presented. Par exemple, en c#, si vous placez le point d’insertion sur un membre de classe, puis sélectionnez liste des membres, vous obtenez une liste de tous les membres de la classe.For example, in C#, if you position the caret on a class member and select List Members, you get a list of all members of the class. Si vous placez le signe insertion après une période qui suit une variable objet, vous obtenez une liste de tous les membres de la classe qui représente l’objet.If you position the caret after a period that follows an object variable, you get a list of all members of the class that object represents. Notez que si le point d’insertion est placé sur un membre lorsque la liste des membres est affichée, sélectionnez un membre dans la liste remplace le membre le signe insertion sur avec celle de la liste.Note that if the caret is positioned on a member when the member list is shown, selecting a member from the list replaces the member the caret is on with the one in the list.

Le déclencheur de jetonThe Token Trigger

Le TokenTriggers déclencheur lance un appel à la Completion méthode sur le Source classe et le Completion (méthode), appelle à son tour, l’analyseur avec le motif de l’analyse de ParseReason (si le déclencheur de jeton est également inclus les TokenTriggers indicateur, la raison de l’analyse est ParseReason qui combine la sélection de membres et la mise en surbrillance des accolades).The TokenTriggers trigger initiates a call to the Completion method on the Source class and the Completion method, in turn, calls the parser with the parse reason of ParseReason (if the token trigger also included the TokenTriggers flag, the parse reason is ParseReason which combines member selection and brace highlighting).

L’analyseur détermine le contexte de l’actuelle positionner ainsi que ce qui a été tapé avant le membre sélectionner caractère.The parser determines the context of the current position as well as what has been typed before the member select character. À partir de ces informations, l’analyseur crée une liste de tous les membres de l’étendue demandée.From this information, the parser creates a list of all members of the requested scope. Cette liste de déclarations est stockée dans le AuthoringScope objet qui est retourné à partir de la ParseSource (méthode).This list of declarations is stored in the AuthoringScope object that is returned from the ParseSource method. Si toutes les déclarations sont retournées, l’info-bulle Saisie semi-automatique de membre s’affiche.If any declarations are returned, the member completion tool tip is displayed. L’info-bulle est géré par une instance de la CompletionSet classe.The tool tip is managed by an instance of the CompletionSet class.

L’activation de la prise en charge pour l’exécution de membreEnabling Support for Member Completion

Vous devez avoir le CodeSense entrée de Registre est définie sur 1 pour prendre en charge toute opération IntelliSense.You must have the CodeSense registry entry set to 1 to support any IntelliSense operation. Cette entrée de Registre peut être définie avec un paramètre nommé passé à la ProvideLanguageServiceAttribute attribut associé au package de langue de l’utilisateur.This registry entry can be set with a named parameter passed to the ProvideLanguageServiceAttribute user attribute associated with the language package. Les classes de service de langage de lire la valeur de cette entrée de Registre à partir de la EnableCodeSense propriété sur la LanguagePreferences classe.The language service classes read the value of this registry entry from the EnableCodeSense property on the LanguagePreferences class.

Si votre scanneur retourne le jeton déclencheur de TokenTriggers, votre analyseur renvoie une liste de déclarations, puis la liste de saisie semi-automatique du membre s’affiche.If your scanner returns the token trigger of TokenTriggers, and your parser returns a list of declarations, then the member completion list is displayed.

Prise en charge de la saisie semi-automatique des membres dans l’analyseurSupporting Member Completion in the Scanner

Le moteur d’analyse doit être en mesure de détecter un caractère de terminaison de membres et définir le déclencheur d’émission de jeton de TokenTriggers lorsque ce caractère est analysé.The scanner must be able to detect a member completion character and set the token trigger of TokenTriggers when that character is parsed.

ExempleExample

Voici un exemple simplifié de détecter le caractère de fin de membre et de configuration approprié TokenTriggers indicateur.Here is a simplified example of detecting the member completion character and setting the appropriate TokenTriggers flag. Cet exemple est à titre d’illustration uniquement.This example is for illustrative purposes only. Il suppose que votre scanneur contient une méthode GetNextToken qui identifie et retourne les jetons à partir d’une ligne de texte.It assumes that your scanner contains a method GetNextToken that identifies and returns tokens from a line of text. L’exemple de code définit simplement le déclencheur lorsqu’il détecte le type de caractère correct.The example code simply sets the trigger whenever it sees the right kind of character.

using Microsoft.VisualStudio.Package;  
using Microsoft.VisualStudio.TextManager.Interop;  

namespace TestLanguagePackage  
{  
    public class TestScanner : IScanner  
    {  
        private Lexer lex;  
        private const char memberSelectChar = '.';  

        public bool ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo,  
                                                   ref int state)  
        {  
            bool foundToken = false  
            string token = lex.GetNextToken();  
            if (token != null)  
            {  
                foundToken = true;  
                char c = token[0];  
                if (c == memberSelectChar)  
                {  
                        tokenInfo.Trigger |= TokenTriggers.MemberSelect;  
                }  
            }  
            return foundToken;  
        }  
    }  
}  

Prise en charge d’achèvement de membre dans l’analyseurSupporting Member Completion in the Parser

Fin de membre, le Source classe appelle la GetDeclarations (méthode).For member completion, the Source class calls the GetDeclarations method. Vous devez implémenter la liste dans une classe dérivée de la Declarations classe.You must implement the list in a class that is derived from the Declarations class. Consultez la Declarations classe pour plus d’informations sur les méthodes que vous devez implémenter.See the Declarations class for details about the methods you must implement.

L’analyseur est appelée avec ParseReason ou ParseReason quand un caractère de sélection de membre est tapé.The parser is called with ParseReason or ParseReason when a member select character is typed. L’emplacement donné le ParseRequest objet est immédiatement après le membre Sélectionnez caractère.The location given in the ParseRequest object is immediately after the member select character. L’analyseur doit collecter les noms de tous les membres qui peuvent apparaître dans une liste de membres à ce moment précis dans le code source.The parser must collect the names of all members that can appear in a member list at that particular point in the source code. Puis, l’analyseur doit analyser la ligne actuelle pour déterminer la portée de que l’utilisateur veut associé au caractère de sélection de membre.Then the parser must parse the current line to determine the scope the user wants associated with the member select character.

Cette étendue est basée sur le type de l’identificateur avant le membre sélectionner caractère.This scope is based on the type of the identifier before the member select character. Par exemple, en c#, étant donné la variable membre languageService qui a un type de LanguageService, en tapant languageService.For example, in C#, given the member variable languageService that has a type of LanguageService, typing languageService. génère une liste de tous les membres de la LanguageService classe.produces a list of all the members of the LanguageService class. Également dans c#, en tapant cela.Also in C#, typing this. génère une liste de tous les membres de la classe dans l’étendue actuelle.produces a list of all the members of the class in the current scope.

ExempleExample

L’exemple suivant montre une façon de remplir un Declarations liste.The following example shows one way to populate a Declarations list. Ce code suppose que l’analyseur construit une déclaration et l’ajoute à la liste en appelant un AddDeclaration méthode sur la TestAuthoringScope classe.This code assumes that the parser constructs a declaration and adds it to the list by calling an AddDeclaration method on the TestAuthoringScope class.

using System.Collections;  
using Microsoft.VisualStudio.Package;  
using Microsoft.VisualStudio.TextManager.Interop;  

namespace TestLanguagePackage  
{  
    internal class TestDeclaration  
    {  
        public string Name;            // Name of declaration  
        public int     TypeImageIndex; // Glyph index  
        public string Description;     // Description of declaration  

        public TestDeclaration(string name, int typeImageIndex, string description)  
        {  
            this.Name = name;  
            this.TypeImageIndex = typeImageIndex;  
            this.Description = description;  
        }  
    }  

    //===================================================  
    internal class TestDeclarations : Declarations  
    {  
        private ArrayList declarations;  

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

        public void AddDeclaration(TestDeclaration declaration)  
        {  
            declarations.Add(declaration);  
        }  

        //////////////////////////////////////////////////////////////////////  
        // Declarations of class methods that must be implemented.  
        public override int GetCount()  
        {  
            // Return the number of declarations to show.  
            return declarations.Count;  
        }  

        public override string GetDescription(int index)  
        {  
            // Return the description of the specified item.  
            string description = "";  
            if (index >= 0 && index < declarations.Count)  
            {  
                description = ((TestDeclaration)declarations[index]).Description;  
            }  
            return description;  
        }  

        public override string GetDisplayText(int index)  
        {  
            // Determine what is displayed in the tool tip list.  
            string text = null;  
            if (index >= 0 && index < declarations.Count)  
            {  
                text = ((TestDeclaration)declarations[index]).Name;  
            }  
            return text;  
        }  

        public override int GetGlyph(int index)  
        {  
            // Return index of image to display next to the display text.  
            int imageIndex = -1;  
            if (index >= 0 && index < declarations.Count)  
            {  
                imageIndex = ((TestDeclaration)declarations[index]).TypeImageIndex;  
            }  
            return imageIndex;  
        }  

        public override string GetName(int index)  
        {  
            string name = null;  
            if (index >= 0 && index < declarations.Count)  
            {  
                name = ((TestDeclaration)declarations[index]).Name;  
            }  
            return name;  
        }  
    }  

    //===================================================  
    public class TestAuthoringScope : AuthoringScope  
    {  
        private TestDeclarations declarationsList;  

        public void AddDeclaration(TestDeclaration declaration)  
        {  
            if (declaration != null)  
            {  
                if (declarationsList == null)  
                {  
                    declarationsList = new TestDeclarations();  
                }  
                declarationsList.AddDeclaration(declaration);  
            }  
        }  

        public override Declarations GetDeclarations(IVsTextView view,  
                                                     int line,  
                                                     int col,  
                                                     TokenInfo info,  
                                                     ParseReason reason)  
        {  
            return declarationsList;  
        }  

        /////////////////////////////////////////////////  
        // Remainder of AuthoringScope methods not shown.  
        /////////////////////////////////////////////////  
    }  

    //===================================================  
    class TestLanguageService : LanguageService  
    {  
        public override AuthoringScope ParseSource(ParseRequest req)  
        {  
            TestAuthoringScope scope = new TestAuthoringScope();  
            if (req.Reason == ParseReason.MemberSelect ||  
                req.Reason == ParseReason.MemberSelectAndHighlightBraces)  
            {  
                // Gather list of declarations based on what the user  
                // has typed so far. In this example, this list is an array of  
                // MemberDeclaration objects (a helper class you might implement  
                // to hold member declarations).  
                // How this list is gathered is dependent on the parser  
                // and is not shown here.  
                MemberDeclarations memberDeclarations;  
                memberDeclarations = GetDeclarationsForScope();  

                // Now populate the Declarations list in the authoring scope.  
                // GetImageIndexBasedOnType() is a helper method you  
                // might implement to convert a member type to an index into  
                // the image list returned from the language service.  
                foreach (MemberDeclaration dec in memberDeclarations)  
                {  
                    scope.AddDeclaration(new TestDeclaration(  
                                             dec.Name,  
                                             GetImageIndexBasedOnType(dec.Type),  
                                             dec.Description));  
                }  
            }  
            return scope;  
        }  
    }  
}